summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2017-11-15 13:56:38 +0100
committerArmin Le Grand <Armin.Le.Grand@cib.de>2017-11-18 13:07:46 +0100
commitd74b26b41bfea3ba7a1834953b2bfe9b7ff0d70f (patch)
tree9e9684d1481df209e585ab08b079de5bfa86a466
parentRotateFlyFrame3: Made interactions work properly (diff)
downloadcore-d74b26b41bfea3ba7a1834953b2bfe9b7ff0d70f.tar.gz
core-d74b26b41bfea3ba7a1834953b2bfe9b7ff0d70f.zip
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
-rw-r--r--include/svx/svdobj.hxx7
-rw-r--r--svx/source/svdraw/svddrgmt.cxx20
-rw-r--r--svx/source/svdraw/svdobj.cxx10
-rw-r--r--svx/source/uitest/sdrobject.cxx16
-rw-r--r--sw/source/core/draw/dflyobj.cxx134
-rw-r--r--sw/source/core/frmedt/fefly1.cxx19
-rw-r--r--sw/source/core/inc/dflyobj.hxx4
-rw-r--r--sw/source/core/inc/flyfrms.hxx1
-rw-r--r--sw/source/core/inc/frame.hxx35
-rw-r--r--sw/source/core/layout/fly.cxx32
-rw-r--r--sw/source/core/layout/wsfrm.cxx68
11 files changed, 226 insertions, 120 deletions
diff --git a/include/svx/svdobj.hxx b/include/svx/svdobj.hxx
index 2a7c629a05d3..bf227c9635c4 100644
--- a/include/svx/svdobj.hxx
+++ b/include/svx/svdobj.hxx
@@ -75,10 +75,9 @@ class OutputDevice;
class Fraction;
namespace basegfx {
-
+class B2DPoint;
class B2DPolyPolygon;
class B2DHomMatrix;
-
}
namespace sdr
@@ -511,14 +510,14 @@ public:
/// Nbc means "no broadcast".
virtual void NbcMove (const Size& rSiz);
virtual void NbcResize(const Point& rRef, const Fraction& xFact, const Fraction& yFact);
- virtual void NbcCrop (const Point& rRef, const Fraction& xFact, const Fraction& yFact);
+ virtual void NbcCrop (const basegfx::B2DPoint& rRef, double fxFact, double fyFact);
virtual void NbcRotate(const Point& rRef, long nAngle, double sn, double cs);
virtual void NbcMirror(const Point& rRef1, const Point& rRef2);
virtual void NbcShear (const Point& rRef, long nAngle, double tn, bool bVShear);
virtual void Move (const Size& rSiz);
virtual void Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bUnsetRelative = true);
- virtual void Crop (const Point& rRef, const Fraction& xFact, const Fraction& yFact);
+ virtual void Crop (const basegfx::B2DPoint& rRef, double fxFact, double fyFact);
virtual void Rotate(const Point& rRef, long nAngle, double sn, double cs);
virtual void Mirror(const Point& rRef1, const Point& rRef2);
virtual void Shear (const Point& rRef, long nAngle, double tn, bool bVShear);
diff --git a/svx/source/svdraw/svddrgmt.cxx b/svx/source/svdraw/svddrgmt.cxx
index 714d4e66a334..1e3344c26410 100644
--- a/svx/source/svdraw/svddrgmt.cxx
+++ b/svx/source/svdraw/svddrgmt.cxx
@@ -3766,25 +3766,17 @@ bool SdrDragCrop::EndSdrDrag(bool /*bCopy*/)
if(bExternal)
{
- // With Ref point (opposed to dragged point), X scale and Y scale,
+ // With aLocalStart point (opposed to dragged point), X scale and Y scale,
// we call crop (virtual method) on pSdrObject which calls VirtFlyDrawObj
- // crop. aRef needs to be adapted to concrete Object's boundaries which
- // is different from Crop-Ranges. This is because the Graphic and it's
- // SdrObject representation is inside the FlyFrame, but not identical
- // with it.
- const tools::Rectangle& rOutRect(pExternalSdrObject->GetCurrentBoundRect());
- const basegfx::B2DHomMatrix aExternalTransform(
- basegfx::utils::createScaleTranslateB2DHomMatrix(
- rOutRect.getWidth(), rOutRect.getHeight(),
- rOutRect.Left(), rOutRect.Top()));
- const basegfx::B2DPoint aRef(aExternalTransform * aLocalStart);
+ // crop. Use aLocalStart unchanged, so being relative to the Crop-Action,
+ // the called instance knows best how to use it
const double fScaleX(aRangeNewNoShearNoRotate.getWidth() / aRangeOriginalNoShearNoRotate.getWidth());
const double fScaleY(aRangeNewNoShearNoRotate.getHeight() / aRangeOriginalNoShearNoRotate.getHeight());
pExternalSdrObject->Crop(
- Point(basegfx::fround(aRef.getX()), basegfx::fround(aRef.getY())),
- Fraction(fScaleX),
- Fraction(fScaleY));
+ aLocalStart,
+ fScaleX,
+ fScaleY);
}
else
{
diff --git a/svx/source/svdraw/svdobj.cxx b/svx/source/svdraw/svdobj.cxx
index d5ef63b3c842..020c75655be8 100644
--- a/svx/source/svdraw/svdobj.cxx
+++ b/svx/source/svdraw/svdobj.cxx
@@ -1485,8 +1485,10 @@ void SdrObject::Move(const Size& rSiz)
}
}
-void SdrObject::NbcCrop(const Point& /*rRef*/, const Fraction& /*xFact*/, const Fraction& /*yFact*/) {
- // Default: does nothing. Real behaviour in SwVirtFlyDrawObj and SdrGrafObj
+void SdrObject::NbcCrop(const basegfx::B2DPoint& /*aRef*/, double /*fxFact*/, double /*fyFact*/)
+{
+ // Default: does nothing. Real behaviour in SwVirtFlyDrawObj and SdrDragCrop::EndSdrDrag.
+ // Where SwVirtFlyDrawObj is the only real user of it to do something local
}
void SdrObject::Resize(const Point& rRef, const Fraction& xFact, const Fraction& yFact, bool bUnsetRelative)
@@ -1507,10 +1509,10 @@ void SdrObject::Resize(const Point& rRef, const Fraction& xFact, const Fraction&
}
}
-void SdrObject::Crop(const Point& rRef, const Fraction& xFact, const Fraction& yFact)
+void SdrObject::Crop(const basegfx::B2DPoint& rRef, double fxFact, double fyFact)
{
tools::Rectangle aBoundRect0; if (pUserCall!=nullptr) aBoundRect0=GetLastBoundRect();
- NbcCrop(rRef, xFact, yFact);
+ NbcCrop(rRef, fxFact, fyFact);
SetChanged();
BroadcastObjectChange();
SendUserCall(SdrUserCallType::Resize,aBoundRect0);
diff --git a/svx/source/uitest/sdrobject.cxx b/svx/source/uitest/sdrobject.cxx
index f70cb2e3c511..4fdd4c315764 100644
--- a/svx/source/uitest/sdrobject.cxx
+++ b/svx/source/uitest/sdrobject.cxx
@@ -99,6 +99,8 @@ void SdrUIObject::execute(const OUString& rAction,
}
else if (rAction == "CROP")
{
+ // RotateFlyFrame3: Note: Crop does nothing at SdrObject
+ // anymore, see comment at SdrObject::NbcCrop
auto itrNX = rParameters.find("X");
if (itrNX == rParameters.end())
throw css::uno::RuntimeException("missing parameter X");
@@ -107,23 +109,21 @@ void SdrUIObject::execute(const OUString& rAction,
if (itrNY == rParameters.end())
throw css::uno::RuntimeException("missing parameter Y");
- long nX = itrNX->second.toInt32();
- long nY = itrNY->second.toInt32();
- Point aPos(nX, nY);
+ const double fX(itrNX->second.toDouble());
+ const double fY(itrNY->second.toDouble());
+ const basegfx::B2DPoint aPos(fX, fY);
auto itrFracX = rParameters.find("FRAC_X");
if (itrFracX == rParameters.end())
throw css::uno::RuntimeException("missing parameter FRAC_X");
- double nFracX = itrFracX->second.toDouble();
- Fraction aFracX(nFracX);
+ const double fFracX(itrFracX->second.toDouble());
auto itrFracY = rParameters.find("FRAC_Y");
if (itrFracY == rParameters.end())
throw css::uno::RuntimeException("missing parameter FRAC_Y");
- double nFracY = itrFracY->second.toDouble();
- Fraction aFracY(nFracY);
+ const double fFracY(itrFracY->second.toDouble());
- pObj->Crop(aPos, aFracX, aFracY);
+ pObj->Crop(aPos, fFracX, fFracY);
}
else if (rAction == "ROTATE")
{
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());
}
}