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

Armin Le Grand Armin.Le.Grand at cib.de
Wed Nov 15 13:00:55 UTC 2017


 include/svx/svdobj.hxx          |    7 --
 svx/source/svdraw/svddrgmt.cxx  |   20 +-----
 svx/source/svdraw/svdobj.cxx    |   10 +--
 svx/source/uitest/sdrobject.cxx |   16 ++---
 sw/source/core/draw/dflyobj.cxx |  123 +++++++++++++++++++++++-----------------
 sw/source/core/inc/dflyobj.hxx  |    4 -
 sw/source/core/inc/frame.hxx    |    1 
 sw/source/core/layout/wsfrm.cxx |    4 +
 8 files changed, 102 insertions(+), 83 deletions(-)

New commits:
commit d7c5d633de9a78f1b0b233393ca7fc48ad0b5130
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Wed Nov 15 13:56:38 2017 +0100

    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 Croppped, transformed object to be in the correct
    relative position to the uncropped, untransfomed one.
    
    Change-Id: I67da35b4aec11d2bb195720a416dab4dbb42432a

diff --git a/include/svx/svdobj.hxx b/include/svx/svdobj.hxx
index cd6953312565..ae92ffa13069 100644
--- a/include/svx/svdobj.hxx
+++ b/include/svx/svdobj.hxx
@@ -74,10 +74,9 @@ class OutputDevice;
 class Fraction;
 
 namespace basegfx {
-
+class B2DPoint;
 class B2DPolyPolygon;
 class B2DHomMatrix;
-
 }
 
 namespace sdr
@@ -510,14 +509,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..bc16d4712ce2 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();
 }
 
@@ -1115,9 +1136,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/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/frame.hxx b/sw/source/core/inc/frame.hxx
index 811bd390d82d..c0df129946f1 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; }
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index 7f7068ed0362..d090d056f127 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)


More information about the Libreoffice-commits mailing list