summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand <Armin.Le.Grand@cib.de>2017-11-02 18:28:04 +0100
committerArmin Le Grand <Armin.Le.Grand@cib.de>2017-11-17 13:31:17 +0100
commit7275da2f686fe4c01bbb702f5100b08ded90d14e (patch)
treee01273b9acc22685530a5a76919836d967cc7410
parent4b69497e36b941d4db62ae8d5bad863d032fdc50 (diff)
RotateFlyFrame3: Initial support added
First steps to get a rotated FlyFrame and content that only uses layouted sizes/positions and does not change the model data (except rotation). This works with persistence, after reload the rotation can be resetted with going back to the original FrameSize. Lot of stuff not yet working, experimental state. Change-Id: Ie29d501fe2e618a1cb4457d600ce97575ed372d0
-rw-r--r--basegfx/source/numeric/ftools.cxx34
-rw-r--r--include/basegfx/numeric/ftools.hxx20
-rw-r--r--sw/source/core/doc/notxtfrm.cxx59
-rw-r--r--sw/source/core/inc/flyfrms.hxx3
-rw-r--r--sw/source/core/inc/frame.hxx14
-rw-r--r--sw/source/core/inc/notxtfrm.hxx3
-rw-r--r--sw/source/core/layout/flylay.cxx51
-rw-r--r--sw/source/core/layout/wsfrm.cxx51
8 files changed, 235 insertions, 0 deletions
diff --git a/basegfx/source/numeric/ftools.cxx b/basegfx/source/numeric/ftools.cxx
index a67bc56bd74e..994bd29e30eb 100644
--- a/basegfx/source/numeric/ftools.cxx
+++ b/basegfx/source/numeric/ftools.cxx
@@ -44,6 +44,40 @@ namespace basegfx
}
}
}
+
+ double normalizeToRange(double v, const double fRange)
+ {
+ if(fTools::lessOrEqual(fRange, 0.0))
+ {
+ // with a zero (or less) range, all normalizes to 0.0
+ return 0.0;
+ }
+
+ const bool bNegative(fTools::less(v, 0.0));
+
+ if(bNegative)
+ {
+ if(fTools::moreOrEqual(v, -fRange))
+ {
+ // in range [-fRange, 0.0[, shift one step
+ return v + fRange;
+ }
+
+ // re-calculate
+ return v - (floor(v/fRange)*fRange);
+ }
+ else
+ {
+ if(fTools::less(v, fRange))
+ {
+ // already in range [0.0, fRange[, nothing to do
+ return v;
+ }
+
+ // re-calculate
+ return v - (floor(v/fRange)*fRange);
+ }
+ }
} // end of namespace basegfx
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/basegfx/numeric/ftools.hxx b/include/basegfx/numeric/ftools.hxx
index 19e8e101987c..eb030b2530d1 100644
--- a/include/basegfx/numeric/ftools.hxx
+++ b/include/basegfx/numeric/ftools.hxx
@@ -152,6 +152,26 @@ namespace basegfx
*/
BASEGFX_DLLPUBLIC double snapToNearestMultiple(double v, const double fStep);
+ /** RotateFlyFrame3: Normalize to range defined by [0.0 ... fRange[, independent
+ if v is positive or negative.
+
+ Examples:
+
+ normalizeToRange(0.5, -1.0) = 0.0
+ normalizeToRange(0.5, 0.0) = 0.0
+ normalizeToRange(0.5, 1.0) = 0.5
+ normalizeToRange(-0.5, 1.0) = 0.5
+ normalizeToRange(-0.3, 1.0) = 0.7
+ normalizeToRange(-0.7, 1.0) = 0.3
+ normalizeToRange(3.5, 1.0) = 0.5
+ normalizeToRange(3.3, 1.0) = 0.3
+ normalizeToRange(3.7, 1.0) = 0.7
+ normalizeToRange(-3.5, 1.0) = 0.5
+ normalizeToRange(-3.3, 1.0) = 0.7
+ normalizeToRange(-3.7, 1.0) = 0.3
+ */
+ BASEGFX_DLLPUBLIC double normalizeToRange(double v, const double fRange);
+
class BASEGFX_DLLPUBLIC fTools
{
public:
diff --git a/sw/source/core/doc/notxtfrm.cxx b/sw/source/core/doc/notxtfrm.cxx
index e4c3f751e41d..4631dbb7a2e3 100644
--- a/sw/source/core/doc/notxtfrm.cxx
+++ b/sw/source/core/doc/notxtfrm.cxx
@@ -492,6 +492,56 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
Format(getRootFrame()->GetCurrShell()->GetOut());
}
}
+
+ // RotateFlyFrame3 - inner frame
+ // After the layout is finished, apply possible set rotation to it
+ const double fRotation(getRotation());
+
+ if(0.0 != fRotation)
+ {
+ SwRect aFrameArea(getFrameArea());
+ SwRect aFramePrintArea(getFramePrintArea());
+ const Point aCenter(aFrameArea.Center());
+
+ // apply rotation and re-set the FrameArea definitions
+ rotateFrameAreaDefinitionAroundPoint(aFrameArea, aFramePrintArea, aCenter, fRotation);
+
+ if(aFrameArea != getFrameArea())
+ {
+ SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
+ aFrm.setSwRect(aFrameArea);
+ }
+
+ if(aFramePrintArea != getFramePrintArea())
+ {
+ SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
+ aPrt.setSwRect(aFramePrintArea);
+ }
+ }
+}
+
+// RotateFlyFrame3 - inner frame
+// Check if we contain a SwGrfNode and get possible rotation from it
+double SwNoTextFrame::getRotation() const
+{
+ const SwNoTextNode* pSwNoTextNode(nullptr != GetNode() ? GetNode()->GetNoTextNode() : nullptr);
+
+ if(nullptr != pSwNoTextNode)
+ {
+ const SwGrfNode* pSwGrfNode(pSwNoTextNode->GetGrfNode());
+
+ if(nullptr != pSwGrfNode)
+ {
+ const SwAttrSet& rSwAttrSet(pSwGrfNode->GetSwAttrSet());
+ const SwRotationGrf& rSwRotationGrf(rSwAttrSet.GetRotationGrf());
+ const double fRotate(static_cast< double >(-rSwRotationGrf.GetValue()) * (M_PI/1800.0));
+
+ return basegfx::normalizeToRange(fRotate, F_2PI);
+ }
+ }
+
+ // call parent
+ return SwContentFrame::getRotation();
}
/** Calculate the Bitmap's site, if needed */
@@ -649,6 +699,15 @@ void SwNoTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
pDrawView->AdjustMarkHdl(nullptr);
}
}
+
+ // RotateFlyFrame3 - invalidate needed for ContentFrame (inner, this)
+ // and LayoutFrame (outer, GetUpper)
+ InvalidateAll_();
+
+ if(GetUpper())
+ {
+ GetUpper()->InvalidateAll_();
+ }
}
}
break;
diff --git a/sw/source/core/inc/flyfrms.hxx b/sw/source/core/inc/flyfrms.hxx
index 719eb01f07bd..91b4188fb48a 100644
--- a/sw/source/core/inc/flyfrms.hxx
+++ b/sw/source/core/inc/flyfrms.hxx
@@ -116,6 +116,9 @@ public:
and its anchor frame isn't inside another Writer fly frame.
*/
virtual bool IsFormatPossible() const override;
+
+ // RotateFlyFrame3 - Support for outer Frame of a SwGrfNode
+ virtual double getRotation() 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 b69b942ad40e..dbef917b206e 100644
--- a/sw/source/core/inc/frame.hxx
+++ b/sw/source/core/inc/frame.hxx
@@ -196,6 +196,15 @@ public:
};
};
+// RotateFlyFrame3 - Helper method that rotates a FrameAreaDefinition content
+// around a given point. It takes care for FramePrintArea being relative to
+// FrameArea and creates the rotated BoundRects
+void rotateFrameAreaDefinitionAroundPoint(
+ SwRect& rFrameArea,
+ SwRect& rFramePrintArea,
+ const Point& rCenter,
+ double fRotation);
+
/**
* Base class of the Writer layout elements.
*
@@ -820,6 +829,11 @@ public:
virtual void dumpAsXmlAttributes(xmlTextWriterPtr writer) const;
void dumpChildrenAsXml(xmlTextWriterPtr writer) const;
bool IsCollapse() const;
+
+ // RotateFlyFrame3 - Support for handing out a rotation, currently
+ // only used for SwGrfNode in inner SwFrame of a SwFlyFrame, but may
+ // be used in the future. Default returns 0.0 (no rotation)
+ virtual double getRotation() const;
};
inline bool SwFrame::IsInDocBody() const
diff --git a/sw/source/core/inc/notxtfrm.hxx b/sw/source/core/inc/notxtfrm.hxx
index 802c737eeb21..a1936193af44 100644
--- a/sw/source/core/inc/notxtfrm.hxx
+++ b/sw/source/core/inc/notxtfrm.hxx
@@ -57,6 +57,9 @@ public:
void StopAnimation( OutputDevice* = nullptr ) const;
bool HasAnimation() const;
+
+ // RotateFlyFrame3 - Support for inner frame of a SwGrfNode
+ virtual double getRotation() const override;
};
#endif
diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx
index f0ef660adb88..69fa2615a733 100644
--- a/sw/source/core/layout/flylay.cxx
+++ b/sw/source/core/layout/flylay.cxx
@@ -26,6 +26,7 @@
#include <frmtool.hxx>
#include <hints.hxx>
#include <sectfrm.hxx>
+#include <notxtfrm.hxx>
#include <svx/svdpage.hxx>
#include <editeng/ulspitem.hxx>
@@ -220,6 +221,40 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
else
nLoopControlRuns = 0;
}
+
+ // RotateFlyFrame3 - inner frame
+ const double fRotation(getRotation());
+
+ if(0.0 != fRotation)
+ {
+ SwRect aFrameArea(getFrameArea());
+ SwRect aFramePrintArea(getFramePrintArea());
+ Point aCenter(aFrameArea.Center());
+
+ if(GetUpper())
+ {
+ // get center from outer frame (layout frame)
+ const SwRect aUpperFrameArea(GetUpper()->getFrameArea());
+
+ aCenter = aUpperFrameArea.Center();
+ }
+
+ // apply rotation and re-set the FrameArea definitions
+ rotateFrameAreaDefinitionAroundPoint(aFrameArea, aFramePrintArea, aCenter, fRotation);
+
+ if(aFrameArea != getFrameArea())
+ {
+ SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this);
+ aFrm.setSwRect(aFrameArea);
+ }
+
+ if(aFramePrintArea != getFramePrintArea())
+ {
+ SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this);
+ aPrt.setSwRect(aFramePrintArea);
+ }
+ }
+
Unlock();
#if OSL_DEBUG_LEVEL > 0
@@ -231,6 +266,22 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
#endif
}
+// RotateFlyFrame3
+double SwFlyFreeFrame::getRotation() const
+{
+ // SwLayoutFrame::Lower() != SwFrame::GetLower(), but SwFrame::GetLower()
+ // calls SwLayoutFrame::Lower() when it's a SwLayoutFrame - so use GetLower()
+ const SwNoTextFrame* pSwNoTextFrame(dynamic_cast< const SwNoTextFrame* >(GetLower()));
+
+ if(nullptr != pSwNoTextFrame)
+ {
+ return pSwNoTextFrame->getRotation();
+ }
+
+ // call parent
+ return SwFlyFrame::getRotation();
+}
+
/** determines, if direct environment of fly frame has 'auto' size
#i17297#
diff --git a/sw/source/core/layout/wsfrm.cxx b/sw/source/core/layout/wsfrm.cxx
index 16cb40082a14..dbe44b5084e6 100644
--- a/sw/source/core/layout/wsfrm.cxx
+++ b/sw/source/core/layout/wsfrm.cxx
@@ -51,6 +51,9 @@
#include <editeng/frmdiritem.hxx>
#include <sortedobjs.hxx>
+// RotateFlyFrame3
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+
using namespace ::com::sun::star;
SwFrameAreaDefinition::SwFrameAreaDefinition()
@@ -102,6 +105,54 @@ SwFrameAreaDefinition::FramePrintAreaWriteAccess::~FramePrintAreaWriteAccess()
}
}
+void rotateFrameAreaDefinitionAroundPoint(
+ SwRect& rFrameArea,
+ SwRect& rFramePrintArea,
+ const Point& rCenter,
+ double fRotation)
+{
+ if(!basegfx::fTools::equalZero(fRotation) && rFrameArea.HasArea())
+ {
+ basegfx::B2DRange aFrameRange(
+ rFrameArea.Left(),
+ rFrameArea.Top(),
+ rFrameArea.Right(),
+ rFrameArea.Bottom());
+ const basegfx::B2DPoint aOldTopLeft(aFrameRange.getMinimum());
+ const basegfx::B2DHomMatrix aRotateAroundCenter(basegfx::utils::createRotateAroundPoint(rCenter.X(), rCenter.Y(), fRotation));
+
+ aFrameRange.transform(aRotateAroundCenter);
+ rFrameArea = SwRect(
+ basegfx::fround(aFrameRange.getMinX()),
+ basegfx::fround(aFrameRange.getMinY()),
+ basegfx::fround(aFrameRange.getWidth()),
+ basegfx::fround(aFrameRange.getHeight()));
+
+ if(rFramePrintArea.HasArea())
+ {
+ basegfx::B2DRange aFramePrintRange(
+ rFramePrintArea.Left() + aOldTopLeft.getX(),
+ rFramePrintArea.Top() + aOldTopLeft.getY(),
+ rFramePrintArea.Right() + aOldTopLeft.getX(),
+ rFramePrintArea.Bottom() + aOldTopLeft.getY());
+ const basegfx::B2DPoint aNewTopLeft(aFrameRange.getMinimum());
+
+ aFramePrintRange.transform(aRotateAroundCenter);
+ rFramePrintArea = SwRect(
+ basegfx::fround(aFramePrintRange.getMinX() - aNewTopLeft.getX()),
+ basegfx::fround(aFramePrintRange.getMinY() - aNewTopLeft.getY()),
+ basegfx::fround(aFramePrintRange.getWidth()),
+ basegfx::fround(aFramePrintRange.getHeight()));
+ }
+ }
+}
+
+// RotateFlyFrame3 - get a possible rotation from SwFrame, default returns 0.0 (no rotation)
+double SwFrame::getRotation() const
+{
+ return 0.0;
+}
+
SwFrame::SwFrame( SwModify *pMod, SwFrame* pSib )
: SwFrameAreaDefinition(),
SwClient( pMod ),