diff options
author | Miklos Vajna <vmiklos@collabora.com> | 2019-09-20 11:55:21 +0200 |
---|---|---|
committer | Miklos Vajna <vmiklos@collabora.com> | 2019-09-20 12:42:17 +0200 |
commit | f8c7a2284b88c149addc8a30abb0cad8a10dad77 (patch) | |
tree | 546b535ce46c8a9f3f10fd165eee82c2d402000a /sw | |
parent | ea4f3099d6e0cf30d80caa8b2121c7a358f80fdd (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
Diffstat (limited to 'sw')
-rw-r--r-- | sw/inc/fmtwrapinfluenceonobjpos.hxx | 5 | ||||
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/tdf124600b.docx | bin | 0 -> 15959 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport13.cxx | 9 | ||||
-rw-r--r-- | sw/source/core/attr/fmtwrapinfluenceonobjpos.cxx | 10 | ||||
-rw-r--r-- | sw/source/core/doc/textboxhelper.cxx | 8 | ||||
-rw-r--r-- | sw/source/core/inc/tocntntanchoredobjectposition.hxx | 4 | ||||
-rw-r--r-- | sw/source/core/objectpositioning/tocntntanchoredobjectposition.cxx | 92 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxsdrexport.cxx | 4 |
8 files changed, 104 insertions, 28 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 Binary files differnew file mode 100644 index 000000000000..aa25ada91baf --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/tdf124600b.docx 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)); |