diff options
-rw-r--r-- | basegfx/source/numeric/ftools.cxx | 34 | ||||
-rw-r--r-- | include/basegfx/numeric/ftools.hxx | 20 | ||||
-rw-r--r-- | sw/source/core/doc/notxtfrm.cxx | 59 | ||||
-rw-r--r-- | sw/source/core/inc/flyfrms.hxx | 3 | ||||
-rw-r--r-- | sw/source/core/inc/frame.hxx | 14 | ||||
-rw-r--r-- | sw/source/core/inc/notxtfrm.hxx | 3 | ||||
-rw-r--r-- | sw/source/core/layout/flylay.cxx | 51 | ||||
-rw-r--r-- | sw/source/core/layout/wsfrm.cxx | 51 |
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 ), |