summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2019-09-20 11:55:21 +0200
committerMiklos Vajna <vmiklos@collabora.com>2019-09-20 12:42:17 +0200
commitf8c7a2284b88c149addc8a30abb0cad8a10dad77 (patch)
tree546b535ce46c8a9f3f10fd165eee82c2d402000a
parentea4f3099d6e0cf30d80caa8b2121c7a358f80fdd (diff)
Related: tdf#124600 sw anchored object allow overlap: add DOCX filter
Which also made it necessary to support allow-overlap=no for not only shapes, but for shapes-with-text in the layout. Change-Id: Ibd229d21995c0a1053db6bbab0a6ccbbf75f36d3 Reviewed-on: https://gerrit.libreoffice.org/79277 Reviewed-by: Miklos Vajna <vmiklos@collabora.com> Tested-by: Jenkins
-rw-r--r--sw/inc/fmtwrapinfluenceonobjpos.hxx5
-rw-r--r--sw/qa/extras/ooxmlexport/data/tdf124600b.docxbin0 -> 15959 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport13.cxx9
-rw-r--r--sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx10
-rw-r--r--sw/source/core/doc/textboxhelper.cxx8
-rw-r--r--sw/source/core/inc/tocntntanchoredobjectposition.hxx4
-rw-r--r--sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx92
-rw-r--r--sw/source/filter/ww8/docxsdrexport.cxx4
-rw-r--r--writerfilter/source/dmapper/GraphicImport.cxx9
9 files changed, 110 insertions, 31 deletions
diff --git a/sw/inc/fmtwrapinfluenceonobjpos.hxx b/sw/inc/fmtwrapinfluenceonobjpos.hxx
index 8e56be1ed653..897e825b14ff 100644
--- a/sw/inc/fmtwrapinfluenceonobjpos.hxx
+++ b/sw/inc/fmtwrapinfluenceonobjpos.hxx
@@ -21,6 +21,7 @@
#include "hintids.hxx"
#include "format.hxx"
+#include "swtypes.hxx"
#include <svl/poolitem.hxx>
#include <com/sun/star/text/WrapInfluenceOnPosition.hpp>
@@ -30,6 +31,8 @@ private:
sal_Int16 mnWrapInfluenceOnPosition;
/// Allow objects to overlap, permitted by default.
bool mbAllowOverlap = true;
+ /// Vertical offset added during positioning to avoid an overlap.
+ SwTwips mnOverlapVertOffset = 0;
public:
@@ -59,6 +62,8 @@ public:
void SetAllowOverlap(bool bAllowOverlap);
bool GetAllowOverlap() const;
+ void SetOverlapVertOffset(SwTwips nOverlapVertOffset);
+ SwTwips GetOverlapVertOffset() const;
void dumpAsXml(xmlTextWriterPtr pWriter) const override;
};
diff --git a/sw/qa/extras/ooxmlexport/data/tdf124600b.docx b/sw/qa/extras/ooxmlexport/data/tdf124600b.docx
new file mode 100644
index 000000000000..aa25ada91baf
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf124600b.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
index dd059cdb6af9..ad5aec4e6d39 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx
@@ -279,6 +279,15 @@ DECLARE_OOXMLEXPORT_TEST(tdf123912_protectedForm, "tdf123912_protectedForm.odt")
CPPUNIT_ASSERT_EQUAL_MESSAGE("Section1 is protected", false, getProperty<bool>(xSect, "IsProtected"));
}
+DECLARE_OOXMLEXPORT_TEST(tdf124600b, "tdf124600b.docx")
+{
+ // <wp:anchor allowOverlap="0"> was lost on roundtrip, we always wrote "1" on export.
+ bool bAllowOverlap1 = getProperty<bool>(getShape(1), "AllowOverlap");
+ CPPUNIT_ASSERT(!bAllowOverlap1);
+ bool bAllowOverlap2 = getProperty<bool>(getShape(2), "AllowOverlap");
+ CPPUNIT_ASSERT(!bAllowOverlap2);
+}
+
DECLARE_OOXMLEXPORT_TEST(testDateControl, "empty-date-control.odt")
{
// Check that we exported the empty date control correctly
diff --git a/sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx b/sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx
index a593416407c3..4182bb90a95a 100644
--- a/sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx
+++ b/sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx
@@ -43,7 +43,8 @@ bool SwFormatWrapInfluenceOnObjPos::operator==( const SfxPoolItem& rAttr ) const
const SwFormatWrapInfluenceOnObjPos& rAttribute
= static_cast<const SwFormatWrapInfluenceOnObjPos&>(rAttr);
return (mnWrapInfluenceOnPosition == rAttribute.GetWrapInfluenceOnObjPos()
- && mbAllowOverlap == rAttribute.mbAllowOverlap);
+ && mbAllowOverlap == rAttribute.mbAllowOverlap
+ && mnOverlapVertOffset == rAttribute.mnOverlapVertOffset);
}
SfxPoolItem* SwFormatWrapInfluenceOnObjPos::Clone( SfxItemPool * ) const
@@ -154,6 +155,13 @@ bool SwFormatWrapInfluenceOnObjPos::GetAllowOverlap() const
return mbAllowOverlap;
}
+void SwFormatWrapInfluenceOnObjPos::SetOverlapVertOffset(SwTwips nOverlapVertOffset)
+{
+ mnOverlapVertOffset = nOverlapVertOffset;
+}
+
+SwTwips SwFormatWrapInfluenceOnObjPos::GetOverlapVertOffset() const { return mnOverlapVertOffset; }
+
void SwFormatWrapInfluenceOnObjPos::dumpAsXml(xmlTextWriterPtr pWriter) const
{
xmlTextWriterStartElement(pWriter, BAD_CAST("SwFormatWrapInfluenceOnObjPos"));
diff --git a/sw/source/core/doc/textboxhelper.cxx b/sw/source/core/doc/textboxhelper.cxx
index 83672434b79d..89072dffae14 100644
--- a/sw/source/core/doc/textboxhelper.cxx
+++ b/sw/source/core/doc/textboxhelper.cxx
@@ -563,6 +563,14 @@ void SwTextBoxHelper::syncProperty(SwFrameFormat* pShape, sal_uInt16 nWID, sal_u
case RES_FRAMEDIR:
aPropertyName = UNO_NAME_WRITING_MODE;
break;
+ case RES_WRAP_INFLUENCE_ON_OBJPOS:
+ switch (nMemberID)
+ {
+ case MID_ALLOW_OVERLAP:
+ aPropertyName = UNO_NAME_ALLOW_OVERLAP;
+ break;
+ }
+ break;
}
if (!aPropertyName.isEmpty())
diff --git a/sw/source/core/inc/tocntntanchoredobjectposition.hxx b/sw/source/core/inc/tocntntanchoredobjectposition.hxx
index 01033a6f1e7b..07dd957cdf9c 100644
--- a/sw/source/core/inc/tocntntanchoredobjectposition.hxx
+++ b/sw/source/core/inc/tocntntanchoredobjectposition.hxx
@@ -81,6 +81,10 @@ namespace objectpositioning
/** frame, at which the vertical position is oriented at
*/
const SwLayoutFrame& GetVertPosOrientFrame() const { return *mpVertPosOrientFrame;}
+
+ /// In case overlap is not allowed, re-position the current object.
+ void CalcOverlap(const SwTextFrame* pAnchorFrameForVertPos, Point& rRelPos,
+ const SwTwips nTopOfAnch);
};
} // namespace objectpositioning
diff --git a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
index f26b48ac0a98..0fc56d1af80e 100644
--- a/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
+++ b/sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx
@@ -44,6 +44,7 @@
#include <dflyobj.hxx>
#include <fmtwrapinfluenceonobjpos.hxx>
#include <sortedobjs.hxx>
+#include <textboxhelper.hxx>
using namespace objectpositioning;
using namespace ::com::sun::star;
@@ -975,32 +976,7 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
// If it was requested to not overlap with already formatted objects, take care of that
// here.
- bool bAllowOverlap = rFrameFormat.GetWrapInfluenceOnObjPos().GetAllowOverlap();
- if (!bAllowOverlap)
- {
- // Get the list of objects.
- const SwSortedObjs& rSortedObjs = *pAnchorFrameForVertPos->GetDrawObjs();
- for (const auto& pAnchoredObj : rSortedObjs)
- {
- if (pAnchoredObj == &GetAnchoredObj())
- {
- // We found ourselves, stop iterating.
- break;
- }
-
- if (!GetAnchoredObj().GetObjRect().IsOver(pAnchoredObj->GetObjRect()))
- {
- // Found an already positioned object, but it doesn't overlap, ignore.
- continue;
- }
-
- // Already formatted, overlaps: resolve the conflict by shifting ourselves down.
- SwTwips nYDiff
- = pAnchoredObj->GetObjRect().Bottom() - GetAnchoredObj().GetObjRect().Top();
- aRelPos.setY(aRelPos.getY() + nYDiff + 1);
- GetAnchoredObj().SetObjTop(nTopOfAnch + aRelPos.Y());
- }
- }
+ CalcOverlap(pAnchorFrameForVertPos, aRelPos, nTopOfAnch);
}
// determine 'horizontal' position
@@ -1097,6 +1073,70 @@ void SwToContentAnchoredObjectPosition::CalcPosition()
GetAnchoredObj().SetCurrRelPos( aRelPos );
}
+void SwToContentAnchoredObjectPosition::CalcOverlap(const SwTextFrame* pAnchorFrameForVertPos,
+ Point& rRelPos, const SwTwips nTopOfAnch)
+{
+ const SwFrameFormat& rFrameFormat = GetFrameFormat();
+ bool bAllowOverlap = rFrameFormat.GetWrapInfluenceOnObjPos().GetAllowOverlap();
+ if (bAllowOverlap)
+ {
+ return;
+ }
+
+ if (SwTextBoxHelper::isTextBox(&rFrameFormat, RES_FLYFRMFMT))
+ {
+ // This is the frame part of a textbox, just take the offset from the textbox's shape part.
+ SwFrameFormat* pShapeOfTextBox
+ = SwTextBoxHelper::getOtherTextBoxFormat(&rFrameFormat, RES_FLYFRMFMT);
+ if (pShapeOfTextBox)
+ {
+ SwTwips nYDiff = pShapeOfTextBox->GetWrapInfluenceOnObjPos().GetOverlapVertOffset();
+ if (nYDiff > 0)
+ {
+ rRelPos.setY(rRelPos.getY() + nYDiff + 1);
+ GetAnchoredObj().SetObjTop(nTopOfAnch + rRelPos.Y());
+ }
+ }
+ return;
+ }
+
+ // Get the list of objects.
+ const SwSortedObjs& rSortedObjs = *pAnchorFrameForVertPos->GetDrawObjs();
+ for (const auto& pAnchoredObj : rSortedObjs)
+ {
+ if (pAnchoredObj == &GetAnchoredObj())
+ {
+ // We found ourselves, stop iterating.
+ break;
+ }
+
+ if (SwTextBoxHelper::isTextBox(&pAnchoredObj->GetFrameFormat(), RES_FLYFRMFMT))
+ {
+ // Overlapping with the frame of a textbox is fine.
+ continue;
+ }
+
+ if (!GetAnchoredObj().GetObjRect().IsOver(pAnchoredObj->GetObjRect()))
+ {
+ // Found an already positioned object, but it doesn't overlap, ignore.
+ continue;
+ }
+
+ // Already formatted, overlaps: resolve the conflict by shifting ourselves down.
+ SwTwips nYDiff = pAnchoredObj->GetObjRect().Bottom() - GetAnchoredObj().GetObjRect().Top();
+ rRelPos.setY(rRelPos.getY() + nYDiff + 1);
+ GetAnchoredObj().SetObjTop(nTopOfAnch + rRelPos.Y());
+
+ // Store our offset that avoids the overlap. If this is a shape of a textbox, then the frame
+ // of the textbox will use it.
+ SwFormatWrapInfluenceOnObjPos aInfluence(rFrameFormat.GetWrapInfluenceOnObjPos());
+ aInfluence.SetOverlapVertOffset(nYDiff);
+ const_cast<SwFrameFormat&>(rFrameFormat).LockModify();
+ const_cast<SwFrameFormat&>(rFrameFormat).SetFormatAttr(aInfluence);
+ const_cast<SwFrameFormat&>(rFrameFormat).UnlockModify();
+ }
+}
+
/**
* Determine frame for horizontal position
*/
diff --git a/sw/source/filter/ww8/docxsdrexport.cxx b/sw/source/filter/ww8/docxsdrexport.cxx
index d250b4747bdd..de82c29deae6 100644
--- a/sw/source/filter/ww8/docxsdrexport.cxx
+++ b/sw/source/filter/ww8/docxsdrexport.cxx
@@ -24,6 +24,7 @@
#include <fmtornt.hxx>
#include <fmtfsize.hxx>
#include <frmatr.hxx>
+#include <fmtwrapinfluenceonobjpos.hxx>
#include "docxattributeoutput.hxx"
#include "docxexportfilter.hxx"
#include <comphelper/flagguard.hxx>
@@ -465,7 +466,8 @@ void DocxSdrExport::startDMLAnchorInline(const SwFrameFormat* pFrameFormat, cons
attrList->add(XML_simplePos, "0");
attrList->add(XML_locked, "0");
attrList->add(XML_layoutInCell, "1");
- attrList->add(XML_allowOverlap, "1"); // TODO
+ bool bAllowOverlap = pFrameFormat->GetWrapInfluenceOnObjPos().GetAllowOverlap();
+ attrList->add(XML_allowOverlap, bAllowOverlap ? "1" : "0");
if (pObj != nullptr)
// It seems 0 and 1 have special meaning: just start counting from 2 to avoid issues with that.
attrList->add(XML_relativeHeight, OString::number(pObj->GetOrdNum() + 2));
diff --git a/writerfilter/source/dmapper/GraphicImport.cxx b/writerfilter/source/dmapper/GraphicImport.cxx
index c148d7989e0d..269a4e290ecb 100644
--- a/writerfilter/source/dmapper/GraphicImport.cxx
+++ b/writerfilter/source/dmapper/GraphicImport.cxx
@@ -197,6 +197,7 @@ public:
sal_Int16 nVertRelation;
text::WrapTextMode nWrap;
bool bLayoutInCell;
+ bool bAllowOverlap = true;
bool bOpaque;
bool bContour;
bool bContourOutside;
@@ -596,9 +597,9 @@ void GraphicImport::lcl_attribute(Id nName, Value& rValue)
break;
case NS_ooxml::LN_CT_Anchor_hidden: // 90992; - ignored
break;
- case NS_ooxml::LN_CT_Anchor_allowOverlap: // 90993;
- //enable overlapping - ignored
- break;
+ case NS_ooxml::LN_CT_Anchor_allowOverlap:
+ m_pImpl->bAllowOverlap = nIntValue != 0;
+ break;
case NS_ooxml::LN_CT_Anchor_wp14_anchorId:
case NS_ooxml::LN_CT_Inline_wp14_anchorId:
{
@@ -866,6 +867,8 @@ void GraphicImport::lcl_attribute(Id nName, Value& rValue)
xShapeProps->setPropertyValue("Surround", uno::makeAny(static_cast<sal_Int32>(m_pImpl->nWrap)));
m_pImpl->applyZOrder(xShapeProps);
m_pImpl->applyName(xShapeProps);
+ xShapeProps->setPropertyValue("AllowOverlap",
+ uno::makeAny(m_pImpl->bAllowOverlap));
// Get the grab-bag set by oox, merge with our one and then put it back.
comphelper::SequenceAsHashMap aInteropGrabBag(xShapeProps->getPropertyValue("InteropGrabBag"));