Rebased ref, commits from common ancestor: commit 43658985c8a68cf6ef53182a527f13f8288c95bf Author: Armin Le Grand <armin.le.gr...@cib.de> Date: Tue Nov 14 18:07:32 2017 +0100
RotateFlyFrame3: Made interactions work properly Have now created working interactive Rotation, Scale, Move and Crop. Using as much of the old code as possible since it does corrections based on BorderWidth/s stuff and similar. To do so, need to back-transform and execute in unrotated/ untransformed state as much as possible. Had some problems with SwVirtFlyDrawObj::NbcMove usages and hacks there, had to restructure some of these. Change-Id: Ibedf6d834f96b2f8e9c1ace2a0c984aa26cedc74 diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx index cb436581adf2..811bd390d82d 100644 --- a/sw/source/core/inc/frame.hxx +++ b/sw/source/core/inc/frame.hxx @@ -29,8 +29,8 @@ #include <svl/SfxBroadcaster.hxx> #include <o3tl/typed_flags_set.hxx> #include <IDocumentDrawModelAccess.hxx> - #include <com/sun/star/style/TabStop.hpp> +#include <basegfx/matrix/b2dhommatrix.hxx> class SwLayoutFrame; class SwRootFrame; commit 75c522ac031e3ca8fa38ffd35f2e1914f13b0772 Author: Armin Le Grand <armin.le.gr...@cib.de> Date: Tue Nov 14 18:07:32 2017 +0100 RotateFlyFrame3: Made interactions work properly Have now created working interactive Rotation, Scale, Move and Crop. Using as much of the old code as possible since it does corrections based on BorderWidth/s stuff and similar. To do so, need to back-transform and execute in unrotated/ untransformed state as much as possible. Had some problems with SwVirtFlyDrawObj::NbcMove usages and hacks there, had to restructure some of these. Change-Id: Ibedf6d834f96b2f8e9c1ace2a0c984aa26cedc74 diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx index 3971c9140da2..9432576bdcf4 100644 --- a/sw/source/core/doc/notxtfrm.cxx +++ b/sw/source/core/doc/notxtfrm.cxx @@ -473,7 +473,7 @@ const Size& SwNoTextFrame::GetSize() const void SwNoTextFrame::MakeAll(vcl::RenderContext* pRenderContext) { // RotateFlyFrame3 - inner frame. Get rotation and check if used - const double fRotation(getFrameRotation()); + const double fRotation(getLocalFrameRotation()); const bool bRotated(!basegfx::fTools::equalZero(fRotation)); if(bRotated) @@ -498,7 +498,7 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* pRenderContext) // is currently beyond scope if(pUpperFly->isTransformableSwFrame()) { - pUpperFly->getTransformableSwFrame()->resetAreaDefinitionsToUntransformed(); + pUpperFly->getTransformableSwFrame()->restoreFrameAreas(); } } @@ -508,7 +508,7 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* pRenderContext) // Reset to BoundAreas will be done below automatically if(isTransformableSwFrame()) { - getTransformableSwFrame()->resetAreaDefinitionsToUntransformed(); + getTransformableSwFrame()->restoreFrameAreas(); } } @@ -549,7 +549,7 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* pRenderContext) // upper frame, so it can bre re-created on the fly if(pUpperFly->isTransformableSwFrame()) { - pUpperFly->getTransformableSwFrame()->resetAreaDefinitionsToTransformed(); + pUpperFly->getTransformableSwFrame()->adaptFrameAreasToTransformations(); } } @@ -566,7 +566,7 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* pRenderContext) getTransformableSwFrame()->createFrameAreaTransformations( fRotation, aB2DCenter); - getTransformableSwFrame()->resetAreaDefinitionsToTransformed(); + getTransformableSwFrame()->adaptFrameAreasToTransformations(); } else { @@ -615,13 +615,13 @@ void SwNoTextFrame::transform_translate(const Point& rOffset) rOffset.X(), rOffset.Y())); // transform using TransformableSwFrame - getTransformableSwFrame()->doTransform(aTransform); + getTransformableSwFrame()->transform(aTransform); } } // RotateFlyFrame3 - inner frame // Check if we contain a SwGrfNode and get possible rotation from it -double SwNoTextFrame::getFrameRotation() const +double SwNoTextFrame::getLocalFrameRotation() const { const SwNoTextNode* pSwNoTextNode(nullptr != GetNode() ? GetNode()->GetNoTextNode() : nullptr); diff --git a/sw/source/core/draw/dflyobj.cxx b/sw/source/core/draw/dflyobj.cxx index cc12dd1baad9..e1035a3754fa 100644 --- a/sw/source/core/draw/dflyobj.cxx +++ b/sw/source/core/draw/dflyobj.cxx @@ -630,9 +630,18 @@ void SwVirtFlyDrawObj::NbcSetLogicRect(const tools::Rectangle& ) } // SwVirtFlyDrawObj::Move() and Resize() - void SwVirtFlyDrawObj::NbcMove(const Size& rSiz) { + if(GetFlyFrame()->IsFlyFreeFrame() && static_cast<SwFlyFreeFrame*>(GetFlyFrame())->isTransformableSwFrame()) + { + // When we have a change in transformed state, we need to fall back to the + // state without possible transformations. Restore FrameArea and use aOutRect + // from old FrameArea. From here, all former actions below should be fine + TransformableSwFrame* pTransformableSwFrame(static_cast<SwFlyFreeFrame*>(GetFlyFrame())->getTransformableSwFrame()); + pTransformableSwFrame->restoreFrameAreas(); + aOutRect = GetFlyFrame()->getFrameArea().SVRect(); + } + MoveRect( aOutRect, rSiz ); const Point aOldPos( GetFlyFrame()->getFrameArea().Pos() ); const Point aNewPos( aOutRect.TopLeft() ); @@ -649,7 +658,9 @@ void SwVirtFlyDrawObj::NbcMove(const Size& rSiz) //anchor must be set. Anchor and the new RelPos is calculated and //placed by the Fly itself. if( GetFlyFrame()->IsFlyAtContentFrame() ) + { static_cast<SwFlyAtContentFrame*>(GetFlyFrame())->SetAbsPos( aNewPos ); + } else { const SwFrameFormat *pTmpFormat = GetFormat(); @@ -781,34 +792,63 @@ void SwVirtFlyDrawObj::NbcCrop(const Point& rRef, const Fraction& xFact, const F { // Get Wrt Shell SwWrtShell *pSh = dynamic_cast<SwWrtShell*>( GetFlyFrame()->getRootFrame()->GetCurrShell() ); + if (!pSh) + { return; + } + + GraphicObject const *pGraphicObject = pSh->GetGraphicObj(); + + if (!pGraphicObject) + { + return; + } + + const bool bIsTransformableSwFrame( + GetFlyFrame()->IsFlyFreeFrame() && + static_cast<SwFlyFreeFrame*>(GetFlyFrame())->isTransformableSwFrame()); + + if(bIsTransformableSwFrame) + { + // When we have a change in transformed state, we need to fall back to the + // state without possible transformations. Restore FrameArea and use aOutRect + // from old FrameArea. From here, all former actions below should be fine + TransformableSwFrame* pTransformableSwFrame(static_cast<SwFlyFreeFrame*>(GetFlyFrame())->getTransformableSwFrame()); + pTransformableSwFrame->restoreFrameAreas(); + aOutRect = GetFlyFrame()->getFrameArea().SVRect(); + } // Compute old and new rect. This will give us the deformation to apply to // the object to crop - tools::Rectangle aOldRect( aOutRect ); - - const long nOldWidth = aOldRect.GetWidth(); - const long nOldHeight = aOldRect.GetHeight(); + const long nOldWidth(aOutRect.GetWidth()); + const long nOldHeight(aOutRect.GetHeight()); if (!nOldWidth || !nOldHeight) + { return; + } tools::Rectangle aNewRect( aOutRect ); ResizeRect( aNewRect, rRef, xFact, yFact ); // Get graphic object size in 100th of mm - GraphicObject const *pGraphicObject = pSh->GetGraphicObj(); - if (!pGraphicObject) - return; const MapMode aMapMode100thmm(MapUnit::Map100thMM); Size aGraphicSize(pGraphicObject->GetPrefSize()); + if( MapUnit::MapPixel == pGraphicObject->GetPrefMapMode().GetMapUnit() ) + { aGraphicSize = Application::GetDefaultDevice()->PixelToLogic( aGraphicSize, aMapMode100thmm ); + } else + { aGraphicSize = OutputDevice::LogicToLogic( aGraphicSize, pGraphicObject->GetPrefMapMode(), aMapMode100thmm); + } + if( aGraphicSize.Width() == 0 || aGraphicSize.Height() == 0 ) + { return ; + } // Get old values for crop in 10th of mm SfxItemSet aSet( pSh->GetAttrPool(), svl::Items<RES_GRFATR_CROPGRF, RES_GRFATR_CROPGRF>{} ); @@ -825,10 +865,10 @@ void SwVirtFlyDrawObj::NbcCrop(const Point& rRef, const Fraction& xFact, const F double fScaleX = ( aGraphicSize.Width() - aCropRectangle.Left() - aCropRectangle.Right() ) / (double)nOldWidth; double fScaleY = ( aGraphicSize.Height() - aCropRectangle.Top() - aCropRectangle.Bottom() ) / (double)nOldHeight; - sal_Int32 nDiffLeft = aNewRect.Left() - aOldRect.Left(); - sal_Int32 nDiffTop = aNewRect.Top() - aOldRect.Top(); - sal_Int32 nDiffRight = aNewRect.Right() - aOldRect.Right(); - sal_Int32 nDiffBottom = aNewRect.Bottom() - aOldRect.Bottom(); + sal_Int32 nDiffLeft = aNewRect.Left() - aOutRect.Left(); + sal_Int32 nDiffTop = aNewRect.Top() - aOutRect.Top(); + sal_Int32 nDiffRight = aNewRect.Right() - aOutRect.Right(); + sal_Int32 nDiffBottom = aNewRect.Bottom() - aOutRect.Bottom(); // Compute new values in 10th of mm sal_Int32 nLeftCrop = static_cast<sal_Int32>( aCropRectangle.Left() + nDiffLeft * fScaleX ); @@ -854,31 +894,117 @@ void SwVirtFlyDrawObj::NbcCrop(const Point& rRef, const Fraction& xFact, const F aSz.SetHeight(aNewRect.GetHeight()); pFormat->GetDoc()->SetAttr( aSz, *pFormat ); + if(bIsTransformableSwFrame) + { + // Need to correct the TopLeft position in rotated state to make + // the interaction look correct. First, extract rotation (and others + // currently not used) + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + GetFlyFrame()->getFrameAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX); + + // calc the center of the unchanged object + const basegfx::B2DPoint aFormerCenter( + GetFlyFrame()->getFrameAreaTransformation() * basegfx::B2DPoint(0.5, 0.5)); + + // define the existing rotaiton around that former center + const basegfx::B2DHomMatrix aRotFormerCenter( + basegfx::utils::createRotateAroundPoint( + aFormerCenter.getX(), + aFormerCenter.getY(), + fRotate)); + + // use the new center of the unrotated object, rotate it around the + // former center + const Point aNewCenter(aNewRect.Center()); + const basegfx::B2DPoint aRotNewCenter( + aRotFormerCenter * basegfx::B2DPoint(aNewCenter.X(), aNewCenter.Y())); + + // Create the new TopLeft of the unrotated, cropped object by creating + // as if re-rceating the unrotated geometry + const Point aNewTopLeft( + basegfx::fround(aRotNewCenter.getX() - (0.5 * aNewRect.getWidth())), + basegfx::fround(aRotNewCenter.getY() - (0.5 * aNewRect.getHeight()))); + + // checvk if we have movement and execute if yes + const Size aDeltaMove( + basegfx::fround(aNewTopLeft.getX() - aOutRect.Left()), + basegfx::fround(aNewTopLeft.getY() - aOutRect.Top())); + + if(0 != aDeltaMove.Width() || 0 != aDeltaMove.Height()) + { + NbcMove(aDeltaMove); + } + } + // pSh->EndUndo(SwUndoId::END); pSh->EndAllAction(); - } -void SwVirtFlyDrawObj::NbcResize(const Point& rRef, - const Fraction& xFact, const Fraction& yFact) +void SwVirtFlyDrawObj::NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) { - ResizeRect( aOutRect, rRef, xFact, yFact ); - const SwFrame* pTmpFrame = GetFlyFrame()->GetAnchorFrame(); + if( !pTmpFrame ) + { pTmpFrame = GetFlyFrame(); - const bool bVertX = pTmpFrame->IsVertical(); + } + + const bool bVertX(pTmpFrame->IsVertical()); + const bool bRTL(pTmpFrame->IsRightToLeft()); + const bool bVertL2RX(pTmpFrame->IsVertLR()); + const bool bUseRightEdge((bVertX && !bVertL2RX ) || bRTL); + const bool bIsTransformableSwFrame( + GetFlyFrame()->IsFlyFreeFrame() && + static_cast<SwFlyFreeFrame*>(GetFlyFrame())->isTransformableSwFrame()); + + if(bIsTransformableSwFrame) + { + // When we have a change in transformed state, we need to fall back to the + // state without possible transformations. + // In the Resize case to correctly handle the changes, apply to the transformation + // and extract the new, untransformed state from that modified transformation + basegfx::B2DHomMatrix aNewMat(GetFlyFrame()->getFrameAreaTransformation()); + const basegfx::B2DPoint aRef(rRef.X(), rRef.Y()); + + // apply state to already valid transformation + aNewMat.translate(-aRef.getX(), -aRef.getY()); + aNewMat.scale(double(xFact), double(yFact)); + aNewMat.translate(aRef.getX(), aRef.getY()); + + // get center of transfomed state + const basegfx::B2DPoint aCenter(aNewMat * basegfx::B2DPoint(0.5, 0.5)); + + // decompose to extract scale + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + aNewMat.decompose(aScale, aTranslate, fRotate, fShearX); + + // create new modified 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()))); + + // restore FrameAreas so that actions below not adapted to new + // full transformations take the correct actions + TransformableSwFrame* pTransformableSwFrame(static_cast<SwFlyFreeFrame*>(GetFlyFrame())->getTransformableSwFrame()); + pTransformableSwFrame->restoreFrameAreas(); + } + else + { + ResizeRect( aOutRect, rRef, xFact, yFact ); + } - const bool bRTL = pTmpFrame->IsRightToLeft(); + // Position may also change, remember old one. This ois now already + // the one in the unrotated, old coordinate system + Point aOldPos(bUseRightEdge ? GetFlyFrame()->getFrameArea().TopRight() : GetFlyFrame()->getFrameArea().Pos()); - const bool bVertL2RX = pTmpFrame->IsVertLR(); - const Point aNewPos( ( bVertX && !bVertL2RX ) || bRTL ? - aOutRect.Right() + 1 : - aOutRect.Left(), - aOutRect.Top() ); + // get target size in old coordinate system + Size aSz( aOutRect.Right() - aOutRect.Left() + 1, aOutRect.Bottom()- aOutRect.Top() + 1 ); - Size aSz( aOutRect.Right() - aOutRect.Left() + 1, - aOutRect.Bottom()- aOutRect.Top() + 1 ); + // compare with restored FrameArea if( aSz != GetFlyFrame()->getFrameArea().SSize() ) { //The width of the columns should not be too narrow @@ -903,6 +1029,7 @@ void SwVirtFlyDrawObj::NbcResize(const Point& rRef, const SwFormatFrameSize aOldFrameSz( pFormat->GetFrameSize() ); GetFlyFrame()->ChgSize( aSz ); SwFormatFrameSize aFrameSz( pFormat->GetFrameSize() ); + if ( aFrameSz.GetWidthPercent() || aFrameSz.GetHeightPercent() ) { long nRelWidth, nRelHeight; @@ -910,6 +1037,7 @@ void SwVirtFlyDrawObj::NbcResize(const Point& rRef, GetFlyFrame()->GetAnchorFrame() : GetFlyFrame()->GetAnchorFrame()->GetUpper(); const SwViewShell *pSh = GetFlyFrame()->getRootFrame()->GetCurrShell(); + if ( pSh && pRel->IsBodyFrame() && pSh->GetViewOptions()->getBrowseMode() && pSh->VisArea().HasArea() ) @@ -924,40 +1052,50 @@ void SwVirtFlyDrawObj::NbcResize(const Point& rRef, nRelWidth = pRel->getFramePrintArea().Width(); nRelHeight = pRel->getFramePrintArea().Height(); } + if ( aFrameSz.GetWidthPercent() && aFrameSz.GetWidthPercent() != SwFormatFrameSize::SYNCED && aOldFrameSz.GetWidth() != aFrameSz.GetWidth() ) + { aFrameSz.SetWidthPercent( sal_uInt8(aSz.Width() * 100.0 / nRelWidth + 0.5) ); + } + if ( aFrameSz.GetHeightPercent() && aFrameSz.GetHeightPercent() != SwFormatFrameSize::SYNCED && aOldFrameSz.GetHeight() != aFrameSz.GetHeight() ) + { aFrameSz.SetHeightPercent( sal_uInt8(aSz.Height() * 100.0 / nRelHeight + 0.5) ); + } + pFormat->GetDoc()->SetAttr( aFrameSz, *pFormat ); } } - //Position can also be changed! - const Point aOldPos( ( bVertX && !bVertL2RX ) || bRTL ? - GetFlyFrame()->getFrameArea().TopRight() : - GetFlyFrame()->getFrameArea().Pos() ); + //Position can also be changed, get new one + const Point aNewPos(bUseRightEdge ? aOutRect.Right() + 1 : aOutRect.Left(), aOutRect.Top()); + if ( aNewPos != aOldPos ) { - //May have been altered by the ChgSize! - if( bVertX || bRTL ) + // Former late change in aOutRect by ChgSize + // is now taken into account directly by calculating + // aNewPos *after* calling ChgSize (see old code). + // Still need to adapt aOutRect since the 'Move' is already applied + // here (see ResizeRect) and it's the same SdrObject + const Size aDeltaMove( + aNewPos.X() - aOldPos.X(), + aNewPos.Y() - aOldPos.Y()); + MoveRect(aOutRect, Size(-aDeltaMove.Width(), -aDeltaMove.Height())); + + // Now, move as needed (no empty delta which was a hack anyways) + if(bIsTransformableSwFrame) { - if( aOutRect.TopRight() != aNewPos ) - { - SwTwips nDeltaX; - if ( bVertL2RX ) - nDeltaX = aNewPos.X() - aOutRect.Left(); - else - nDeltaX = aNewPos.X() - aOutRect.Right(); - SwTwips nDeltaY = aNewPos.Y() - aOutRect.Top(); - MoveRect( aOutRect, Size( nDeltaX, nDeltaY ) ); - } + // need to save aOutRect to FrameArea, will be restored to aOutRect in + // SwVirtFlyDrawObj::NbcMove currently for TransformableSwFrames + SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*GetFlyFrame()); + aFrm.setSwRect(aOutRect); } - else if ( aOutRect.TopLeft() != aNewPos ) - aOutRect.SetPos( aNewPos ); + + // keep old hack - not clear what happens here bInResize = true; - NbcMove( Size( 0, 0 ) ); + NbcMove(aDeltaMove); bInResize = false; } } diff --git a/sw/source/core/inc/flyfrms.hxx b/sw/source/core/inc/flyfrms.hxx index 429ff26b25e8..5334a0269447 100644 --- a/sw/source/core/inc/flyfrms.hxx +++ b/sw/source/core/inc/flyfrms.hxx @@ -26,7 +26,7 @@ // #i28701# class SwFlyAtContentFrame; -double getFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame); +double getLocalFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame); // Base class for those Flys that can "move freely" or better that are not // bound in Content. @@ -63,7 +63,7 @@ private: // RotateFlyFrame3 - Support for outer Frame of a SwGrfNode // Only for local data extraction. To uniquely access information // for local transformation, use getFrameArea(Print)Transformation - double getFrameRotation() const; + double getLocalFrameRotation() const; protected: // #i28701# - new friend class <SwFlyNotify> for access to diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx index b8a2d7ab0370..cb436581adf2 100644 --- a/sw/source/core/inc/frame.hxx +++ b/sw/source/core/inc/frame.hxx @@ -207,10 +207,7 @@ public: virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const; // RotateFlyFrame3 - Support for Transformations - // Diverse transformations, starting with a concrete translate that has - // to be mapped and currently directly changes SwRect(s) at SwFrames. For - // now stay on sigle actions (*_translate), bu tmaybe later unified to - // a single transform with a single B2DHomMatrix to apply + // Modify current transformations by applying given translation virtual void transform_translate(const Point& rOffset); }; @@ -228,7 +225,10 @@ private: basegfx::B2DHomMatrix maFrameAreaTransformation; basegfx::B2DHomMatrix maFramePrintAreaTransformation; - // last saved versions of SwRect(s) from SwFrameAreaDefinition + // last saved versions of SwRect(s) from SwFrameAreaDefinition, + // set from adaptFrameAreasToTransformations before modifying + // SwFrameAreaDefinition(s), used for restore from + // restoreFrameAreas SwRect maSavedFrameArea; SwRect maSavedFramePrintArea; @@ -262,17 +262,17 @@ public: // 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 resetAreaDefinitionsToTransformed). + // last saved (see adaptFrameAreasToTransformations). // Only the SwRect(s) are changed back, not the transformations. - void resetAreaDefinitionsToUntransformed(); + 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. - void resetAreaDefinitionsToTransformed(); + void adaptFrameAreasToTransformations(); - // transform by given B2DHomMatrix - void doTransform(const basegfx::B2DHomMatrix aTransform); + // Modify current definitions by applying the given transformation + void transform(const basegfx::B2DHomMatrix aTransform); }; /** diff --git a/sw/source/core/inc/notxtfrm.hxx b/sw/source/core/inc/notxtfrm.hxx index 6144b32e58eb..2726a4eb5071 100644 --- a/sw/source/core/inc/notxtfrm.hxx +++ b/sw/source/core/inc/notxtfrm.hxx @@ -44,8 +44,8 @@ private: // RotateFlyFrame3 - Support for inner frame of a SwGrfNode. // Only for local data extraction. To uniquely access information // for local transformation, use getFrameArea(Print)Transformation. - friend double getFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame); - double getFrameRotation() const; + friend double getLocalFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame); + double getLocalFrameRotation() const; protected: virtual void MakeAll(vcl::RenderContext* pRenderContext) override; diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx index a3c8890df118..684b989d76b8 100644 --- a/sw/source/core/layout/fly.cxx +++ b/sw/source/core/layout/fly.cxx @@ -1966,6 +1966,7 @@ Size SwFlyFrame::ChgSize( const Size& aNewSize ) } } } + if ( aAdjustedNewSize != getFrameArea().SSize() ) { SwFrameFormat *pFormat = GetFormat(); diff --git a/sw/source/core/layout/flycnt.cxx b/sw/source/core/layout/flycnt.cxx index 2b980f904c39..87d3bba45400 100644 --- a/sw/source/core/layout/flycnt.cxx +++ b/sw/source/core/layout/flycnt.cxx @@ -1371,9 +1371,7 @@ void SwFlyAtContentFrame::SetAbsPos( const Point &rNew ) GetPageFrame()->MoveFly( this, pTmpPage ); const Point aRelPos = bVert ? Point( -nY, nX ) : Point( nX, nY ); - ChgRelPos( aRelPos ); - GetFormat()->GetDoc()->GetIDocumentUndoRedo().EndUndo( SwUndoId::END, nullptr ); if ( pOldPage != FindPageFrame() ) diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx index 10c519fea697..8a8c714ef351 100644 --- a/sw/source/core/layout/flylay.cxx +++ b/sw/source/core/layout/flylay.cxx @@ -156,7 +156,7 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) const int nLoopControlMax = 10; // RotateFlyFrame3 - outer frame - const double fRotation(getFrameRotation()); + const double fRotation(getLocalFrameRotation()); const bool bRotated(!basegfx::fTools::equalZero(fRotation)); if(bRotated) @@ -166,7 +166,7 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) // needed. Reset to BoundAreas will be done below automatically if(isTransformableSwFrame()) { - getTransformableSwFrame()->resetAreaDefinitionsToUntransformed(); + getTransformableSwFrame()->restoreFrameAreas(); } } @@ -264,7 +264,7 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) getTransformableSwFrame()->createFrameAreaTransformations( fRotation, aB2DCenter); - getTransformableSwFrame()->resetAreaDefinitionsToTransformed(); + getTransformableSwFrame()->adaptFrameAreasToTransformations(); } else { @@ -323,17 +323,17 @@ void SwFlyFreeFrame::transform_translate(const Point& rOffset) rOffset.X(), rOffset.Y())); // transform using TransformableSwFrame - getTransformableSwFrame()->doTransform(aTransform); + getTransformableSwFrame()->transform(aTransform); } } // RotateFlyFrame3 - outer frame -double getFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame) +double getLocalFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame) { - return rNoTextFrame.getFrameRotation(); + return rNoTextFrame.getLocalFrameRotation(); } -double SwFlyFreeFrame::getFrameRotation() const +double SwFlyFreeFrame::getLocalFrameRotation() const { // SwLayoutFrame::Lower() != SwFrame::GetLower(), but SwFrame::GetLower() // calls SwLayoutFrame::Lower() when it's a SwLayoutFrame - so use GetLower() @@ -341,7 +341,7 @@ double SwFlyFreeFrame::getFrameRotation() const if(nullptr != pSwNoTextFrame) { - return getFrameRotation_from_SwNoTextFrame(*pSwNoTextFrame); + return getLocalFrameRotation_from_SwNoTextFrame(*pSwNoTextFrame); } // no rotation diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index 4cd9245eb2f0..7f7068ed0362 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -166,7 +166,7 @@ void TransformableSwFrame::createFrameAreaTransformations( rFramePrintArea.Left() + rFrameArea.Left(), rFramePrintArea.Top() + rFrameArea.Top()); } -void TransformableSwFrame::resetAreaDefinitionsToTransformed() +void TransformableSwFrame::adaptFrameAreasToTransformations() { if(!getLocalFrameAreaTransformation().isIdentity()) { @@ -203,7 +203,7 @@ void TransformableSwFrame::resetAreaDefinitionsToTransformed() } } -void TransformableSwFrame::resetAreaDefinitionsToUntransformed() +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 @@ -224,7 +224,7 @@ void TransformableSwFrame::resetAreaDefinitionsToUntransformed() } // transform by given B2DHomMatrix -void TransformableSwFrame::doTransform(const basegfx::B2DHomMatrix aTransform) +void TransformableSwFrame::transform(const basegfx::B2DHomMatrix aTransform) { if(!aTransform.isIdentity()) { commit eab9a72072f841a29533747c5e6affe0e720517a Author: Armin Le Grand <armin.le.gr...@cib.de> Date: Thu Nov 9 15:53:33 2017 +0100 RotateFlyFrame3: Restructured TransformableSwFrame No longer derive a SwFrame that needs Transformation support from TransformableSwFrame, but keep it as a member (in a std::unique_ptr). Adapted all usages, also added reset of local SwRect(s) in local SwFrameAreaDefinition during layouting. That makes PrintPreview work correctly. Change-Id: I2e7720e67b57d4d29c0feb065878e246192a8a4c diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx index 897e9f6d1121..3971c9140da2 100644 --- a/sw/source/core/doc/notxtfrm.cxx +++ b/sw/source/core/doc/notxtfrm.cxx @@ -144,7 +144,8 @@ static void lcl_PaintReplacement( const SwRect &rRect, const OUString &rText, SwNoTextFrame::SwNoTextFrame(SwNoTextNode * const pNode, SwFrame* pSib ) : SwContentFrame( pNode, pSib ), - TransformableSwFrame() + // RotateFlyFrame3 + mpTransformableSwFrame() { mnFrameType = SwFrameType::NoTxt; } @@ -474,25 +475,41 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* pRenderContext) // RotateFlyFrame3 - inner frame. Get rotation and check if used const double fRotation(getFrameRotation()); const bool bRotated(!basegfx::fTools::equalZero(fRotation)); - SwFlyFreeFrame* pUpperFly(dynamic_cast< SwFlyFreeFrame* >(GetUpper())); - if(bRotated && pUpperFly && !pUpperFly->isFrameAreaDefinitionValid()) + if(bRotated) { - // RotateFlyFrame3: outer frame *needs* to be layouted first, force this by calling - // it's ::Calc directly - pUpperFly->Calc(pRenderContext); - } + SwFlyFreeFrame* pUpperFly(dynamic_cast< SwFlyFreeFrame* >(GetUpper())); - if(bRotated && pUpperFly) - { - // Reset outer frame to unrotated state. This is necessary to make the - // layouting below work as currently implemented in Writer. As expected - // using Transformations allows to do this on the fly due to all information - // being included there. - // The full solution would be to adapt the whole layouting - // process of Writer to take care of Transformations, but that - // is currently beyond scope - pUpperFly->resetAreaDefinitionsToUntransformed(*pUpperFly); + if(pUpperFly) + { + if(!pUpperFly->isFrameAreaDefinitionValid()) + { + // RotateFlyFrame3: outer frame *needs* to be layouted first, force this by calling + // it's ::Calc directly + pUpperFly->Calc(pRenderContext); + } + + // Reset outer frame to unrotated state. This is necessary to make the + // layouting below work as currently implemented in Writer. As expected + // using Transformations allows to do this on the fly due to all information + // being included there. + // The full solution would be to adapt the whole layouting + // process of Writer to take care of Transformations, but that + // is currently beyond scope + if(pUpperFly->isTransformableSwFrame()) + { + pUpperFly->getTransformableSwFrame()->resetAreaDefinitionsToUntransformed(); + } + } + + // Re-layout may be partially (see all isFrameAreaDefinitionValid() flags), + // so resetting the local SwFrame(s) in the local SwFrameAreaDefinition is also + // needed (e.g. for PrintPreview). + // Reset to BoundAreas will be done below automatically + if(isTransformableSwFrame()) + { + getTransformableSwFrame()->resetAreaDefinitionsToUntransformed(); + } } SwContentNotify aNotify( this ); @@ -519,15 +536,9 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* pRenderContext) } // RotateFlyFrame3 - inner frame - // After the unrotated layout is finished, apply possible set rotation to it - if(!bRotated) + if(bRotated) { - // reset transformations to show that they are not used - resetLocalAreaTransformations(); - } - else - { - const bool bMeValid(isFrameAreaDefinitionValid()); + SwFlyFreeFrame* pUpperFly(dynamic_cast< SwFlyFreeFrame* >(GetUpper())); if(pUpperFly) { @@ -536,30 +547,41 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* pRenderContext) // the transformed SwFrame. All needed information is part // of the already correctly created Transformations of the // upper frame, so it can bre re-created on the fly - pUpperFly->resetAreaDefinitionsToTransformed(*pUpperFly); + if(pUpperFly->isTransformableSwFrame()) + { + pUpperFly->getTransformableSwFrame()->resetAreaDefinitionsToTransformed(); + } } - if(bMeValid) + // After the unrotated layout is finished, apply possible set rotation to it + // 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()); + + if(!mpTransformableSwFrame) { - // 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()); - - updateTransformationsAndFrameAreaDefinitions( - *this, - fRotation, - aB2DCenter); + mpTransformableSwFrame.reset(new TransformableSwFrame(*this)); } + + getTransformableSwFrame()->createFrameAreaTransformations( + fRotation, + aB2DCenter); + getTransformableSwFrame()->resetAreaDefinitionsToTransformed(); + } + else + { + // reset transformations to show that they are not used + mpTransformableSwFrame.reset(); } } // RotateFlyFrame3 - Support for Transformations - outer frame basegfx::B2DHomMatrix SwNoTextFrame::getFrameAreaTransformation() const { - if(!getLocalFrameAreaTransformation().isIdentity()) + if(isTransformableSwFrame()) { // use pre-created transformation - return getLocalFrameAreaTransformation(); + return getTransformableSwFrame()->getLocalFrameAreaTransformation(); } // call parent @@ -568,10 +590,10 @@ basegfx::B2DHomMatrix SwNoTextFrame::getFrameAreaTransformation() const basegfx::B2DHomMatrix SwNoTextFrame::getFramePrintAreaTransformation() const { - if(!getLocalFramePrintAreaTransformation().isIdentity()) + if(isTransformableSwFrame()) { // use pre-created transformation - return getLocalFramePrintAreaTransformation(); + return getTransformableSwFrame()->getLocalFramePrintAreaTransformation(); } // call parent @@ -586,14 +608,14 @@ void SwNoTextFrame::transform_translate(const Point& rOffset) SwContentFrame::transform_translate(rOffset); // check if the Transformations need to be adapted - if(isTransformationUsed()) + if(isTransformableSwFrame()) { const basegfx::B2DHomMatrix aTransform( basegfx::utils::createTranslateB2DHomMatrix( rOffset.X(), rOffset.Y())); // transform using TransformableSwFrame - doTransform(aTransform); + getTransformableSwFrame()->doTransform(aTransform); } } diff --git a/sw/source/core/inc/flyfrms.hxx b/sw/source/core/inc/flyfrms.hxx index c388d80a0c0b..429ff26b25e8 100644 --- a/sw/source/core/inc/flyfrms.hxx +++ b/sw/source/core/inc/flyfrms.hxx @@ -30,7 +30,7 @@ double getFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame); // Base class for those Flys that can "move freely" or better that are not // bound in Content. -class SwFlyFreeFrame : public SwFlyFrame, public TransformableSwFrame +class SwFlyFreeFrame : public SwFlyFrame { private: // #i34753# - flag for at-page anchored Writer fly frames @@ -43,6 +43,9 @@ private: SwRect maUnclippedFrame; + // RotateFlyFrame3 add TransformableSwFrame + std::unique_ptr< TransformableSwFrame > mpTransformableSwFrame; + void CheckClip( const SwFormatFrameSize &rSz ); //'Emergency' Clipping. /** determines, if direct environment of fly frame has 'auto' size @@ -126,6 +129,11 @@ public: virtual bool IsFormatPossible() const override; // RotateFlyFrame3 - Support for Transformations + bool isTransformableSwFrame() const { return bool(mpTransformableSwFrame); } + TransformableSwFrame* getTransformableSwFrame() { return mpTransformableSwFrame.get(); } + const TransformableSwFrame* getTransformableSwFrame() const { return mpTransformableSwFrame.get(); } + + // RotateFlyFrame3 - Support for Transformations virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const override; virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const override; diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx index 7cb12dadad1a..b8a2d7ab0370 100644 --- a/sw/source/core/inc/frame.hxx +++ b/sw/source/core/inc/frame.hxx @@ -220,54 +220,25 @@ public: class SW_DLLPUBLIC TransformableSwFrame { private: + // The SwFrameAreaDefinition to work on + SwFrameAreaDefinition& mrSwFrameAreaDefinition; + // FrameAreaTransformation and FramePrintAreaTransformation // here when more than translate/scale is used (e.g. rotation) basegfx::B2DHomMatrix maFrameAreaTransformation; basegfx::B2DHomMatrix maFramePrintAreaTransformation; - // helper method to create FrameAreaTransformations based on the - // curent FrameAreaDefinition - void createFrameAreaTransformations( - const SwFrameAreaDefinition& rSwFrameAreaDefinition, - double fRotation, - const basegfx::B2DPoint& rCenter); - - // helper method to set FrameAreaDefinitions based on given - // transformations - void setFrameAreaDefinitionsToBoundRangesOfTransformations( - SwFrameAreaDefinition& rSwFrameAreaDefinition); - -protected: - // Full update of Transformations and BoundAreas: - // - Re-create Transformations based on SwRect(s) from the - // given SwFrameAreaDefinition. - // - Based on that, create BoundRanges for the Transformations - // and use as new SwRect(s) for the given SwFrameAreaDefinition. - void updateTransformationsAndFrameAreaDefinitions( - SwFrameAreaDefinition& rSwFrameAreaDefinition, - double fRotation, - const basegfx::B2DPoint& rCenter); - - void setLocalFrameAreaTransformation(const basegfx::B2DHomMatrix& rNew) - { - maFrameAreaTransformation = rNew; - } - - void setLocalFramePrintAreaTransformation(const basegfx::B2DHomMatrix& rNew) - { - maFramePrintAreaTransformation = rNew; - } - - void resetLocalAreaTransformations() - { - maFrameAreaTransformation.identity(); - maFramePrintAreaTransformation.identity(); - } + // last saved versions of SwRect(s) from SwFrameAreaDefinition + SwRect maSavedFrameArea; + SwRect maSavedFramePrintArea; public: - TransformableSwFrame() - : maFrameAreaTransformation(), - maFramePrintAreaTransformation() + TransformableSwFrame(SwFrameAreaDefinition& rSwFrameAreaDefinition) + : mrSwFrameAreaDefinition(rSwFrameAreaDefinition), + maFrameAreaTransformation(), + maFramePrintAreaTransformation(), + maSavedFrameArea(), + maSavedFramePrintArea() { } @@ -282,27 +253,23 @@ public: return maFramePrintAreaTransformation; } - // This method allows to reset the SwRect(s) in the - // given SwFrameAreaDefinition which are already apapted to - // Transformation and thus have a changed BoundArea back to - // the untransformed state. Only the SwRect(s) are changed - // back, not the transformations. As expected from using - // Transformations, these contain all the necessary - // information - void resetAreaDefinitionsToUntransformed( - SwFrameAreaDefinition& rSwFrameAreaDefinition); + // Helper method to re-create FrameAreaTransformations based on the + // curent FrameAreaDefinition, 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 resetAreaDefinitionsToTransformed). + // Only the SwRect(s) are changed back, not the transformations. + void resetAreaDefinitionsToUntransformed(); // Re-Creates the SwRect(s) as BoundAreas based on the current - // Transformations, useful to set back the SwRect(s) to Transformed - // state when itz was necessary to reset them temporarily (see above) - void resetAreaDefinitionsToTransformed( - SwFrameAreaDefinition& rSwFrameAreaDefinition); - - // check if used - bool isTransformationUsed() const - { - return !maFrameAreaTransformation.isIdentity() || !maFramePrintAreaTransformation.isIdentity(); - } + // set Transformations, also saves the last SwRect(s) to the save + // values. + void resetAreaDefinitionsToTransformed(); // transform by given B2DHomMatrix void doTransform(const basegfx::B2DHomMatrix aTransform); diff --git a/sw/source/core/inc/notxtfrm.hxx b/sw/source/core/inc/notxtfrm.hxx index 0054078890a4..6144b32e58eb 100644 --- a/sw/source/core/inc/notxtfrm.hxx +++ b/sw/source/core/inc/notxtfrm.hxx @@ -26,7 +26,7 @@ class OutputDevice; class SwBorderAttrs; struct SwCursorMoveState; -class SwNoTextFrame: public SwContentFrame, public TransformableSwFrame +class SwNoTextFrame: public SwContentFrame { private: friend void FrameFinit(); @@ -38,6 +38,9 @@ private: virtual void DestroyImpl() override; virtual ~SwNoTextFrame() override; + // RotateFlyFrame3 add TransformableSwFrame + std::unique_ptr< TransformableSwFrame > mpTransformableSwFrame; + // RotateFlyFrame3 - Support for inner frame of a SwGrfNode. // Only for local data extraction. To uniquely access information // for local transformation, use getFrameArea(Print)Transformation. @@ -66,6 +69,11 @@ public: bool HasAnimation() const; // RotateFlyFrame3 - Support for Transformations + bool isTransformableSwFrame() const { return bool(mpTransformableSwFrame); } + TransformableSwFrame* getTransformableSwFrame() { return mpTransformableSwFrame.get(); } + const TransformableSwFrame* getTransformableSwFrame() const { return mpTransformableSwFrame.get(); } + + // RotateFlyFrame3 - Support for Transformations virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const override; virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const override; diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx index 7a9aa676dfdc..10c519fea697 100644 --- a/sw/source/core/layout/flylay.cxx +++ b/sw/source/core/layout/flylay.cxx @@ -47,12 +47,13 @@ using namespace ::com::sun::star; SwFlyFreeFrame::SwFlyFreeFrame( SwFlyFrameFormat *pFormat, SwFrame* pSib, SwFrame *pAnch ) : SwFlyFrame( pFormat, pSib, pAnch ), - TransformableSwFrame(), // #i34753# mbNoMakePos( false ), // #i37068# mbNoMoveOnCheckClip( false ), - maUnclippedFrame( ) + maUnclippedFrame(), + // RotateFlyFrame3 + mpTransformableSwFrame() { } @@ -154,6 +155,21 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) int nLoopControlRuns = 0; const int nLoopControlMax = 10; + // RotateFlyFrame3 - outer frame + const double fRotation(getFrameRotation()); + const bool bRotated(!basegfx::fTools::equalZero(fRotation)); + + if(bRotated) + { + // Re-layout may be partially (see all isFrameAreaDefinitionValid() flags), + // so resetting the local SwFrame(s) in the local SwFrameAreaDefinition is + // needed. Reset to BoundAreas will be done below automatically + if(isTransformableSwFrame()) + { + getTransformableSwFrame()->resetAreaDefinitionsToUntransformed(); + } + } + while ( !isFrameAreaPositionValid() || !isFrameAreaSizeValid() || !isFramePrintAreaValid() || m_bFormatHeightOnly || !m_bValidContentPos ) { SwRectFnSet aRectFnSet(this); @@ -233,30 +249,27 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) // RotateFlyFrame3 - outer frame // Do not refresh transforms/Areas self here, this will be done // when inner and outer frame are layouted, in SwNoTextFrame::MakeAll - const double fRotation(getFrameRotation()); - const bool bRotated(!basegfx::fTools::equalZero(fRotation)); - - if(!bRotated) - { - // reset transformations to show that they are not used - resetLocalAreaTransformations(); - } - else + if(bRotated) { // RotateFlyFrame3: Safe changes locally - const bool bMeValid(isFrameAreaDefinitionValid()); + // get center from outer frame (layout frame) to be on the safe side + const Point aCenter(getFrameArea().Center()); + const basegfx::B2DPoint aB2DCenter(aCenter.X(), aCenter.Y()); - if(bMeValid) + if(!mpTransformableSwFrame) { - // get center from outer frame (layout frame) to be on the safe side - const Point aCenter(getFrameArea().Center()); - const basegfx::B2DPoint aB2DCenter(aCenter.X(), aCenter.Y()); - - updateTransformationsAndFrameAreaDefinitions( - *this, - fRotation, - aB2DCenter); + mpTransformableSwFrame.reset(new TransformableSwFrame(*this)); } + + getTransformableSwFrame()->createFrameAreaTransformations( + fRotation, + aB2DCenter); + getTransformableSwFrame()->resetAreaDefinitionsToTransformed(); + } + else + { + // reset transformations to show that they are not used + mpTransformableSwFrame.reset(); } Unlock(); @@ -273,10 +286,10 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) // RotateFlyFrame3 - Support for Transformations - outer frame basegfx::B2DHomMatrix SwFlyFreeFrame::getFrameAreaTransformation() const { - if(!getLocalFrameAreaTransformation().isIdentity()) + if(isTransformableSwFrame()) { // use pre-created transformation - return getLocalFrameAreaTransformation(); + return getTransformableSwFrame()->getLocalFrameAreaTransformation(); } // call parent @@ -285,10 +298,10 @@ basegfx::B2DHomMatrix SwFlyFreeFrame::getFrameAreaTransformation() const basegfx::B2DHomMatrix SwFlyFreeFrame::getFramePrintAreaTransformation() const { - if(!getLocalFramePrintAreaTransformation().isIdentity()) + if(isTransformableSwFrame()) { // use pre-created transformation - return getLocalFramePrintAreaTransformation(); + return getTransformableSwFrame()->getLocalFramePrintAreaTransformation(); } // call parent @@ -303,14 +316,14 @@ void SwFlyFreeFrame::transform_translate(const Point& rOffset) SwFlyFrame::transform_translate(rOffset); // check if the Transformations need to be adapted - if(isTransformationUsed()) + if(isTransformableSwFrame()) { const basegfx::B2DHomMatrix aTransform( basegfx::utils::createTranslateB2DHomMatrix( rOffset.X(), rOffset.Y())); // transform using TransformableSwFrame - doTransform(aTransform); + getTransformableSwFrame()->doTransform(aTransform); } } diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index a67a70d46c76..4cd9245eb2f0 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -147,33 +147,26 @@ void SwFrameAreaDefinition::transform_translate(const Point& rOffset) } void TransformableSwFrame::createFrameAreaTransformations( - const SwFrameAreaDefinition& rSwFrameAreaDefinition, double fRotation, const basegfx::B2DPoint& rCenter) { - // 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)); - const SwRect& rFrameArea(rSwFrameAreaDefinition.getFrameArea()); - const SwRect& rFramePrintArea(rSwFrameAreaDefinition.getFramePrintArea()); - - setLocalFrameAreaTransformation( - aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix( - rFrameArea.Width(), rFrameArea.Height(), - rFrameArea.Left(), rFrameArea.Top())); - setLocalFramePrintAreaTransformation( - aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix( - rFramePrintArea.Width(), rFramePrintArea.Height(), - rFramePrintArea.Left() + rFrameArea.Left(), rFramePrintArea.Top() + rFrameArea.Top())); + const SwRect& rFrameArea(mrSwFrameAreaDefinition.getFrameArea()); + const SwRect& rFramePrintArea(mrSwFrameAreaDefinition.getFramePrintArea()); + + maFrameAreaTransformation = aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix( + rFrameArea.Width(), rFrameArea.Height(), + rFrameArea.Left(), rFrameArea.Top()); + maFramePrintAreaTransformation = aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix( + rFramePrintArea.Width(), rFramePrintArea.Height(), + rFramePrintArea.Left() + rFrameArea.Left(), rFramePrintArea.Top() + rFrameArea.Top()); } -void TransformableSwFrame::setFrameAreaDefinitionsToBoundRangesOfTransformations( - SwFrameAreaDefinition& rSwFrameAreaDefinition) +void TransformableSwFrame::resetAreaDefinitionsToTransformed() { if(!getLocalFrameAreaTransformation().isIdentity()) { @@ -183,9 +176,10 @@ void TransformableSwFrame::setFrameAreaDefinitionsToBoundRangesOfTransformations basegfx::fround(aRangeFrameArea.getMinX()), basegfx::fround(aRangeFrameArea.getMinY()), basegfx::fround(aRangeFrameArea.getWidth()), basegfx::fround(aRangeFrameArea.getHeight())); - if(aNewFrm != rSwFrameAreaDefinition.getFrameArea()) + if(aNewFrm != mrSwFrameAreaDefinition.getFrameArea()) { - SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(rSwFrameAreaDefinition); + maSavedFrameArea = mrSwFrameAreaDefinition.getFrameArea(); + SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(mrSwFrameAreaDefinition); aFrm.setSwRect(aNewFrm); } } @@ -195,83 +189,40 @@ void TransformableSwFrame::setFrameAreaDefinitionsToBoundRangesOfTransformations basegfx::B2DRange aRangeFramePrintArea(0.0, 0.0, 1.0, 1.0); aRangeFramePrintArea.transform(getLocalFramePrintAreaTransformation()); const SwRect aNewPrt( - basegfx::fround(aRangeFramePrintArea.getMinX()) - rSwFrameAreaDefinition.getFrameArea().Left(), - basegfx::fround(aRangeFramePrintArea.getMinY()) - rSwFrameAreaDefinition.getFrameArea().Top(), + basegfx::fround(aRangeFramePrintArea.getMinX()) - mrSwFrameAreaDefinition.getFrameArea().Left(), + basegfx::fround(aRangeFramePrintArea.getMinY()) - mrSwFrameAreaDefinition.getFrameArea().Top(), basegfx::fround(aRangeFramePrintArea.getWidth()), basegfx::fround(aRangeFramePrintArea.getHeight())); - if(aNewPrt != rSwFrameAreaDefinition.getFramePrintArea()) + if(aNewPrt != mrSwFrameAreaDefinition.getFramePrintArea()) { - SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(rSwFrameAreaDefinition); + maSavedFramePrintArea = mrSwFrameAreaDefinition.getFramePrintArea(); + SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(mrSwFrameAreaDefinition); aPrt.setSwRect(aNewPrt); } } } -void TransformableSwFrame::updateTransformationsAndFrameAreaDefinitions( - SwFrameAreaDefinition& rSwFrameAreaDefinition, - double fRotation, - const basegfx::B2DPoint& rCenter) +void TransformableSwFrame::resetAreaDefinitionsToUntransformed() { - createFrameAreaTransformations( - rSwFrameAreaDefinition, - fRotation, - rCenter); + // 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 - setFrameAreaDefinitionsToBoundRangesOfTransformations( - rSwFrameAreaDefinition); -} - -void TransformableSwFrame::resetAreaDefinitionsToUntransformed( - SwFrameAreaDefinition& rSwFrameAreaDefinition) -{ - // calculate center of object - basegfx::B2DPoint aCenter(getLocalFrameAreaTransformation() * basegfx::B2DPoint(0.5, 0.5)); - - if(!getLocalFrameAreaTransformation().isIdentity()) + if(!getLocalFrameAreaTransformation().isIdentity() && maSavedFrameArea != mrSwFrameAreaDefinition.getFrameArea()) { - basegfx::B2DTuple aScale, aTranslate; - double fRotate(0.0), fShearX(0.0); - getLocalFrameAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX); - const SwRect aNewFrm( - basegfx::fround(aCenter.getX() - (0.5 * aScale.getX())), - basegfx::fround(aCenter.getY() - (0.5 * aScale.getY())), - basegfx::fround(aScale.getX()), - basegfx::fround(aScale.getY())); - - if(aNewFrm != rSwFrameAreaDefinition.getFrameArea()) - { - SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(rSwFrameAreaDefinition); - aFrm.setSwRect(aNewFrm); - } + SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(mrSwFrameAreaDefinition); + aFrm.setSwRect(maSavedFrameArea); } - if(!getLocalFramePrintAreaTransformation().isIdentity()) + if(!getLocalFramePrintAreaTransformation().isIdentity() && maSavedFramePrintArea != mrSwFrameAreaDefinition.getFramePrintArea()) { - basegfx::B2DTuple aScale, aTranslate; - double fRotate(0.0), fShearX(0.0); - getLocalFramePrintAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX); - const SwRect aNewPrt( - basegfx::fround(aCenter.getX() - (0.5 * aScale.getX())) - rSwFrameAreaDefinition.getFrameArea().Left(), - basegfx::fround(aCenter.getY() - (0.5 * aScale.getY())) - rSwFrameAreaDefinition.getFrameArea().Top(), - basegfx::fround(aScale.getX()), - basegfx::fround(aScale.getY())); - - if(aNewPrt != rSwFrameAreaDefinition.getFramePrintArea()) - { - SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(rSwFrameAreaDefinition); - aPrt.setSwRect(aNewPrt); - } + SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(mrSwFrameAreaDefinition); + aPrt.setSwRect(maSavedFramePrintArea); } } -void TransformableSwFrame::resetAreaDefinitionsToTransformed( - SwFrameAreaDefinition& rSwFrameAreaDefinition) -{ - setFrameAreaDefinitionsToBoundRangesOfTransformations( - rSwFrameAreaDefinition); -} - // transform by given B2DHomMatrix void TransformableSwFrame::doTransform(const basegfx::B2DHomMatrix aTransform) { commit 7b70e6a57fcbc4b73da7c75105ec58a6777d610f Author: Armin Le Grand <armin.le.gr...@cib.de> Date: Thu Nov 9 11:35:09 2017 +0100 RotateFlyFrame3: Added basic transformation support In lcl_MoveAllLowers SwFrame(s) were directly modified, not even by calling any member method what makes it hard to react on changes to geometric definition(s). Added logic to Transform a SwFrame, currently basic by using e.g. SwFrame::Ltransform_translate, may be later unified to general Transformation usage with a homogen Matrix Change-Id: I7582fbd1472e12e481adacedda2e65cc0c282eac diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx index b4fb5485d02e..897e9f6d1121 100644 --- a/sw/source/core/doc/notxtfrm.cxx +++ b/sw/source/core/doc/notxtfrm.cxx @@ -578,6 +578,25 @@ basegfx::B2DHomMatrix SwNoTextFrame::getFramePrintAreaTransformation() const return SwContentFrame::getFramePrintAreaTransformation(); } +// RotateFlyFrame3 - Support for Transformations +void SwNoTextFrame::transform_translate(const Point& rOffset) +{ + // call parent - this will do the basic transform for SwRect(s) + // in the SwFrameAreaDefinition + SwContentFrame::transform_translate(rOffset); + + // check if the Transformations need to be adapted + if(isTransformationUsed()) + { + const basegfx::B2DHomMatrix aTransform( + basegfx::utils::createTranslateB2DHomMatrix( + rOffset.X(), rOffset.Y())); + + // transform using TransformableSwFrame + doTransform(aTransform); + } +} + // RotateFlyFrame3 - inner frame // Check if we contain a SwGrfNode and get possible rotation from it double SwNoTextFrame::getFrameRotation() const diff --git a/sw/source/core/inc/flyfrms.hxx b/sw/source/core/inc/flyfrms.hxx index b4f66f9d22d3..c388d80a0c0b 100644 --- a/sw/source/core/inc/flyfrms.hxx +++ b/sw/source/core/inc/flyfrms.hxx @@ -128,6 +128,9 @@ public: // RotateFlyFrame3 - Support for Transformations virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const override; virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const override; + + // RotateFlyFrame3 - Support for Transformations + virtual void transform_translate(const Point& rOffset) override; }; // 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 2d0a1c321372..7cb12dadad1a 100644 --- a/sw/source/core/inc/frame.hxx +++ b/sw/source/core/inc/frame.hxx @@ -205,6 +205,13 @@ public: // SwFrame of a SwFlyFrame) virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const; virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const; + + // RotateFlyFrame3 - Support for Transformations + // Diverse transformations, starting with a concrete translate that has + // to be mapped and currently directly changes SwRect(s) at SwFrames. For + // now stay on sigle actions (*_translate), bu tmaybe later unified to + // a single transform with a single B2DHomMatrix to apply + virtual void transform_translate(const Point& rOffset); }; /// RotateFlyFrame3: Helper class when you want to make your SwFrame derivate @@ -290,6 +297,15 @@ public: // state when itz was necessary to reset them temporarily (see above) void resetAreaDefinitionsToTransformed( SwFrameAreaDefinition& rSwFrameAreaDefinition); + + // check if used + bool isTransformationUsed() const + { + return !maFrameAreaTransformation.isIdentity() || !maFramePrintAreaTransformation.isIdentity(); + } + + // transform by given B2DHomMatrix + void doTransform(const basegfx::B2DHomMatrix aTransform); }; /** diff --git a/sw/source/core/inc/notxtfrm.hxx b/sw/source/core/inc/notxtfrm.hxx index 43f020496599..0054078890a4 100644 --- a/sw/source/core/inc/notxtfrm.hxx +++ b/sw/source/core/inc/notxtfrm.hxx @@ -68,6 +68,9 @@ public: // RotateFlyFrame3 - Support for Transformations virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const override; virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const override; + + // RotateFlyFrame3 - Support for Transformations + virtual void transform_translate(const Point& rOffset) override; }; #endif diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx index 2c8cc422dd25..7a9aa676dfdc 100644 --- a/sw/source/core/layout/flylay.cxx +++ b/sw/source/core/layout/flylay.cxx @@ -41,6 +41,7 @@ #include <viewimp.hxx> #include <IDocumentSettingAccess.hxx> #include <IDocumentDrawModelAccess.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> using namespace ::com::sun::star; @@ -294,6 +295,25 @@ basegfx::B2DHomMatrix SwFlyFreeFrame::getFramePrintAreaTransformation() const return SwFlyFrame::getFramePrintAreaTransformation(); } +// RotateFlyFrame3 - Support for Transformations +void SwFlyFreeFrame::transform_translate(const Point& rOffset) +{ + // call parent - this will do the basic transform for SwRect(s) + // in the SwFrameAreaDefinition + SwFlyFrame::transform_translate(rOffset); + + // check if the Transformations need to be adapted + if(isTransformationUsed()) + { + const basegfx::B2DHomMatrix aTransform( + basegfx::utils::createTranslateB2DHomMatrix( + rOffset.X(), rOffset.Y())); + + // transform using TransformableSwFrame + doTransform(aTransform); + } +} + // RotateFlyFrame3 - outer frame double getFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame) { diff --git a/sw/source/core/layout/pagechg.cxx b/sw/source/core/layout/pagechg.cxx index 716642b03fa5..72f86fc8fd69 100644 --- a/sw/source/core/layout/pagechg.cxx +++ b/sw/source/core/layout/pagechg.cxx @@ -1927,19 +1927,9 @@ static void lcl_MoveAllLowers( SwFrame* pFrame, const Point& rOffset ) const SwRect aFrame( pFrame->getFrameArea() ); // first move the current frame - { - SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*pFrame); - - if (aFrm.Pos().X() != FAR_AWAY) - { - aFrm.Pos().X() += rOffset.X(); - } - - if (aFrm.Pos().Y() != FAR_AWAY) - { - aFrm.Pos().Y() += rOffset.Y(); - } - } + // RotateFlyFrame3: moved to transform_translate instead of + // direct modification to allow the SwFrame evtl. needed own reactions + pFrame->transform_translate(rOffset); // Don't forget accessibility: if( pFrame->IsAccessibleFrame() ) diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index 972083bd273d..a67a70d46c76 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -129,6 +129,23 @@ basegfx::B2DHomMatrix SwFrameAreaDefinition::getFramePrintAreaTransformation() c rFramePrintArea.Top() + rFrameArea.Top()); } +void SwFrameAreaDefinition::transform_translate(const Point& rOffset) +{ + // RotateFlyFrame3: default is to change the FrameArea, FramePrintArea needs no + // change since it is relative to FrameArea + SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); + + if (aFrm.Pos().X() != FAR_AWAY) + { + aFrm.Pos().X() += rOffset.X(); + } + + if (aFrm.Pos().Y() != FAR_AWAY) + { + aFrm.Pos().Y() += rOffset.Y(); + } +} + void TransformableSwFrame::createFrameAreaTransformations( const SwFrameAreaDefinition& rSwFrameAreaDefinition, double fRotation, @@ -255,6 +272,23 @@ void TransformableSwFrame::resetAreaDefinitionsToTransformed( rSwFrameAreaDefinition); } +// transform by given B2DHomMatrix +void TransformableSwFrame::doTransform(const basegfx::B2DHomMatrix aTransform) +{ + if(!aTransform.isIdentity()) + { + if(!maFrameAreaTransformation.isIdentity()) + { + maFrameAreaTransformation *= aTransform; + } + + if(!maFramePrintAreaTransformation.isIdentity()) + { + maFramePrintAreaTransformation *= aTransform; + } + } +} + SwFrame::SwFrame( SwModify *pMod, SwFrame* pSib ) : SwFrameAreaDefinition(), SwClient( pMod ), commit bc4432846a8142b5e5d559eff392c28c888260ba Author: Armin Le Grand <armin.le.gr...@cib.de> Date: Wed Nov 8 14:00:57 2017 +0100 RotateFlyFrame3: Isolated functionality and automations Isolated tooling stuff for SwFrames that support Transformations to TransformableSwFrame, adapted all usages. Developed functionality to reset temporarily the already adapted SwFrame of the outer frame to non-rotated to mate the layouting work. Made the outer frame being layouted always first. Change-Id: Ia60a971b8eaa28859d0f2a5243eabf68fe949846 diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx index 1accccb8e492..b4fb5485d02e 100644 --- a/sw/source/core/doc/notxtfrm.cxx +++ b/sw/source/core/doc/notxtfrm.cxx @@ -144,8 +144,7 @@ static void lcl_PaintReplacement( const SwRect &rRect, const OUString &rText, SwNoTextFrame::SwNoTextFrame(SwNoTextNode * const pNode, SwFrame* pSib ) : SwContentFrame( pNode, pSib ), - maFrameAreaTransformation(), - maFramePrintAreaTransformation() + TransformableSwFrame() { mnFrameType = SwFrameType::NoTxt; } @@ -472,11 +471,28 @@ const Size& SwNoTextFrame::GetSize() const void SwNoTextFrame::MakeAll(vcl::RenderContext* pRenderContext) { - if(GetUpper() && !GetUpper()->isFrameAreaDefinitionValid()) + // RotateFlyFrame3 - inner frame. Get rotation and check if used + const double fRotation(getFrameRotation()); + const bool bRotated(!basegfx::fTools::equalZero(fRotation)); + SwFlyFreeFrame* pUpperFly(dynamic_cast< SwFlyFreeFrame* >(GetUpper())); + + if(bRotated && pUpperFly && !pUpperFly->isFrameAreaDefinitionValid()) + { + // RotateFlyFrame3: outer frame *needs* to be layouted first, force this by calling + // it's ::Calc directly + pUpperFly->Calc(pRenderContext); + } + + if(bRotated && pUpperFly) { - // outer frame *needs* to be layouted first, force this by calling - // ::Calc directly - GetUpper()->Calc(pRenderContext); + // Reset outer frame to unrotated state. This is necessary to make the + // layouting below work as currently implemented in Writer. As expected + // using Transformations allows to do this on the fly due to all information + // being included there. + // The full solution would be to adapt the whole layouting + // process of Writer to take care of Transformations, but that + // is currently beyond scope + pUpperFly->resetAreaDefinitionsToUntransformed(*pUpperFly); } SwContentNotify aNotify( this ); @@ -504,66 +520,46 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* pRenderContext) // RotateFlyFrame3 - inner frame // After the unrotated layout is finished, apply possible set rotation to it - const double fRotation(getFrameRotation()); - - if(basegfx::fTools::equalZero(fRotation)) + if(!bRotated) { // reset transformations to show that they are not used - maFrameAreaTransformation.identity(); - maFramePrintAreaTransformation.identity(); + resetLocalAreaTransformations(); } else { const bool bMeValid(isFrameAreaDefinitionValid()); - const bool bUpperValid(!GetUpper() || GetUpper()->isFrameAreaDefinitionValid()); - if(bMeValid && bUpperValid) + if(pUpperFly) + { + // restore outer frame back to Transformed state, that means + // set the SwFrameAreaDefinition(s) back to BoundAreas of + // the transformed SwFrame. All needed information is part + // of the already correctly created Transformations of the + // upper frame, so it can bre re-created on the fly + pUpperFly->resetAreaDefinitionsToTransformed(*pUpperFly); + } + + if(bMeValid) { // 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()); - updateTransformationsAndAreas( + updateTransformationsAndFrameAreaDefinitions( + *this, fRotation, aB2DCenter); - - if(GetUpper()) - { - SwFlyFreeFrame *pFly = dynamic_cast< SwFlyFreeFrame* >(GetUpper()); - - if(pFly) - { - pFly->updateTransformationsAndAreas( - fRotation, - aB2DCenter); - } - } } } } -void SwNoTextFrame::updateTransformationsAndAreas( - double fRotation, - const basegfx::B2DPoint& rCenter) -{ - createFrameAreaTransformations( - maFrameAreaTransformation, - maFramePrintAreaTransformation, - fRotation, - rCenter); - - setFrameAreaDefinitionsToBoundRangesOfTransformations( - maFrameAreaTransformation, - maFramePrintAreaTransformation); -} - // RotateFlyFrame3 - Support for Transformations - outer frame basegfx::B2DHomMatrix SwNoTextFrame::getFrameAreaTransformation() const { - if(!maFrameAreaTransformation.isIdentity()) + if(!getLocalFrameAreaTransformation().isIdentity()) { // use pre-created transformation - return maFrameAreaTransformation; + return getLocalFrameAreaTransformation(); } // call parent @@ -572,10 +568,10 @@ basegfx::B2DHomMatrix SwNoTextFrame::getFrameAreaTransformation() const basegfx::B2DHomMatrix SwNoTextFrame::getFramePrintAreaTransformation() const { - if(!maFramePrintAreaTransformation.isIdentity()) + if(!getLocalFramePrintAreaTransformation().isIdentity()) { // use pre-created transformation - return maFramePrintAreaTransformation; + return getLocalFramePrintAreaTransformation(); } // call parent diff --git a/sw/source/core/inc/flyfrms.hxx b/sw/source/core/inc/flyfrms.hxx index e202c9733d88..b4f66f9d22d3 100644 --- a/sw/source/core/inc/flyfrms.hxx +++ b/sw/source/core/inc/flyfrms.hxx @@ -26,9 +26,11 @@ // #i28701# class SwFlyAtContentFrame; +double getFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame); + // Base class for those Flys that can "move freely" or better that are not // bound in Content. -class SwFlyFreeFrame : public SwFlyFrame +class SwFlyFreeFrame : public SwFlyFrame, public TransformableSwFrame { private: // #i34753# - flag for at-page anchored Writer fly frames @@ -41,12 +43,6 @@ private: 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 @@ -61,6 +57,11 @@ private: */ bool HasEnvironmentAutoSize() const; + // RotateFlyFrame3 - Support for outer Frame of a SwGrfNode + // Only for local data extraction. To uniquely access information + // for local transformation, use getFrameArea(Print)Transformation + double getFrameRotation() const; + protected: // #i28701# - new friend class <SwFlyNotify> for access to // method <NotifyBackground> @@ -124,17 +125,9 @@ public: */ virtual bool IsFormatPossible() const override; - // RotateFlyFrame3 - Support for Transformations for outer Frame of a SwGrfNode - basegfx::B2DHomMatrix getFrameAreaTransformation() const; - basegfx::B2DHomMatrix getFramePrintAreaTransformation() const; - void updateTransformationsAndAreas( - double fRotation, - const basegfx::B2DPoint& rCenter); - - // RotateFlyFrame3 - Support for outer Frame of a SwGrfNode - // Only for local data extraction. To uniquely access information - // for local transformation, use getFrameArea(Print)Transformation - double getFrameRotation() const; + // RotateFlyFrame3 - Support for Transformations + virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const override; + virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const override; }; // 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 d02426976204..2d0a1c321372 100644 --- a/sw/source/core/inc/frame.hxx +++ b/sw/source/core/inc/frame.hxx @@ -144,20 +144,6 @@ 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(); @@ -208,6 +194,102 @@ public: ~FramePrintAreaWriteAccess(); void setSwRect(const SwRect& rNew) { *reinterpret_cast< SwRect* >(this) = rNew; } }; + + // 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) + virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const; + virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const; +}; + +/// 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 +class SW_DLLPUBLIC TransformableSwFrame +{ +private: + // FrameAreaTransformation and FramePrintAreaTransformation + // here when more than translate/scale is used (e.g. rotation) + basegfx::B2DHomMatrix maFrameAreaTransformation; + basegfx::B2DHomMatrix maFramePrintAreaTransformation; + + // helper method to create FrameAreaTransformations based on the + // curent FrameAreaDefinition + void createFrameAreaTransformations( + const SwFrameAreaDefinition& rSwFrameAreaDefinition, + double fRotation, + const basegfx::B2DPoint& rCenter); + + // helper method to set FrameAreaDefinitions based on given + // transformations + void setFrameAreaDefinitionsToBoundRangesOfTransformations( + SwFrameAreaDefinition& rSwFrameAreaDefinition); + +protected: + // Full update of Transformations and BoundAreas: + // - Re-create Transformations based on SwRect(s) from the + // given SwFrameAreaDefinition. + // - Based on that, create BoundRanges for the Transformations + // and use as new SwRect(s) for the given SwFrameAreaDefinition. + void updateTransformationsAndFrameAreaDefinitions( + SwFrameAreaDefinition& rSwFrameAreaDefinition, + double fRotation, + const basegfx::B2DPoint& rCenter); + + void setLocalFrameAreaTransformation(const basegfx::B2DHomMatrix& rNew) + { + maFrameAreaTransformation = rNew; + } + + void setLocalFramePrintAreaTransformation(const basegfx::B2DHomMatrix& rNew) + { + maFramePrintAreaTransformation = rNew; + } + + void resetLocalAreaTransformations() + { + maFrameAreaTransformation.identity(); + maFramePrintAreaTransformation.identity(); + } + +public: + TransformableSwFrame() + : maFrameAreaTransformation(), + maFramePrintAreaTransformation() + { + } + + // Support for Transformations for inner frame of a SwGrfNode + const basegfx::B2DHomMatrix& getLocalFrameAreaTransformation() const + { + return maFrameAreaTransformation; + } + + const basegfx::B2DHomMatrix& getLocalFramePrintAreaTransformation() const + { + return maFramePrintAreaTransformation; + } + + // This method allows to reset the SwRect(s) in the + // given SwFrameAreaDefinition which are already apapted to + // Transformation and thus have a changed BoundArea back to + // the untransformed state. Only the SwRect(s) are changed + // back, not the transformations. As expected from using + // Transformations, these contain all the necessary + // information + void resetAreaDefinitionsToUntransformed( + SwFrameAreaDefinition& rSwFrameAreaDefinition); + + // Re-Creates the SwRect(s) as BoundAreas based on the current + // Transformations, useful to set back the SwRect(s) to Transformed + // state when itz was necessary to reset them temporarily (see above) + void resetAreaDefinitionsToTransformed( + SwFrameAreaDefinition& rSwFrameAreaDefinition); }; /** @@ -834,17 +916,6 @@ public: virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const; void dumpChildrenAsXml(xmlTextWriterPtr writer) const; bool IsCollapse() 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 fa64a1be3214..43f020496599 100644 --- a/sw/source/core/inc/notxtfrm.hxx +++ b/sw/source/core/inc/notxtfrm.hxx @@ -26,17 +26,10 @@ class OutputDevice; class SwBorderAttrs; struct SwCursorMoveState; -class SwNoTextFrame: public SwContentFrame +class SwNoTextFrame: public SwContentFrame, public TransformableSwFrame { private: 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; @@ -45,9 +38,16 @@ private: virtual void DestroyImpl() override; virtual ~SwNoTextFrame() override; + // RotateFlyFrame3 - Support for inner frame of a SwGrfNode. + // Only for local data extraction. To uniquely access information + // for local transformation, use getFrameArea(Print)Transformation. + friend double getFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame); + double getFrameRotation() const; + protected: virtual void MakeAll(vcl::RenderContext* pRenderContext) override; virtual void Modify( const SfxPoolItem*, const SfxPoolItem* ) override; + public: SwNoTextFrame( SwNoTextNode * const, SwFrame* ); @@ -65,17 +65,9 @@ public: void StopAnimation( OutputDevice* = nullptr ) const; bool HasAnimation() const; - // RotateFlyFrame3 - Support for Transformations for inner frame of a SwGrfNode - basegfx::B2DHomMatrix getFrameAreaTransformation() const; - basegfx::B2DHomMatrix getFramePrintAreaTransformation() const; - void updateTransformationsAndAreas( - double fRotation, - const basegfx::B2DPoint& rCenter); - - // RotateFlyFrame3 - Support for inner frame of a SwGrfNode. - // Only for local data extraction. To uniquely access information - // for local transformation, use getFrameArea(Print)Transformation. - double getFrameRotation() const; + // RotateFlyFrame3 - Support for Transformations + virtual basegfx::B2DHomMatrix getFrameAreaTransformation() const override; + virtual basegfx::B2DHomMatrix getFramePrintAreaTransformation() const override; }; #endif diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx index 0fdf70face11..2c8cc422dd25 100644 --- a/sw/source/core/layout/flylay.cxx +++ b/sw/source/core/layout/flylay.cxx @@ -46,14 +46,12 @@ using namespace ::com::sun::star; SwFlyFreeFrame::SwFlyFreeFrame( SwFlyFrameFormat *pFormat, SwFrame* pSib, SwFrame *pAnch ) : SwFlyFrame( pFormat, pSib, pAnch ), + TransformableSwFrame(), // #i34753# mbNoMakePos( false ), // #i37068# mbNoMoveOnCheckClip( false ), - maUnclippedFrame( ), - // RotateFlyFrame3 - maFrameAreaTransformation(), - maFramePrintAreaTransformation() + maUnclippedFrame( ) { } @@ -110,9 +108,11 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) } if ( !GetAnchorFrame() || IsLocked() || IsColLocked() ) + { return; + } - // #i28701# - use new method <GetPageFrame()> + // #i28701# - use new method <GetPageFrame()> if( !GetPageFrame() && GetAnchorFrame() && GetAnchorFrame()->IsInFly() ) { SwFlyFrame* pFly = AnchorFrame()->FindFlyFrame(); @@ -233,12 +233,29 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) // Do not refresh transforms/Areas self here, this will be done // when inner and outer frame are layouted, in SwNoTextFrame::MakeAll const double fRotation(getFrameRotation()); + const bool bRotated(!basegfx::fTools::equalZero(fRotation)); - if(basegfx::fTools::equalZero(fRotation)) + if(!bRotated) { // reset transformations to show that they are not used - maFrameAreaTransformation.identity(); - maFramePrintAreaTransformation.identity(); + resetLocalAreaTransformations(); + } + else + { + // RotateFlyFrame3: Safe changes locally + const bool bMeValid(isFrameAreaDefinitionValid()); + + if(bMeValid) + { + // get center from outer frame (layout frame) to be on the safe side + const Point aCenter(getFrameArea().Center()); + const basegfx::B2DPoint aB2DCenter(aCenter.X(), aCenter.Y()); + + updateTransformationsAndFrameAreaDefinitions( + *this, + fRotation, + aB2DCenter); + } } Unlock(); @@ -252,28 +269,13 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) #endif } -void SwFlyFreeFrame::updateTransformationsAndAreas( - double fRotation, - const basegfx::B2DPoint& rCenter) -{ - createFrameAreaTransformations( - maFrameAreaTransformation, - maFramePrintAreaTransformation, - fRotation, - rCenter); - - setFrameAreaDefinitionsToBoundRangesOfTransformations( - maFrameAreaTransformation, - maFramePrintAreaTransformation); -} - // RotateFlyFrame3 - Support for Transformations - outer frame basegfx::B2DHomMatrix SwFlyFreeFrame::getFrameAreaTransformation() const { - if(!maFrameAreaTransformation.isIdentity()) + if(!getLocalFrameAreaTransformation().isIdentity()) { // use pre-created transformation - return maFrameAreaTransformation; + return getLocalFrameAreaTransformation(); } // call parent @@ -282,10 +284,10 @@ basegfx::B2DHomMatrix SwFlyFreeFrame::getFrameAreaTransformation() const basegfx::B2DHomMatrix SwFlyFreeFrame::getFramePrintAreaTransformation() const { - if(!maFramePrintAreaTransformation.isIdentity()) + if(!getLocalFramePrintAreaTransformation().isIdentity()) { // use pre-created transformation - return maFramePrintAreaTransformation; + return getLocalFramePrintAreaTransformation(); } // call parent @@ -293,6 +295,11 @@ basegfx::B2DHomMatrix SwFlyFreeFrame::getFramePrintAreaTransformation() const } // RotateFlyFrame3 - outer frame +double getFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame) +{ + return rNoTextFrame.getFrameRotation(); +} + double SwFlyFreeFrame::getFrameRotation() const { // SwLayoutFrame::Lower() != SwFrame::GetLower(), but SwFrame::GetLower() @@ -301,7 +308,7 @@ double SwFlyFreeFrame::getFrameRotation() const if(nullptr != pSwNoTextFrame) { - return pSwNoTextFrame->getFrameRotation(); + return getFrameRotation_from_SwNoTextFrame(*pSwNoTextFrame); } // no rotation diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index 5f766af16fce..972083bd273d 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -105,11 +105,34 @@ SwFrameAreaDefinition::FramePrintAreaWriteAccess::~FramePrintAreaWriteAccess() } } -void SwFrameAreaDefinition::createFrameAreaTransformations( - basegfx::B2DHomMatrix& rFrameAreaTransformation, - basegfx::B2DHomMatrix& rFramePrintAreaTransformation, +// RotateFlyFrame3 - Support for Transformations +basegfx::B2DHomMatrix SwFrameAreaDefinition::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 SwFrameAreaDefinition::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()); +} + +void TransformableSwFrame::createFrameAreaTransformations( + const SwFrameAreaDefinition& rSwFrameAreaDefinition, double fRotation, - const basegfx::B2DPoint& rCenter) const + const basegfx::B2DPoint& rCenter) { // save Transformations to rFrameAreaTransformation and // rFramePrintAreaTransformation. Do not forget that PrintArea @@ -119,75 +142,117 @@ void SwFrameAreaDefinition::createFrameAreaTransformations( 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()); + const SwRect& rFrameArea(rSwFrameAreaDefinition.getFrameArea()); + const SwRect& rFramePrintArea(rSwFrameAreaDefinition.getFramePrintArea()); + + setLocalFrameAreaTransformation( + aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix( + rFrameArea.Width(), rFrameArea.Height(), + rFrameArea.Left(), rFrameArea.Top())); + setLocalFramePrintAreaTransformation( + aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix( + rFramePrintArea.Width(), rFramePrintArea.Height(), + rFramePrintArea.Left() + rFrameArea.Left(), rFramePrintArea.Top() + rFrameArea.Top())); } -void SwFrameAreaDefinition::setFrameAreaDefinitionsToBoundRangesOfTransformations( - const basegfx::B2DHomMatrix& rFrameAreaTransformation, - const basegfx::B2DHomMatrix& rFramePrintAreaTransformation) +void TransformableSwFrame::setFrameAreaDefinitionsToBoundRangesOfTransformations( + SwFrameAreaDefinition& rSwFrameAreaDefinition) { - if(!rFrameAreaTransformation.isIdentity()) + if(!getLocalFrameAreaTransformation().isIdentity()) { basegfx::B2DRange aRangeFrameArea(0.0, 0.0, 1.0, 1.0); - - aRangeFrameArea.transform(rFrameAreaTransformation); - + aRangeFrameArea.transform(getLocalFrameAreaTransformation()); const SwRect aNewFrm( basegfx::fround(aRangeFrameArea.getMinX()), basegfx::fround(aRangeFrameArea.getMinY()), basegfx::fround(aRangeFrameArea.getWidth()), basegfx::fround(aRangeFrameArea.getHeight())); - if(aNewFrm != getFrameArea()) + if(aNewFrm != rSwFrameAreaDefinition.getFrameArea()) { - maFrameArea = aNewFrm; + SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(rSwFrameAreaDefinition); + aFrm.setSwRect(aNewFrm); } } - if(!rFramePrintAreaTransformation.isIdentity()) + if(!getLocalFramePrintAreaTransformation().isIdentity()) { basegfx::B2DRange aRangeFramePrintArea(0.0, 0.0, 1.0, 1.0); - - aRangeFramePrintArea.transform(rFramePrintAreaTransformation); - + aRangeFramePrintArea.transform(getLocalFramePrintAreaTransformation()); const SwRect aNewPrt( - basegfx::fround(aRangeFramePrintArea.getMinX()) - getFrameArea().Left(), - basegfx::fround(aRangeFramePrintArea.getMinY()) - getFrameArea().Top(), + basegfx::fround(aRangeFramePrintArea.getMinX()) - rSwFrameAreaDefinition.getFrameArea().Left(), + basegfx::fround(aRangeFramePrintArea.getMinY()) - rSwFrameAreaDefinition.getFrameArea().Top(), basegfx::fround(aRangeFramePrintArea.getWidth()), basegfx::fround(aRangeFramePrintArea.getHeight())); - if(aNewPrt != getFramePrintArea()) + if(aNewPrt != rSwFrameAreaDefinition.getFramePrintArea()) { - maFramePrintArea = aNewPrt; + SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(rSwFrameAreaDefinition); + aPrt.setSwRect(aNewPrt); } } } -// RotateFlyFrame3 - Support for Transformations -basegfx::B2DHomMatrix SwFrame::getFrameAreaTransformation() const +void TransformableSwFrame::updateTransformationsAndFrameAreaDefinitions( + SwFrameAreaDefinition& rSwFrameAreaDefinition, + double fRotation, + const basegfx::B2DPoint& rCenter) { - // default implementation hands out FrameArea (outer frame) - const SwRect& rFrameArea(getFrameArea()); + createFrameAreaTransformations( + rSwFrameAreaDefinition, + fRotation, + rCenter); - return basegfx::utils::createScaleTranslateB2DHomMatrix( - rFrameArea.Width(), rFrameArea.Height(), - rFrameArea.Left(), rFrameArea.Top()); + setFrameAreaDefinitionsToBoundRangesOfTransformations( + rSwFrameAreaDefinition); } -basegfx::B2DHomMatrix SwFrame::getFramePrintAreaTransformation() const +void TransformableSwFrame::resetAreaDefinitionsToUntransformed( + SwFrameAreaDefinition& rSwFrameAreaDefinition) { - // default implementation hands out FramePrintArea (outer frame) - // Take into account that FramePrintArea is relative to FrameArea - const SwRect& rFrameArea(getFrameArea()); - const SwRect& rFramePrintArea(getFramePrintArea()); + // calculate center of object + basegfx::B2DPoint aCenter(getLocalFrameAreaTransformation() * basegfx::B2DPoint(0.5, 0.5)); - return basegfx::utils::createScaleTranslateB2DHomMatrix( - rFramePrintArea.Width(), rFramePrintArea.Height(), - rFramePrintArea.Left() + rFrameArea.Left(), - rFramePrintArea.Top() + rFrameArea.Top()); + if(!getLocalFrameAreaTransformation().isIdentity()) + { + basegfx::B2DTuple aScale, aTranslate; + double fRotate(0.0), fShearX(0.0); + getLocalFrameAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX); + const SwRect aNewFrm( + basegfx::fround(aCenter.getX() - (0.5 * aScale.getX())), + basegfx::fround(aCenter.getY() - (0.5 * aScale.getY())), + basegfx::fround(aScale.getX()), + basegfx::fround(aScale.getY())); + + if(aNewFrm != rSwFrameAreaDefinition.getFrameArea()) + { + SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(rSwFrameAreaDefinition); + aFrm.setSwRect(aNewFrm); + } + } + + if(!getLocalFramePrintAreaTransformation().isIdentity()) + { + basegfx::B2DTuple aScale, aTranslate; + double fRotate(0.0), fShearX(0.0); + getLocalFramePrintAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX); + const SwRect aNewPrt( + basegfx::fround(aCenter.getX() - (0.5 * aScale.getX())) - rSwFrameAreaDefinition.getFrameArea().Left(), + basegfx::fround(aCenter.getY() - (0.5 * aScale.getY())) - rSwFrameAreaDefinition.getFrameArea().Top(), + basegfx::fround(aScale.getX()), + basegfx::fround(aScale.getY())); + + if(aNewPrt != rSwFrameAreaDefinition.getFramePrintArea()) + { + SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(rSwFrameAreaDefinition); + aPrt.setSwRect(aNewPrt); + } + } +} + +void TransformableSwFrame::resetAreaDefinitionsToTransformed( + SwFrameAreaDefinition& rSwFrameAreaDefinition) +{ + setFrameAreaDefinitionsToBoundRangesOfTransformations( + rSwFrameAreaDefinition); } SwFrame::SwFrame( SwModify *pMod, SwFrame* pSib ) commit 9b136d5e69b86f81785d6ed9bfe3059a5ef97a2c Author: Armin Le Grand <armin.le.gr...@cib.de> Date: Tue Nov 7 18:18:44 2017 +0100 RotateFlyFrame: Late-Updating of Areas When Layouting the update of the Areas is needed, but during layout needs to be stable on the unrotated values. Hard to find the right spot to do this, decided to use the inner/outer frame, layout both, and trigger the updates when the inner frame is layouted to non- rotated Areas for inner and outer frame. Still not sure oif this will be correct, but is close to working well. Some repaints/updates missing Change-Id: I3d7dcbf624f3f32392e5e98420cb348d11d7d322 diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx index 4a040cedfb9d..1accccb8e492 100644 --- a/sw/source/core/doc/notxtfrm.cxx +++ b/sw/source/core/doc/notxtfrm.cxx @@ -470,8 +470,15 @@ const Size& SwNoTextFrame::GetSize() const return pFly->getFramePrintArea().SSize(); } -void SwNoTextFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) +void SwNoTextFrame::MakeAll(vcl::RenderContext* pRenderContext) { + if(GetUpper() && !GetUpper()->isFrameAreaDefinitionValid()) + { + // outer frame *needs* to be layouted first, force this by calling + // ::Calc directly + GetUpper()->Calc(pRenderContext); + } + SwContentNotify aNotify( this ); SwBorderAttrAccess aAccess( SwFrame::GetCache(), this ); const SwBorderAttrs &rAttrs = *aAccess.Get(); @@ -495,9 +502,9 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) } } - // RotateFlyFrame3 - outer frame + // RotateFlyFrame3 - inner frame // After the unrotated layout is finished, apply possible set rotation to it - const double fRotation(getRotation()); + const double fRotation(getFrameRotation()); if(basegfx::fTools::equalZero(fRotation)) { @@ -507,25 +514,49 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) } 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); + const bool bMeValid(isFrameAreaDefinitionValid()); + const bool bUpperValid(!GetUpper() || GetUpper()->isFrameAreaDefinitionValid()); + + if(bMeValid && bUpperValid) + { + // 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()); + + updateTransformationsAndAreas( + fRotation, + aB2DCenter); + + if(GetUpper()) + { + SwFlyFreeFrame *pFly = dynamic_cast< SwFlyFreeFrame* >(GetUpper()); + + if(pFly) + { + pFly->updateTransformationsAndAreas( + fRotation, + aB2DCenter); + } + } + } } } +void SwNoTextFrame::updateTransformationsAndAreas( + double fRotation, + const basegfx::B2DPoint& rCenter) +{ + createFrameAreaTransformations( + maFrameAreaTransformation, + maFramePrintAreaTransformation, + fRotation, + rCenter); + + setFrameAreaDefinitionsToBoundRangesOfTransformations( + maFrameAreaTransformation, + maFramePrintAreaTransformation); +} + // RotateFlyFrame3 - Support for Transformations - outer frame basegfx::B2DHomMatrix SwNoTextFrame::getFrameAreaTransformation() const { @@ -551,9 +582,9 @@ basegfx::B2DHomMatrix SwNoTextFrame::getFramePrintAreaTransformation() const return SwContentFrame::getFramePrintAreaTransformation(); } -// RotateFlyFrame3 - outer frame +// RotateFlyFrame3 - inner frame // Check if we contain a SwGrfNode and get possible rotation from it -double SwNoTextFrame::getRotation() const +double SwNoTextFrame::getFrameRotation() const { const SwNoTextNode* pSwNoTextNode(nullptr != GetNode() ? GetNode()->GetNoTextNode() : nullptr); @@ -571,8 +602,8 @@ double SwNoTextFrame::getRotation() const } } - // call parent - return SwContentFrame::getRotation(); + // no rotation + return 0.0; } /** Calculate the Bitmap's site, if needed */ @@ -735,12 +766,12 @@ void SwNoTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) // 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()) { GetUpper()->InvalidateAll_(); } + + InvalidateAll_(); ... etc. - the rest is truncated _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits