Kaydet (Commit) 51ee0c5b authored tarafından Armin Le Grand's avatar Armin Le Grand

RotateFlyFrame3: Added transformation support to SwFrame

The layout element SwFrame now has methods to get linear
transformations for the geometry-defining FrameAreaDefinitions.
These return by default the SwRect (without being relative
for the FramePrintArea to make things easier), but are
replaced by the now two SwFrame derivates that support
rotation. The layout will now use the BoundRects of the
transformations, thus supporting a future that will allow
all kinds of free transformations (including mirror, rotation
and shear)

Change-Id: I18b85f5ddc2970a1b8c137d30b0c2ee49bb8df72
üst 6675e6ea
...@@ -143,7 +143,9 @@ static void lcl_PaintReplacement( const SwRect &rRect, const OUString &rText, ...@@ -143,7 +143,9 @@ static void lcl_PaintReplacement( const SwRect &rRect, const OUString &rText,
} }
SwNoTextFrame::SwNoTextFrame(SwNoTextNode * const pNode, SwFrame* pSib ) SwNoTextFrame::SwNoTextFrame(SwNoTextNode * const pNode, SwFrame* pSib )
: SwContentFrame( pNode, pSib ) : SwContentFrame( pNode, pSib ),
maFrameAreaTransformation(),
maFramePrintAreaTransformation()
{ {
mnFrameType = SwFrameType::NoTxt; mnFrameType = SwFrameType::NoTxt;
} }
...@@ -493,34 +495,63 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) ...@@ -493,34 +495,63 @@ void SwNoTextFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
} }
} }
// RotateFlyFrame3 - inner frame // RotateFlyFrame3 - outer frame
// After the layout is finished, apply possible set rotation to it // After the unrotated layout is finished, apply possible set rotation to it
const double fRotation(getRotation()); const double fRotation(getRotation());
if(0.0 != fRotation) if(basegfx::fTools::equalZero(fRotation))
{ {
SwRect aFrameArea(getFrameArea()); // reset transformations to show that they are not used
SwRect aFramePrintArea(getFramePrintArea()); maFrameAreaTransformation.identity();
const Point aCenter(aFrameArea.Center()); maFramePrintAreaTransformation.identity();
}
else
{
// save Transformations to local maFrameAreaTransformation
// and maFramePrintAreaTransformation.
const Point aCenter(getFrameArea().Center());
const basegfx::B2DPoint aB2DCenter(aCenter.X(), aCenter.Y());
createFrameAreaTransformations(
maFrameAreaTransformation,
maFramePrintAreaTransformation,
fRotation,
aB2DCenter);
// create BoundRects of FrameAreas and re-set the FrameArea definitions
// to represent the rotated geometry in the layout object
setFrameAreaDefinitionsToBoundRangesOfTransformations(
maFrameAreaTransformation,
maFramePrintAreaTransformation);
}
}
// apply rotation and re-set the FrameArea definitions // RotateFlyFrame3 - Support for Transformations - outer frame
rotateFrameAreaDefinitionAroundPoint(aFrameArea, aFramePrintArea, aCenter, fRotation); basegfx::B2DHomMatrix SwNoTextFrame::getFrameAreaTransformation() const
{
if(!maFrameAreaTransformation.isIdentity())
{
// use pre-created transformation
return maFrameAreaTransformation;
}
if(aFrameArea != getFrameArea()) // call parent
{ return SwContentFrame::getFrameAreaTransformation();
SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); }
aFrm.setSwRect(aFrameArea);
}
if(aFramePrintArea != getFramePrintArea()) basegfx::B2DHomMatrix SwNoTextFrame::getFramePrintAreaTransformation() const
{ {
SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); if(!maFramePrintAreaTransformation.isIdentity())
aPrt.setSwRect(aFramePrintArea); {
} // use pre-created transformation
return maFramePrintAreaTransformation;
} }
// call parent
return SwContentFrame::getFramePrintAreaTransformation();
} }
// RotateFlyFrame3 - inner frame // RotateFlyFrame3 - outer frame
// Check if we contain a SwGrfNode and get possible rotation from it // Check if we contain a SwGrfNode and get possible rotation from it
double SwNoTextFrame::getRotation() const double SwNoTextFrame::getRotation() const
{ {
...@@ -701,7 +732,9 @@ void SwNoTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) ...@@ -701,7 +732,9 @@ void SwNoTextFrame::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
} }
// RotateFlyFrame3 - invalidate needed for ContentFrame (inner, this) // RotateFlyFrame3 - invalidate needed for ContentFrame (inner, this)
// and LayoutFrame (outer, GetUpper) // and LayoutFrame (outer, GetUpper). It is possible to only invalidate
// the outer frame, but that leads to an in-between state that gets
// potentially painted
InvalidateAll_(); InvalidateAll_();
if(GetUpper()) if(GetUpper())
......
...@@ -40,6 +40,12 @@ class SwFlyFreeFrame : public SwFlyFrame ...@@ -40,6 +40,12 @@ class SwFlyFreeFrame : public SwFlyFrame
SwRect maUnclippedFrame; SwRect maUnclippedFrame;
// RotateFlyFrame3 - Support for Transformations, hold
// FrameAreaTransformation and FramePrintAreaTransformation
// here when rotation is used
basegfx::B2DHomMatrix maFrameAreaTransformation;
basegfx::B2DHomMatrix maFramePrintAreaTransformation;
void CheckClip( const SwFormatFrameSize &rSz ); //'Emergency' Clipping. void CheckClip( const SwFormatFrameSize &rSz ); //'Emergency' Clipping.
/** determines, if direct environment of fly frame has 'auto' size /** determines, if direct environment of fly frame has 'auto' size
...@@ -119,6 +125,10 @@ public: ...@@ -119,6 +125,10 @@ public:
// RotateFlyFrame3 - Support for outer Frame of a SwGrfNode // RotateFlyFrame3 - Support for outer Frame of a SwGrfNode
virtual double getRotation() const override; virtual double getRotation() const override;
// RotateFlyFrame3 - Support for Transformations for outer Frame of a SwGrfNode
basegfx::B2DHomMatrix getFrameAreaTransformation() const;
basegfx::B2DHomMatrix getFramePrintAreaTransformation() const;
}; };
// Flys that are bound to LayoutFrames and not to Content // Flys that are bound to LayoutFrames and not to Content
......
...@@ -144,6 +144,20 @@ protected: ...@@ -144,6 +144,20 @@ protected:
void setFrameAreaSizeValid(bool bNew); void setFrameAreaSizeValid(bool bNew);
void setFramePrintAreaValid(bool bNew); void setFramePrintAreaValid(bool bNew);
// helper method to create FrameAreaTransformations based on the
// curent FrameAreaDefinition
void createFrameAreaTransformations(
basegfx::B2DHomMatrix& rFrameAreaTransformation,
basegfx::B2DHomMatrix& rFramePrintAreaTransformation,
double fRotation,
const basegfx::B2DPoint& rCenter) const;
// helper method to set FrameAreaDefinitions based on given
// transformations
void setFrameAreaDefinitionsToBoundRangesOfTransformations(
const basegfx::B2DHomMatrix& rFrameAreaTransformation,
const basegfx::B2DHomMatrix& rFramePrintAreaTransformation);
public: public:
SwFrameAreaDefinition(); SwFrameAreaDefinition();
...@@ -196,15 +210,6 @@ public: ...@@ -196,15 +210,6 @@ 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. * Base class of the Writer layout elements.
* *
...@@ -834,6 +839,17 @@ public: ...@@ -834,6 +839,17 @@ public:
// only used for SwGrfNode in inner SwFrame of a SwFlyFrame, but may // only used for SwGrfNode in inner SwFrame of a SwFlyFrame, but may
// be used in the future. Default returns 0.0 (no rotation) // be used in the future. Default returns 0.0 (no rotation)
virtual double getRotation() const; virtual double getRotation() const;
// RotateFlyFrame3 - Support for Transformations
// Hand out the Transformations for the current FrameAreaDefinition
// for the FrameArea and FramePrintArea.
// FramePrintArea is not relative to FrameArea in this
// transformation representation (to make it easier to use and understand).
// There is no 'set' method since SwFrame is a layout obejct. For
// some cases rotation will be included (used for SwGrfNode in inner
// SwFrame of a SwFlyFrame)
basegfx::B2DHomMatrix getFrameAreaTransformation() const;
basegfx::B2DHomMatrix getFramePrintAreaTransformation() const;
}; };
inline bool SwFrame::IsInDocBody() const inline bool SwFrame::IsInDocBody() const
......
...@@ -30,6 +30,12 @@ class SwNoTextFrame: public SwContentFrame ...@@ -30,6 +30,12 @@ class SwNoTextFrame: public SwContentFrame
{ {
friend void FrameFinit(); friend void FrameFinit();
// RotateFlyFrame3 - Support for Transformation, hold
// FrameAreaTransformation and FramePrintAreaTransformation
// here when rotation is used
basegfx::B2DHomMatrix maFrameAreaTransformation;
basegfx::B2DHomMatrix maFramePrintAreaTransformation;
const Size& GetSize() const; const Size& GetSize() const;
void Format ( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttrs = nullptr ) override; void Format ( vcl::RenderContext* pRenderContext, const SwBorderAttrs *pAttrs = nullptr ) override;
...@@ -60,6 +66,10 @@ public: ...@@ -60,6 +66,10 @@ public:
// RotateFlyFrame3 - Support for inner frame of a SwGrfNode // RotateFlyFrame3 - Support for inner frame of a SwGrfNode
virtual double getRotation() const override; virtual double getRotation() const override;
// RotateFlyFrame3 - Support for Transformations for inner frame of a SwGrfNode
basegfx::B2DHomMatrix getFrameAreaTransformation() const;
basegfx::B2DHomMatrix getFramePrintAreaTransformation() const;
}; };
#endif #endif
......
...@@ -44,13 +44,16 @@ ...@@ -44,13 +44,16 @@
using namespace ::com::sun::star; using namespace ::com::sun::star;
SwFlyFreeFrame::SwFlyFreeFrame( SwFlyFrameFormat *pFormat, SwFrame* pSib, SwFrame *pAnch ) : SwFlyFreeFrame::SwFlyFreeFrame( SwFlyFrameFormat *pFormat, SwFrame* pSib, SwFrame *pAnch )
SwFlyFrame( pFormat, pSib, pAnch ), : SwFlyFrame( pFormat, pSib, pAnch ),
// #i34753# // #i34753#
mbNoMakePos( false ), mbNoMakePos( false ),
// #i37068# // #i37068#
mbNoMoveOnCheckClip( false ), mbNoMoveOnCheckClip( false ),
maUnclippedFrame( ) maUnclippedFrame( ),
// RotateFlyFrame3
maFrameAreaTransformation(),
maFramePrintAreaTransformation()
{ {
} }
...@@ -223,36 +226,35 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) ...@@ -223,36 +226,35 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
} }
// RotateFlyFrame3 - inner frame // RotateFlyFrame3 - inner frame
// After the unrotated layout is finished, apply possible set rotation to it
const double fRotation(getRotation()); const double fRotation(getRotation());
if(0.0 != fRotation) if(basegfx::fTools::equalZero(fRotation))
{ {
SwRect aFrameArea(getFrameArea()); // reset transformations to show that they are not used
SwRect aFramePrintArea(getFramePrintArea()); maFrameAreaTransformation.identity();
Point aCenter(aFrameArea.Center()); maFramePrintAreaTransformation.identity();
}
if(GetUpper()) else
{ {
// get center from outer frame (layout frame) // save Transformations to local maFrameAreaTransformation
const SwRect aUpperFrameArea(GetUpper()->getFrameArea()); // and maFramePrintAreaTransformation.
aCenter = aUpperFrameArea.Center(); // get center from outer frame (layout frame) to be on the safe side
} const Point aCenter(GetUpper() ? GetUpper()->getFrameArea().Center() : getFrameArea().Center());
const basegfx::B2DPoint aB2DCenter(aCenter.X(), aCenter.Y());
// apply rotation and re-set the FrameArea definitions
rotateFrameAreaDefinitionAroundPoint(aFrameArea, aFramePrintArea, aCenter, fRotation); createFrameAreaTransformations(
maFrameAreaTransformation,
if(aFrameArea != getFrameArea()) maFramePrintAreaTransformation,
{ fRotation,
SwFrameAreaDefinition::FrameAreaWriteAccess aFrm(*this); aB2DCenter);
aFrm.setSwRect(aFrameArea);
} // create BoundRects of FrameAreas and re-set the FrameArea definitions
// to represent the rotated geometry in the layout object
if(aFramePrintArea != getFramePrintArea()) setFrameAreaDefinitionsToBoundRangesOfTransformations(
{ maFrameAreaTransformation,
SwFrameAreaDefinition::FramePrintAreaWriteAccess aPrt(*this); maFramePrintAreaTransformation);
aPrt.setSwRect(aFramePrintArea);
}
} }
Unlock(); Unlock();
...@@ -266,7 +268,32 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/) ...@@ -266,7 +268,32 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* /*pRenderContext*/)
#endif #endif
} }
// RotateFlyFrame3 // RotateFlyFrame3 - Support for Transformations - outer frame
basegfx::B2DHomMatrix SwFlyFreeFrame::getFrameAreaTransformation() const
{
if(!maFrameAreaTransformation.isIdentity())
{
// use pre-created transformation
return maFrameAreaTransformation;
}
// call parent
return SwFlyFrame::getFrameAreaTransformation();
}
basegfx::B2DHomMatrix SwFlyFreeFrame::getFramePrintAreaTransformation() const
{
if(!maFramePrintAreaTransformation.isIdentity())
{
// use pre-created transformation
return maFramePrintAreaTransformation;
}
// call parent
return SwFlyFrame::getFramePrintAreaTransformation();
}
// RotateFlyFrame3 - inner frame
double SwFlyFreeFrame::getRotation() const double SwFlyFreeFrame::getRotation() const
{ {
// SwLayoutFrame::Lower() != SwFrame::GetLower(), but SwFrame::GetLower() // SwLayoutFrame::Lower() != SwFrame::GetLower(), but SwFrame::GetLower()
......
...@@ -105,54 +105,98 @@ SwFrameAreaDefinition::FramePrintAreaWriteAccess::~FramePrintAreaWriteAccess() ...@@ -105,54 +105,98 @@ SwFrameAreaDefinition::FramePrintAreaWriteAccess::~FramePrintAreaWriteAccess()
} }
} }
void rotateFrameAreaDefinitionAroundPoint( void SwFrameAreaDefinition::createFrameAreaTransformations(
SwRect& rFrameArea, basegfx::B2DHomMatrix& rFrameAreaTransformation,
SwRect& rFramePrintArea, basegfx::B2DHomMatrix& rFramePrintAreaTransformation,
const Point& rCenter, double fRotation,
double fRotation) const basegfx::B2DPoint& rCenter) const
{ {
if(!basegfx::fTools::equalZero(fRotation) && rFrameArea.HasArea()) // save Transformations to rFrameAreaTransformation and
// rFramePrintAreaTransformation. Do not forget that PrintArea
// is *relative* to FrameArea
const basegfx::B2DHomMatrix aRotateAroundCenter(
basegfx::utils::createRotateAroundPoint(
rCenter.getX(),
rCenter.getY(),
fRotation));
rFrameAreaTransformation = aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix(
getFrameArea().Width(), getFrameArea().Height(),
getFrameArea().Left(), getFrameArea().Top());
rFramePrintAreaTransformation = aRotateAroundCenter * basegfx::utils::createScaleTranslateB2DHomMatrix(
getFramePrintArea().Width(), getFramePrintArea().Height(),
getFramePrintArea().Left() + getFrameArea().Left(), getFramePrintArea().Top() + getFrameArea().Top());
}
void SwFrameAreaDefinition::setFrameAreaDefinitionsToBoundRangesOfTransformations(
const basegfx::B2DHomMatrix& rFrameAreaTransformation,
const basegfx::B2DHomMatrix& rFramePrintAreaTransformation)
{
if(!rFrameAreaTransformation.isIdentity())
{ {
basegfx::B2DRange aFrameRange( basegfx::B2DRange aRangeFrameArea(0.0, 0.0, 1.0, 1.0);
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); aRangeFrameArea.transform(rFrameAreaTransformation);
rFrameArea = SwRect(
basegfx::fround(aFrameRange.getMinX()),
basegfx::fround(aFrameRange.getMinY()),
basegfx::fround(aFrameRange.getWidth()),
basegfx::fround(aFrameRange.getHeight()));
if(rFramePrintArea.HasArea()) const SwRect aNewFrm(
basegfx::fround(aRangeFrameArea.getMinX()), basegfx::fround(aRangeFrameArea.getMinY()),
basegfx::fround(aRangeFrameArea.getWidth()), basegfx::fround(aRangeFrameArea.getHeight()));
if(aNewFrm != getFrameArea())
{ {
basegfx::B2DRange aFramePrintRange( maFrameArea = aNewFrm;
rFramePrintArea.Left() + aOldTopLeft.getX(), }
rFramePrintArea.Top() + aOldTopLeft.getY(), }
rFramePrintArea.Right() + aOldTopLeft.getX(),
rFramePrintArea.Bottom() + aOldTopLeft.getY()); if(!rFramePrintAreaTransformation.isIdentity())
const basegfx::B2DPoint aNewTopLeft(aFrameRange.getMinimum()); {
basegfx::B2DRange aRangeFramePrintArea(0.0, 0.0, 1.0, 1.0);
aRangeFramePrintArea.transform(rFramePrintAreaTransformation);
const SwRect aNewPrt(
basegfx::fround(aRangeFramePrintArea.getMinX()) - getFrameArea().Left(),
basegfx::fround(aRangeFramePrintArea.getMinY()) - getFrameArea().Top(),
basegfx::fround(aRangeFramePrintArea.getWidth()),
basegfx::fround(aRangeFramePrintArea.getHeight()));
aFramePrintRange.transform(aRotateAroundCenter); if(aNewPrt != getFramePrintArea())
rFramePrintArea = SwRect( {
basegfx::fround(aFramePrintRange.getMinX() - aNewTopLeft.getX()), maFramePrintArea = aNewPrt;
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) // RotateFlyFrame3 - get a possible rotation from SwFrame
double SwFrame::getRotation() const double SwFrame::getRotation() const
{ {
// default returns 0.0 (no rotation)
return 0.0; return 0.0;
} }
// RotateFlyFrame3 - Support for Transformations
basegfx::B2DHomMatrix SwFrame::getFrameAreaTransformation() const
{
// default implementation hands out FrameArea (outer frame)
const SwRect& rFrameArea(getFrameArea());
return basegfx::utils::createScaleTranslateB2DHomMatrix(
rFrameArea.Width(), rFrameArea.Height(),
rFrameArea.Left(), rFrameArea.Top());
}
basegfx::B2DHomMatrix SwFrame::getFramePrintAreaTransformation() const
{
// default implementation hands out FramePrintArea (outer frame)
// Take into account that FramePrintArea is relative to FrameArea
const SwRect& rFrameArea(getFrameArea());
const SwRect& rFramePrintArea(getFramePrintArea());
return basegfx::utils::createScaleTranslateB2DHomMatrix(
rFramePrintArea.Width(), rFramePrintArea.Height(),
rFramePrintArea.Left() + rFrameArea.Left(),
rFramePrintArea.Top() + rFrameArea.Top());
}
SwFrame::SwFrame( SwModify *pMod, SwFrame* pSib ) SwFrame::SwFrame( SwModify *pMod, SwFrame* pSib )
: SwFrameAreaDefinition(), : SwFrameAreaDefinition(),
SwClient( pMod ), 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