summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.co.uk>2016-04-01 14:44:09 +0200
committerMiklos Vajna <vmiklos@collabora.co.uk>2016-04-01 14:23:03 +0000
commitcd1b2f923e0b0be89a5d1c8cbc647133aac09ed5 (patch)
tree29faef24c35a17efe2d0bd49e599bb7146a332fd
parentd3d45ab54e78fa760860923d0ff5c4692d89c99c (diff)
tdf#99004 SwAnchoredObjectPosition: handle textboxes when determining surround
Writer TextBoxes are always wrapped "through", so that they can appear inside their shapes. However, the surround of the shape may influence its position. So when surround is asked for anchor position purposes, take the surround of the TextBox's "parent" shape instead of the one of the TextBox directly. With this, the TextBox in the bugdoc is properly positioned inside its parent shape as expected. (The problem only happens when at least two shapes are anchored to the same paragraph.) Change-Id: I0cf8a41080e6759aa395c119d862c4be79574d66 Reviewed-on: https://gerrit.libreoffice.org/23720 Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk> Tested-by: Jenkins <ci@libreoffice.org>
-rw-r--r--sw/inc/textboxhelper.hxx2
-rw-r--r--sw/qa/extras/uiwriter/data/tdf99004.docxbin0 -> 18435 bytes
-rw-r--r--sw/qa/extras/uiwriter/uiwriter.cxx17
-rw-r--r--sw/source/core/doc/textboxhelper.cxx10
-rw-r--r--sw/source/core/inc/anchoredobjectposition.hxx9
-rw-r--r--sw/source/core/objectpositioning/anchoredobjectposition.cxx28
-rw-r--r--sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx20
-rw-r--r--sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx4
8 files changed, 60 insertions, 30 deletions
diff --git a/sw/inc/textboxhelper.hxx b/sw/inc/textboxhelper.hxx
index d72ba4da5311..2b3e08738230 100644
--- a/sw/inc/textboxhelper.hxx
+++ b/sw/inc/textboxhelper.hxx
@@ -87,6 +87,8 @@ public:
static css::uno::Any getByIndex(SdrPage* pPage, sal_Int32 nIndex, std::set<const SwFrameFormat*>& rTextBoxes) throw(css::lang::IndexOutOfBoundsException);
/// Get the order of the shape, excluding TextBoxes.
static sal_Int32 getOrdNum(const SdrObject* pObject, std::set<const SwFrameFormat*>& rTextBoxes);
+ /// If pTextBox is a textbox, then set rWrapThrough to the surround of its shape.
+ static void getShapeWrapThrough(const SwFrameFormat* pTextBox, bool& rWrapThrough);
/// Saves the current shape -> textbox links in a map, so they can be restored later.
static void saveLinks(const SwFrameFormats& rFormats, std::map<const SwFrameFormat*, const SwFrameFormat*>& rLinks);
diff --git a/sw/qa/extras/uiwriter/data/tdf99004.docx b/sw/qa/extras/uiwriter/data/tdf99004.docx
new file mode 100644
index 000000000000..ef864407effc
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/tdf99004.docx
Binary files differ
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index b450520cb0d8..56db245f7045 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -195,6 +195,7 @@ public:
void testTdf88453Table();
void testClassificationPaste();
void testTdf98987();
+ void testTdf99004();
CPPUNIT_TEST_SUITE(SwUiWriterTest);
CPPUNIT_TEST(testReplaceForward);
@@ -292,6 +293,7 @@ public:
CPPUNIT_TEST(testTdf88453Table);
CPPUNIT_TEST(testClassificationPaste);
CPPUNIT_TEST(testTdf98987);
+ CPPUNIT_TEST(testTdf99004);
CPPUNIT_TEST_SUITE_END();
private:
@@ -3592,6 +3594,21 @@ void SwUiWriterTest::testTdf98987()
CPPUNIT_ASSERT(nRectangle2 < nRectangle3);
}
+void SwUiWriterTest::testTdf99004()
+{
+ createDoc("tdf99004.docx");
+ calcLayout();
+ xmlDocPtr pXmlDoc = parseLayoutDump();
+ sal_Int32 nTextbox1Top = getXPath(pXmlDoc, "/root/page/body/txt/anchored/fly/infos/bounds", "top").toInt32();
+ sal_Int32 nTextBox1Height = getXPath(pXmlDoc, "/root/page/body/txt/anchored/fly/infos/bounds", "height").toInt32();
+ sal_Int32 nTextBox1Bottom = nTextbox1Top + nTextBox1Height;
+
+ assertXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/sdrObject", "name", "Rectangle 2");
+ sal_Int32 nRectangle2Top = getXPath(pXmlDoc, "/root/page/body/txt/anchored/SwAnchoredDrawObject[1]/bounds", "top").toInt32();
+ // This was 3291 and 2531, should be now around 2472 and 2531, i.e. the two rectangles should not overlap anymore.
+ CPPUNIT_ASSERT(nTextBox1Bottom < nRectangle2Top);
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(SwUiWriterTest);
CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx
index 1d334b504920..b52c9cdf34d9 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -27,6 +27,7 @@
#include <mvsave.hxx>
#include <sortedobjs.hxx>
#include <cntfrm.hxx>
+#include <fmtsrnd.hxx>
#include <editeng/unoprnms.hxx>
#include <editeng/charrotateitem.hxx>
@@ -264,6 +265,15 @@ sal_Int32 SwTextBoxHelper::getOrdNum(const SdrObject* pObject, std::set<const Sw
return pObject->GetOrdNum();
}
+void SwTextBoxHelper::getShapeWrapThrough(const SwFrameFormat* pTextBox, bool& rWrapThrough)
+{
+ std::map<SwFrameFormat*, SwFrameFormat*> aMap = findShapes(pTextBox->GetDoc());
+ std::map<SwFrameFormat*, SwFrameFormat*>::iterator it = aMap.find(const_cast<SwFrameFormat*>(pTextBox));
+ if (it != aMap.end())
+ // pTextBox is indeed a TextBox, it->second is its shape.
+ rWrapThrough = it->second->GetSurround().GetSurround() == SURROUND_THROUGHT;
+}
+
SwFrameFormat* SwTextBoxHelper::findTextBox(uno::Reference<drawing::XShape> xShape)
{
SwXShape* pShape = dynamic_cast<SwXShape*>(xShape.get());
diff --git a/sw/source/core/inc/anchoredobjectposition.hxx b/sw/source/core/inc/anchoredobjectposition.hxx
index d6c62242ee8a..d50c0a57d7e6 100644
--- a/sw/source/core/inc/anchoredobjectposition.hxx
+++ b/sw/source/core/inc/anchoredobjectposition.hxx
@@ -126,17 +126,15 @@ namespace objectpositioning
#i11860#
*/
- static SwTwips _GetTopForObjPos( const SwFrame& _rFrame,
+ SwTwips _GetTopForObjPos( const SwFrame& _rFrame,
const SwRectFn& _fnRect,
- const bool _bVert,
- bool bWrapThrough );
+ const bool _bVert ) const;
void _GetVertAlignmentValues( const SwFrame& _rVertOrientFrame,
const SwFrame& _rPageAlignLayFrame,
const sal_Int16 _eRelOrient,
SwTwips& _orAlignAreaHeight,
- SwTwips& _orAlignAreaOffset,
- bool bWrapThrough ) const;
+ SwTwips& _orAlignAreaOffset ) const;
// #i26791# - add output parameter <_roVertOffsetToFrameAnchorPos>
SwTwips _GetVertRelPos( const SwFrame& _rVertOrientFrame,
@@ -146,7 +144,6 @@ namespace objectpositioning
const SwTwips _nVertPos,
const SvxLRSpaceItem& _rLRSpacing,
const SvxULSpaceItem& _rULSpacing,
- bool bWrapThrough,
SwTwips& _roVertOffsetToFrameAnchorPos ) const;
/** adjust calculated vertical in order to keep object inside
diff --git a/sw/source/core/objectpositioning/anchoredobjectposition.cxx b/sw/source/core/objectpositioning/anchoredobjectposition.cxx
index fbadb3a10d74..f47c720f7b88 100644
--- a/sw/source/core/objectpositioning/anchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/anchoredobjectposition.cxx
@@ -37,6 +37,7 @@
#include <ndtxt.hxx>
#include <IDocumentSettingAccess.hxx>
#include <textboxhelper.hxx>
+#include <fmtsrnd.hxx>
using namespace ::com::sun::star;
using namespace objectpositioning;
@@ -156,8 +157,7 @@ SwTwips SwAnchoredObjectPosition::ToCharTopOfLine() const
*/
SwTwips SwAnchoredObjectPosition::_GetTopForObjPos( const SwFrame& _rFrame,
const SwRectFn& _fnRect,
- const bool _bVert,
- bool bWrapThrough )
+ const bool _bVert ) const
{
SwTwips nTopOfFrameForObjPos = (_rFrame.Frame().*_fnRect->fnGetTop)();
@@ -174,6 +174,12 @@ SwTwips SwAnchoredObjectPosition::_GetTopForObjPos( const SwFrame& _rFrame,
nTopOfFrameForObjPos +=
rTextFrame.GetUpperSpaceAmountConsideredForPrevFrameAndPageGrid();
+ const SwFormatSurround& rSurround = mpFrameFormat->GetSurround();
+ bool bWrapThrough = rSurround.GetSurround() == SURROUND_THROUGHT;
+ // If the frame format is a TextBox of a draw shape, then use the
+ // surround of the original shape.
+ SwTextBoxHelper::getShapeWrapThrough(mpFrameFormat, bWrapThrough);
+
// Get the offset between the top of the text frame and the top of
// the first line inside the frame that has more than just fly
// portions.
@@ -189,14 +195,13 @@ void SwAnchoredObjectPosition::_GetVertAlignmentValues(
const SwFrame& _rPageAlignLayFrame,
const sal_Int16 _eRelOrient,
SwTwips& _orAlignAreaHeight,
- SwTwips& _orAlignAreaOffset,
- bool bWrapThrough ) const
+ SwTwips& _orAlignAreaOffset ) const
{
SwTwips nHeight = 0;
SwTwips nOffset = 0;
SWRECTFN( (&_rVertOrientFrame) )
// #i11860# - top of <_rVertOrientFrame> for object positioning
- const SwTwips nVertOrientTop = _GetTopForObjPos( _rVertOrientFrame, fnRect, bVert, bWrapThrough );
+ const SwTwips nVertOrientTop = _GetTopForObjPos( _rVertOrientFrame, fnRect, bVert );
// #i11860# - upper space amount of <_rVertOrientFrame> considered
// for previous frame
const SwTwips nVertOrientUpperSpaceForPrevFrameAndPageGrid =
@@ -327,7 +332,6 @@ SwTwips SwAnchoredObjectPosition::_GetVertRelPos(
const SwTwips _nVertPos,
const SvxLRSpaceItem& _rLRSpacing,
const SvxULSpaceItem& _rULSpacing,
- bool bWrapThrough,
SwTwips& _roVertOffsetToFrameAnchorPos ) const
{
SwTwips nRelPosY = 0;
@@ -336,7 +340,7 @@ SwTwips SwAnchoredObjectPosition::_GetVertRelPos(
SwTwips nAlignAreaHeight;
SwTwips nAlignAreaOffset;
_GetVertAlignmentValues( _rVertOrientFrame, _rPageAlignLayFrame,
- _eRelOrient, nAlignAreaHeight, nAlignAreaOffset, bWrapThrough );
+ _eRelOrient, nAlignAreaHeight, nAlignAreaOffset );
nRelPosY = nAlignAreaOffset;
const SwRect aObjBoundRect( GetAnchoredObj().GetObjRect() );
@@ -693,10 +697,12 @@ void SwAnchoredObjectPosition::_GetHoriAlignmentValues( const SwFrame& _rHoriOr
{
nWidth = (_rHoriOrientFrame.Frame().*fnRect->fnGetWidth)();
- // When positioning TextBoxes, always ignore flys anchored at the
- // text frame, as we do want to have the textbox overlap with its
- // draw shape.
- bool bIgnoreFlysAnchoredAtFrame = !_bObjWrapThrough || SwTextBoxHelper::isTextBox(&GetObject());
+ bool bWrapThrough = _bObjWrapThrough;
+ // If the frame format is a TextBox of a draw shape, then use the
+ // surround of the original shape.
+ SwTextBoxHelper::getShapeWrapThrough(mpFrameFormat, bWrapThrough);
+
+ bool bIgnoreFlysAnchoredAtFrame = !bWrapThrough;
nOffset = _rHoriOrientFrame.IsTextFrame() ?
static_cast<const SwTextFrame&>(_rHoriOrientFrame).GetBaseOfstForFly( bIgnoreFlysAnchoredAtFrame ) :
0;
diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
index 5abf15ba629b..f51d0612dad6 100644
--- a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
@@ -248,7 +248,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
SwTwips nAlignAreaOffset;
_GetVertAlignmentValues( *pOrientFrame, rPageAlignLayFrame,
aVert.GetRelationOrient(),
- nAlignAreaHeight, nAlignAreaOffset, bWrapThrough );
+ nAlignAreaHeight, nAlignAreaOffset );
// determine relative vertical position
SwTwips nRelPosY = nAlignAreaOffset;
@@ -380,16 +380,16 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
{
// #i11860# - use new method <_GetTopForObjPos>
// to get top of frame for object positioning.
- const SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrame, fnRect, bVert, bWrapThrough );
+ const SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrame, fnRect, bVert );
nRelPosY += (*fnRect->fnYDiff)( nTopOfOrient,
- _GetTopForObjPos( rAnchorTextFrame, fnRect, bVert, bWrapThrough ) );
+ _GetTopForObjPos( rAnchorTextFrame, fnRect, bVert ) );
}
// #i42124# - capture object inside vertical
// layout environment.
{
const SwTwips nTopOfAnch =
- _GetTopForObjPos( *pOrientFrame, fnRect, bVert, bWrapThrough );
+ _GetTopForObjPos( *pOrientFrame, fnRect, bVert );
const SwLayoutFrame& rVertEnvironLayFrame =
aEnvOfObj.GetVertEnvironmentLayoutFrame(
*(pOrientFrame->GetUpper()) );
@@ -486,7 +486,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
{
// #i11860# - use new method <_GetTopForObjPos>
// to get top of frame for object positioning.
- SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrame, fnRect, bVert, bWrapThrough );
+ SwTwips nTopOfOrient = _GetTopForObjPos( *pOrientFrame, fnRect, bVert );
if ( aVert.GetRelationOrient() == text::RelOrientation::CHAR )
{
nVertOffsetToFrameAnchorPos = (*fnRect->fnYDiff)(
@@ -509,7 +509,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
// #i11860# - use new method <_GetTopForObjPos>
// to get top of frame for object positioning.
const SwTwips nTopOfOrient =
- _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert, bWrapThrough );
+ _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert );
// Increase <nRelPosY> by margin height,
// if position is vertical aligned to "paragraph text area"
if ( aVert.GetRelationOrient() == text::RelOrientation::PRINT_AREA )
@@ -562,7 +562,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
maOffsetToFrameAnchorPos.Y() = nVertOffsetToFrameAnchorPos;
// #i11860# - use new method <_GetTopForObjPos>
// to get top of frame for object positioning.
- const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert, bWrapThrough );
+ const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert );
if( nRelPosY <= 0 )
{
// Allow negative position, but keep it
@@ -717,7 +717,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
// We need to calculate the part's absolute position, in order for
// it to be put onto the right page and to be pulled into the
// LayLeaf's PrtArea
- const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert, bWrapThrough );
+ const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert );
if( bVert )
{
// --> OD 2009-08-31 #monglianlayout#
@@ -979,7 +979,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
// set calculated vertical position in order to determine correct
// frame, the horizontal position is oriented at.
- const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert, bWrapThrough );
+ const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert );
if( bVert )
{
// --> OD 2009-08-31 #mongolianlayout#
@@ -1039,7 +1039,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
}
// set absolute position at object
- const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert, bWrapThrough );
+ const SwTwips nTopOfAnch = _GetTopForObjPos( *pAnchorFrameForVertPos, fnRect, bVert );
if( bVert )
{
// --> OD 2009-08-31 #mongolianlayout#
diff --git a/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx b/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx
index 09b6172f7bbd..45d8f09762d6 100644
--- a/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/tolayoutanchoredobjectposition.cxx
@@ -81,12 +81,10 @@ void SwToLayoutAnchoredObjectPosition::CalcPosition()
}
// #i26791# - get vertical offset to frame anchor position.
SwTwips nVertOffsetToFrameAnchorPos( 0L );
- const SwFormatSurround& rSurround = rFrameFormat.GetSurround();
- const bool bWrapThrough = rSurround.GetSurround() == SURROUND_THROUGHT;
SwTwips nRelPosY =
_GetVertRelPos( GetAnchorFrame(), GetAnchorFrame(), eVertOrient,
aVert.GetRelationOrient(), aVert.GetPos(),
- rLR, rUL, bWrapThrough, nVertOffsetToFrameAnchorPos );
+ rLR, rUL, nVertOffsetToFrameAnchorPos );
// keep the calculated relative vertical position - needed for filters
// (including the xml-filter)