diff options
author | Armin Le Grand <Armin.Le.Grand@cib.de> | 2017-11-15 13:56:38 +0100 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@cib.de> | 2017-11-18 13:07:46 +0100 |
commit | d74b26b41bfea3ba7a1834953b2bfe9b7ff0d70f (patch) | |
tree | 9e9684d1481df209e585ab08b079de5bfa86a466 /sw/source | |
parent | 1059e234f4b3b3f6b770b2e4d973923e54e7045b (diff) |
RotateFlyFrame3: Corrected interactive Crop
To correct interactive Crop in transformed states, I had to
rework some stuff involved that anyways was in a non optimal
state. Added functionality to translate the object to make
Crop seem to work more seamlessly. Some mapping was needed
to make the Cropped, transformed object to be in the correct
relative position to the uncropped, untransfomed one.
Restructured TransformableSwFrame to directly re-create
last non-transformed SwFrame(s) from the SwFrameAreaDefinition
from the current Transformations, offering the untransformed
SwRect(s) now for usage.
Identified and corrected error when FlyFrame was translated
using keyboard, the accessing method needed to adapt position
in the transformed case.
Started to look at Contour stuff, adapted a set contour to be
correctly used by adapting it as needed in the transformed case.
Change-Id: I0d5f14958bcd6f826b9abd53f1f47b7d0bc5a0e2
Diffstat (limited to 'sw/source')
-rw-r--r-- | sw/source/core/draw/dflyobj.cxx | 134 | ||||
-rw-r--r-- | sw/source/core/frmedt/fefly1.cxx | 19 | ||||
-rw-r--r-- | sw/source/core/inc/dflyobj.hxx | 4 | ||||
-rw-r--r-- | sw/source/core/inc/flyfrms.hxx | 1 | ||||
-rw-r--r-- | sw/source/core/inc/frame.hxx | 35 | ||||
-rw-r--r-- | sw/source/core/layout/fly.cxx | 32 | ||||
-rw-r--r-- | sw/source/core/layout/wsfrm.cxx | 68 |
7 files changed, 203 insertions, 90 deletions
diff --git a/sw/source/core/draw/dflyobj.cxx b/sw/source/core/draw/dflyobj.cxx index e1035a3754fa..a4466f1f9085 100644 --- a/sw/source/core/draw/dflyobj.cxx +++ b/sw/source/core/draw/dflyobj.cxx @@ -634,9 +634,9 @@ 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 + // When we have a change and are in transformed state (e.g. rotation used), + // we need to fall back to the un-transformed state to keep the old code below + // working properly. Restore FrameArea and use aOutRect from old FrameArea. TransformableSwFrame* pTransformableSwFrame(static_cast<SwFlyFreeFrame*>(GetFlyFrame())->getTransformableSwFrame()); pTransformableSwFrame->restoreFrameAreas(); aOutRect = GetFlyFrame()->getFrameArea().SVRect(); @@ -788,7 +788,7 @@ void SwVirtFlyDrawObj::NbcMove(const Size& rSiz) } -void SwVirtFlyDrawObj::NbcCrop(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +void SwVirtFlyDrawObj::NbcCrop(const basegfx::B2DPoint& rRef, double fxFact, double fyFact) { // Get Wrt Shell SwWrtShell *pSh = dynamic_cast<SwWrtShell*>( GetFlyFrame()->getRootFrame()->GetCurrShell() ); @@ -805,50 +805,65 @@ void SwVirtFlyDrawObj::NbcCrop(const Point& rRef, const Fraction& xFact, const F return; } + // Get graphic object size in 100th of mm + 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 ; + } + 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 + // When we have a change and are in transformed state (e.g. rotation used), + // we need to fall back to the un-transformed state to keep the old code below + // working properly. Restore FrameArea and use aOutRect from old FrameArea. TransformableSwFrame* pTransformableSwFrame(static_cast<SwFlyFreeFrame*>(GetFlyFrame())->getTransformableSwFrame()); pTransformableSwFrame->restoreFrameAreas(); aOutRect = GetFlyFrame()->getFrameArea().SVRect(); } // Compute old and new rect. This will give us the deformation to apply to - // the object to crop - const long nOldWidth(aOutRect.GetWidth()); - const long nOldHeight(aOutRect.GetHeight()); + // the object to crop. OldRect is the inner frame, see getFullDragClone() + // below where getFramePrintAreaTransformation is used as object geometry for Crop + const tools::Rectangle aOldRect( + GetFlyFrame()->getFrameArea().TopLeft() + GetFlyFrame()->getFramePrintArea().TopLeft(), + GetFlyFrame()->getFramePrintArea().SSize()); + const long nOldWidth(aOldRect.GetWidth()); + const long nOldHeight(aOldRect.GetHeight()); if (!nOldWidth || !nOldHeight) { return; } - tools::Rectangle aNewRect( aOutRect ); - ResizeRect( aNewRect, rRef, xFact, yFact ); - - // Get graphic object size in 100th of mm - 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); - } + // rRef is relative to the Crop-Action, si in X/Y-Ranges of [0.0 .. 1.0], + // to get the correct absolute position, transform using the old Rect + const Point aRef( + aOldRect.Left() + basegfx::fround(aOldRect.GetWidth() * rRef.getX()), + aOldRect.Top() + basegfx::fround(aOldRect.GetHeight() * rRef.getY())); - if( aGraphicSize.Width() == 0 || aGraphicSize.Height() == 0 ) - { - return ; - } + // appy transformation, use old ResizeRect for now + tools::Rectangle aNewRect( aOldRect ); + ResizeRect( + aNewRect, + aRef, + Fraction(fxFact), + Fraction(fyFact)); // Get old values for crop in 10th of mm SfxItemSet aSet( pSh->GetAttrPool(), svl::Items<RES_GRFATR_CROPGRF, RES_GRFATR_CROPGRF>{} ); @@ -865,10 +880,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() - aOutRect.Left(); - sal_Int32 nDiffTop = aNewRect.Top() - aOutRect.Top(); - sal_Int32 nDiffRight = aNewRect.Right() - aOutRect.Right(); - sal_Int32 nDiffBottom = aNewRect.Bottom() - aOutRect.Bottom(); + 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(); // Compute new values in 10th of mm sal_Int32 nLeftCrop = static_cast<sal_Int32>( aCropRectangle.Left() + nDiffLeft * fScaleX ); @@ -878,7 +893,7 @@ void SwVirtFlyDrawObj::NbcCrop(const Point& rRef, const Fraction& xFact, const F // Apply values pSh->StartAllAction(); -// pSh->StartUndo(SwUndoId::START); + // pSh->StartUndo(SwUndoId::START); // Set new crop values in twips aCrop.SetLeft (convertMm100ToTwip(nLeftCrop)); @@ -890,15 +905,21 @@ void SwVirtFlyDrawObj::NbcCrop(const Point& rRef, const Fraction& xFact, const F // Set new frame size SwFrameFormat *pFormat = GetFormat(); SwFormatFrameSize aSz( pFormat->GetFrameSize() ); - aSz.SetWidth(aNewRect.GetWidth()); - aSz.SetHeight(aNewRect.GetHeight()); + const long aNewWidth(aNewRect.GetWidth() + (aOutRect.GetWidth() - aOldRect.GetWidth())); + const long aNewHeight(aNewRect.GetHeight() + (aOutRect.GetHeight() - aOldRect.GetHeight())); + aSz.SetWidth(aNewWidth); + aSz.SetHeight(aNewHeight); pFormat->GetDoc()->SetAttr( aSz, *pFormat ); + // add move - to make result look better. Fill with defaults + // for the untransformed case + Point aNewTopLeft(aNewRect.TopLeft()); + const Point aOldTopLeft(aOldRect.TopLeft()); + 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) + // Need to correct the NewTopLeft position in transformed state to make + // the interaction look correct. First, extract rotation basegfx::B2DVector aScale, aTranslate; double fRotate, fShearX; GetFlyFrame()->getFrameAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX); @@ -922,22 +943,22 @@ void SwVirtFlyDrawObj::NbcCrop(const Point& rRef, const Fraction& xFact, const F // Create the new TopLeft of the unrotated, cropped object by creating // as if re-rceating the unrotated geometry - const Point aNewTopLeft( + aNewTopLeft = Point( 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())); + // check if we have movement and execute if yes + const Size aDeltaMove( + aNewTopLeft.X() - aOldTopLeft.X(), + aNewTopLeft.Y() - aOldTopLeft.Y()); - if(0 != aDeltaMove.Width() || 0 != aDeltaMove.Height()) - { - NbcMove(aDeltaMove); - } + if(0 != aDeltaMove.Width() || 0 != aDeltaMove.Height()) + { + NbcMove(aDeltaMove); } -// pSh->EndUndo(SwUndoId::END); + // pSh->EndUndo(SwUndoId::END); pSh->EndAllAction(); } @@ -979,13 +1000,14 @@ void SwVirtFlyDrawObj::NbcResize(const Point& rRef, const Fraction& xFact, const basegfx::B2DVector aScale, aTranslate; double fRotate, fShearX; aNewMat.decompose(aScale, aTranslate, fRotate, fShearX); + const basegfx::B2DVector aAbsScale(basegfx::absolute(aScale)); - // create new modified OutRect + // create new modified, but untransformed OutRect aOutRect = tools::Rectangle( - basegfx::fround(aCenter.getX() - (0.5 * aScale.getX())), - basegfx::fround(aCenter.getY() - (0.5 * aScale.getY())), - basegfx::fround(aCenter.getX() + (0.5 * aScale.getX())), - basegfx::fround(aCenter.getY() + (0.5 * aScale.getY()))); + basegfx::fround(aCenter.getX() - (0.5 * aAbsScale.getX())), + basegfx::fround(aCenter.getY() - (0.5 * aAbsScale.getY())), + basegfx::fround(aCenter.getX() + (0.5 * aAbsScale.getX())), + basegfx::fround(aCenter.getY() + (0.5 * aAbsScale.getY()))); // restore FrameAreas so that actions below not adapted to new // full transformations take the correct actions @@ -1115,9 +1137,9 @@ void SwVirtFlyDrawObj::Resize(const Point& rRef, GetFormat()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false); } -void SwVirtFlyDrawObj::Crop(const Point& rRef, const Fraction& xFact, const Fraction& yFact) +void SwVirtFlyDrawObj::Crop(const basegfx::B2DPoint& rRef, double fxFact, double fyFact) { - NbcCrop( rRef, xFact, yFact ); + NbcCrop( rRef, fxFact, fyFact ); SetChanged(); GetFormat()->GetDoc()->GetIDocumentUndoRedo().DoDrawUndo(false); } diff --git a/sw/source/core/frmedt/fefly1.cxx b/sw/source/core/frmedt/fefly1.cxx index f36eac32c09c..105689dbf848 100644 --- a/sw/source/core/frmedt/fefly1.cxx +++ b/sw/source/core/frmedt/fefly1.cxx @@ -368,7 +368,24 @@ void SwFEShell::SetFlyPos( const Point& rAbsPos ) // Set an anchor starting from the absolute position for paragraph bound Flys // Anchor and new RelPos will be calculated and set by the Fly if ( pFly->IsFlyAtContentFrame() ) - static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos( rAbsPos ); + { + if(pFly->IsFlyFreeFrame() && static_cast<SwFlyFreeFrame*>(pFly)->isTransformableSwFrame()) + { + // RotateFlyFrame3: When we have a change and are in transformed state (e.g. rotation used), + // we need to correct the absolute position (rAbsPos) which was created in + // transformed coordinates to untransformed state + TransformableSwFrame* pTransformableSwFrame(static_cast<SwFlyFreeFrame*>(pFly)->getTransformableSwFrame()); + const SwRect aUntransformedFrameArea(pTransformableSwFrame->getUntransformedFrameArea()); + const Point aNewAbsPos( + rAbsPos.X() + aUntransformedFrameArea.Left() - pFly->getFrameArea().Left(), + rAbsPos.Y() + aUntransformedFrameArea.Top() - pFly->getFrameArea().Top()); + static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos(aNewAbsPos); + } + else + { + static_cast<SwFlyAtContentFrame*>(pFly)->SetAbsPos( rAbsPos ); + } + } else { const SwFrame *pAnch = pFly->GetAnchorFrame(); diff --git a/sw/source/core/inc/dflyobj.hxx b/sw/source/core/inc/dflyobj.hxx index e2fcac536073..77df7060420d 100644 --- a/sw/source/core/inc/dflyobj.hxx +++ b/sw/source/core/inc/dflyobj.hxx @@ -101,11 +101,11 @@ public: virtual void NbcMove (const Size& rSiz) override; virtual void NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact) override; - virtual void NbcCrop(const Point& rRef, const Fraction& xFact, const Fraction& yFact) override; + virtual void NbcCrop(const basegfx::B2DPoint& rRef, double fxFact, double fyFact) override; virtual void Move (const Size& rSiz) override; virtual void Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bUnsetRelative = true) override; - virtual void Crop(const Point& rRef, const Fraction& xFact, const Fraction& yFact) override; + virtual void Crop(const basegfx::B2DPoint& rRef, double fxFact, double fyFact) override; virtual void addCropHandles(SdrHdlList& rTarget) const override; virtual void Rotate(const Point& rRef, long nAngle, double sn, double cs) override; diff --git a/sw/source/core/inc/flyfrms.hxx b/sw/source/core/inc/flyfrms.hxx index 5334a0269447..eaae5b89059d 100644 --- a/sw/source/core/inc/flyfrms.hxx +++ b/sw/source/core/inc/flyfrms.hxx @@ -25,6 +25,7 @@ // #i28701# class SwFlyAtContentFrame; +class SwNoTextFrame; double getLocalFrameRotation_from_SwNoTextFrame(const SwNoTextFrame& rNoTextFrame); diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx index 811bd390d82d..cc455a995008 100644 --- a/sw/source/core/inc/frame.hxx +++ b/sw/source/core/inc/frame.hxx @@ -146,6 +146,7 @@ protected: public: SwFrameAreaDefinition(); + virtual ~SwFrameAreaDefinition(); // read access to mb*Valid flags bool isFrameAreaPositionValid() const { return mbFrameAreaPositionValid; } @@ -212,8 +213,8 @@ public: }; /// RotateFlyFrame3: Helper class when you want to make your SwFrame derivate -/// transformable. It provides some tooling to do so. To use, -/// derive your SwFrame from it +/// transformable. It provides some tooling to do so. To use, add as member +/// (see e.g. SwFlyFreeFrame which uses 'std::unique_ptr< TransformableSwFrame >') class SW_DLLPUBLIC TransformableSwFrame { private: @@ -221,54 +222,50 @@ private: SwFrameAreaDefinition& mrSwFrameAreaDefinition; // FrameAreaTransformation and FramePrintAreaTransformation - // here when more than translate/scale is used (e.g. rotation) + // !identtity when needed (translate/scale is used (e.g. rotation)) basegfx::B2DHomMatrix maFrameAreaTransformation; basegfx::B2DHomMatrix maFramePrintAreaTransformation; - // last saved versions of SwRect(s) from SwFrameAreaDefinition, - // set from adaptFrameAreasToTransformations before modifying - // SwFrameAreaDefinition(s), used for restore from - // restoreFrameAreas - SwRect maSavedFrameArea; - SwRect maSavedFramePrintArea; - public: TransformableSwFrame(SwFrameAreaDefinition& rSwFrameAreaDefinition) : mrSwFrameAreaDefinition(rSwFrameAreaDefinition), maFrameAreaTransformation(), - maFramePrintAreaTransformation(), - maSavedFrameArea(), - maSavedFramePrintArea() + maFramePrintAreaTransformation() { } - // Support for Transformations for inner frame of a SwGrfNode + // get SwFrameArea in transformation form const basegfx::B2DHomMatrix& getLocalFrameAreaTransformation() const { return maFrameAreaTransformation; } + // get SwFramePrintArea in transformation form const basegfx::B2DHomMatrix& getLocalFramePrintAreaTransformation() const { return maFramePrintAreaTransformation; } + // Helpers to re-create the untransformed SwRect(s) originally + // in the SwFrameAreaDefinition, based on the current Transformations. + SwRect getUntransformedFrameArea() const; + SwRect getUntransformedFramePrintArea() const; + // Helper method to re-create FrameAreaTransformations based on the - // curent FrameAreaDefinition, given rotation and Center + // curent FrameAreaDefinition transformed by given rotation and Center void createFrameAreaTransformations( double fRotation, const basegfx::B2DPoint& rCenter); // Tooling method to reset the SwRect(s) in the current // SwFrameAreaDefinition which are already apapted to - // Transformation back to the untransformed state that was - // last saved (see adaptFrameAreasToTransformations). + // Transformation back to the untransformed state, using + // the getUntransformedFrame*Area calls above when needed. // Only the SwRect(s) are changed back, not the transformations. void restoreFrameAreas(); // Re-Creates the SwRect(s) as BoundAreas based on the current - // set Transformations, also saves the last SwRect(s) to the save - // values. + // set Transformations. void adaptFrameAreasToTransformations(); // Modify current definitions by applying the given transformation diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx index 684b989d76b8..5163fbb3f3c4 100644 --- a/sw/source/core/layout/fly.cxx +++ b/sw/source/core/layout/fly.cxx @@ -62,6 +62,8 @@ #include <IDocumentLayoutAccess.hxx> #include <textboxhelper.hxx> #include <txtfly.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> +#include <basegfx/matrix/b2dhommatrixtools.hxx> using namespace ::com::sun::star; @@ -2431,8 +2433,9 @@ bool SwFlyFrame::GetContour( tools::PolyPolygon& rContour, { vcl::RenderContext* pRenderContext = getRootFrame()->GetCurrShell()->GetOut(); bool bRet = false; - if( GetFormat()->GetSurround().IsContour() && Lower() && - Lower()->IsNoTextFrame() ) + const bool bIsCandidate(Lower() && Lower()->IsNoTextFrame()); + + if(bIsCandidate && GetFormat()->GetSurround().IsContour()) { SwNoTextNode *pNd = const_cast<SwNoTextNode*>(static_cast<const SwNoTextNode*>(static_cast<const SwContentFrame*>(Lower())->GetNode())); // OD 16.04.2003 #i13147# - determine <GraphicObject> instead of <Graphic> @@ -2524,6 +2527,31 @@ bool SwFlyFrame::GetContour( tools::PolyPolygon& rContour, bRet = true; } } + + if(bRet && + rContour.Count() && + IsFlyFreeFrame() && + static_cast<const SwFlyFreeFrame*>(this)->isTransformableSwFrame()) + { + // RotateFlyFrame: Need to adapt contour to transformation + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + getFrameAreaTransformation().decompose(aScale, aTranslate, fRotate, fShearX); + + if(!basegfx::fTools::equalZero(fRotate)) + { + basegfx::B2DPolyPolygon aSource(rContour.getB2DPolyPolygon()); + const basegfx::B2DPoint aCenter(getFrameAreaTransformation() * basegfx::B2DPoint(0.5, 0.5)); + const basegfx::B2DHomMatrix aRotateAroundCenter( + basegfx::utils::createRotateAroundPoint( + aCenter.getX(), + aCenter.getY(), + fRotate)); + aSource.transform(aRotateAroundCenter); + rContour = tools::PolyPolygon(aSource); + } + } + return bRet; } diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx index 7f7068ed0362..08debf8408e2 100644 --- a/sw/source/core/layout/wsfrm.cxx +++ b/sw/source/core/layout/wsfrm.cxx @@ -65,6 +65,10 @@ SwFrameAreaDefinition::SwFrameAreaDefinition() { } +SwFrameAreaDefinition::~SwFrameAreaDefinition() +{ +} + void SwFrameAreaDefinition::setFrameAreaPositionValid(bool bNew) { if(mbFrameAreaPositionValid != bNew) @@ -146,6 +150,55 @@ void SwFrameAreaDefinition::transform_translate(const Point& rOffset) } } +SwRect TransformableSwFrame::getUntransformedFrameArea() const +{ + const basegfx::B2DHomMatrix& rSource(getLocalFrameAreaTransformation()); + + if(rSource.isIdentity()) + { + return mrSwFrameAreaDefinition.getFrameArea(); + } + else + { + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + rSource.decompose(aScale, aTranslate, fRotate, fShearX); + const basegfx::B2DPoint aCenter(rSource * basegfx::B2DPoint(0.5, 0.5)); + const basegfx::B2DVector aAbsScale(basegfx::absolute(aScale)); + + return SwRect( + basegfx::fround(aCenter.getX() - (0.5 * aAbsScale.getX())), + basegfx::fround(aCenter.getY() - (0.5 * aAbsScale.getY())), + basegfx::fround(aAbsScale.getX()), + basegfx::fround(aAbsScale.getY())); + } +} + +SwRect TransformableSwFrame::getUntransformedFramePrintArea() const +{ + const basegfx::B2DHomMatrix& rSource(getLocalFramePrintAreaTransformation()); + + if(rSource.isIdentity()) + { + return mrSwFrameAreaDefinition.getFramePrintArea(); + } + else + { + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + rSource.decompose(aScale, aTranslate, fRotate, fShearX); + const basegfx::B2DPoint aCenter(rSource * basegfx::B2DPoint(0.5, 0.5)); + const basegfx::B2DVector aAbsScale(basegfx::absolute(aScale)); + const SwRect aUntransformedFrameArea(getUntransformedFrameArea()); + + return SwRect( + basegfx::fround(aCenter.getX() - (0.5 * aAbsScale.getX())) - aUntransformedFrameArea.Left(), + basegfx::fround(aCenter.getY() - (0.5 * aAbsScale.getY())) - aUntransformedFrameArea.Top(), + basegfx::fround(aAbsScale.getX()), + basegfx::fround(aAbsScale.getY())); + } +} + void TransformableSwFrame::createFrameAreaTransformations( double fRotation, const basegfx::B2DPoint& rCenter) @@ -178,7 +231,6 @@ void TransformableSwFrame::adaptFrameAreasToTransformations() if(aNewFrm != mrSwFrameAreaDefinition.getFrameArea()) { - maSavedFrameArea = mrSwFrameAreaDefinition.getFrameArea(); SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(mrSwFrameAreaDefinition); aFrm.setSwRect(aNewFrm); } @@ -196,7 +248,6 @@ void TransformableSwFrame::adaptFrameAreasToTransformations() if(aNewPrt != mrSwFrameAreaDefinition.getFramePrintArea()) { - maSavedFramePrintArea = mrSwFrameAreaDefinition.getFramePrintArea(); SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(mrSwFrameAreaDefinition); aPrt.setSwRect(aNewPrt); } @@ -206,20 +257,17 @@ void TransformableSwFrame::adaptFrameAreasToTransformations() void TransformableSwFrame::restoreFrameAreas() { // This can be done fully based on the Transformations currently - // set (and I did this in the beginning and it may be necessary - // again later), but for simplicity and performance now done using - // the last save values for the SwRect(s), see above - - if(!getLocalFrameAreaTransformation().isIdentity() && maSavedFrameArea != mrSwFrameAreaDefinition.getFrameArea()) + // set, so use this. Only needed when transformation *is* used + if(!getLocalFrameAreaTransformation().isIdentity()) { SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(mrSwFrameAreaDefinition); - aFrm.setSwRect(maSavedFrameArea); + aFrm.setSwRect(getUntransformedFrameArea()); } - if(!getLocalFramePrintAreaTransformation().isIdentity() && maSavedFramePrintArea != mrSwFrameAreaDefinition.getFramePrintArea()) + if(!getLocalFramePrintAreaTransformation().isIdentity()) { SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(mrSwFrameAreaDefinition); - aPrt.setSwRect(maSavedFramePrintArea); + aPrt.setSwRect(getUntransformedFramePrintArea()); } } |