Kaydet (Commit) 6675e6ea authored tarafından Armin Le Grand's avatar Armin Le Grand

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
üst 995c75de
......@@ -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: */
......@@ -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:
......
......@@ -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;
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
......@@ -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#
......
......@@ -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 ),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment