summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/qa/extras/ooxmlexport/data/tdf115719.docxbin0 -> 11905 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport11.cxx7
-rw-r--r--writerfilter/source/dmapper/DomainMapperTableHandler.cxx30
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.cxx17
-rw-r--r--writerfilter/source/dmapper/DomainMapper_Impl.hxx16
-rw-r--r--writerfilter/source/dmapper/PropertyMap.cxx68
-rw-r--r--writerfilter/source/dmapper/PropertyMap.hxx4
-rw-r--r--writerfilter/source/dmapper/SettingsTable.cxx27
-rw-r--r--writerfilter/source/dmapper/SettingsTable.hxx2
9 files changed, 142 insertions, 29 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/tdf115719.docx b/sw/qa/extras/ooxmlexport/data/tdf115719.docx
new file mode 100644
index 000000000000..9519a2a14524
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf115719.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
index 58e654159494..98e207c81d81 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
@@ -99,6 +99,13 @@ DECLARE_OOXMLEXPORT_TEST(testTdf67207_MERGEFIELD, "mailmerge.docx")
CPPUNIT_ASSERT_EQUAL(OUString("com.sun.star.text.fieldmaster.DataBase.Name"), sValue);
}
+DECLARE_OOXMLEXPORT_TEST(testTdf115719, "tdf115719.docx")
+{
+ // This was a single page, instead of pushing the textboxes to the second
+ // page.
+ CPPUNIT_ASSERT_EQUAL(2, getPages());
+}
+
DECLARE_OOXMLEXPORT_TEST(testTdf113183, "tdf113183.docx")
{
// This was 2096, the horizontal positioning of the star shape affected the
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index 2f254be9c67c..e6f993e19387 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
@@ -312,34 +312,6 @@ void lcl_DecrementHoriOrientPosition(std::vector<beans::PropertyValue>& rFramePr
}
}
-sal_Int32 lcl_getWordCompatibilityMode( const css::uno::Sequence< css::beans::PropertyValue >& rCompatSettings )
-{
- for ( int i = 0; i < rCompatSettings.getLength(); ++i )
- {
- const css::beans::PropertyValue& rProp = rCompatSettings[i];
- if ( rProp.Name == "compatSetting" )
- {
- css::uno::Sequence< css::beans::PropertyValue > aCurrentCompatSettings;
- rProp.Value >>= aCurrentCompatSettings;
-
- OUString sName;
- OUString sUri;
- OUString sVal;
-
- aCurrentCompatSettings[0].Value >>= sName;
- aCurrentCompatSettings[1].Value >>= sUri;
- aCurrentCompatSettings[2].Value >>= sVal;
-
- if ( sName == "compatibilityMode" && sUri == "http://schemas.microsoft.com/office/word" )
- {
- return sVal.toInt32();
- }
- }
- }
-
- return -1; // Word compatibility mode not found
-}
-
TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo & rInfo, std::vector<beans::PropertyValue>& rFrameProperties)
{
// will receive the table style if any
@@ -574,7 +546,7 @@ TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo
// tdf#106742: since MS Word 2013 (compatibilityMode >= 15), top-level tables are handled the same as nested tables;
// this is also the default behavior in LO when DOCX doesn't define "compatibilityMode" option
- sal_Int32 nMode = lcl_getWordCompatibilityMode( m_rDMapper_Impl.GetSettingsTable()->GetCompatSettings() );
+ sal_Int32 nMode = m_rDMapper_Impl.GetSettingsTable()->GetWordCompatibilityMode();
if ( nMode > 0 && nMode <= 14 && rInfo.nNestLevel == 1 )
{
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 115bdb002688..ff412635b6fa 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1247,6 +1247,17 @@ void DomainMapper_Impl::finishParagraph( const PropertyMapPtr& pPropertyMap )
xTextRange = xTextAppend->finishParagraph( comphelper::containerToSequence(aProperties) );
m_xPreviousParagraph.set(xTextRange, uno::UNO_QUERY);
+
+ if (!rAppendContext.m_aAnchoredObjects.empty())
+ {
+ // Remember what objects are anchored to this paragraph.
+ AnchoredObjectInfo aInfo;
+ aInfo.m_xParagraph = xTextRange;
+ aInfo.m_aAnchoredObjects = rAppendContext.m_aAnchoredObjects;
+ m_aAnchoredObjectAnchors.push_back(aInfo);
+ rAppendContext.m_aAnchoredObjects.clear();
+ }
+
// We're no longer right after a table conversion.
m_bConvertedTable = false;
@@ -5130,8 +5141,14 @@ void DomainMapper_Impl::ImportGraphic(const writerfilter::Reference< Properties
//insert it into the document at the current cursor position
OSL_ENSURE( xTextContent.is(), "DomainMapper_Impl::ImportGraphic");
if( xTextContent.is())
+ {
appendTextContent( xTextContent, uno::Sequence< beans::PropertyValue >() );
+ if (eGraphicImportType == IMPORT_AS_DETECTED_ANCHOR && !m_aTextAppendStack.empty())
+ // Remember this object is anchored to the current paragraph.
+ m_aTextAppendStack.top().m_aAnchoredObjects.push_back(xTextContent);
+ }
+
// Clear the reference, so in case the embedded object is inside a
// TextFrame, we won't try to resize it (to match the size of the
// TextFrame) here.
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index cf51e7fac46c..807f80164342 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -215,6 +215,12 @@ struct TextAppendContext
css::uno::Reference<css::text::XParagraphCursor> xCursor;
ParagraphPropertiesPtr pLastParagraphProperties;
+ /**
+ * Objects anchored to the current paragraph, may affect the paragraph
+ * spacing.
+ */
+ std::vector<css::uno::Reference<css::text::XTextContent>> m_aAnchoredObjects;
+
TextAppendContext(const css::uno::Reference<css::text::XTextAppend>& xAppend, const css::uno::Reference<css::text::XTextCursor>& xCur)
: xTextAppend(xAppend)
{
@@ -374,6 +380,13 @@ struct FloatingTableInfo
css::uno::Any getPropertyValue(const OUString &propertyName);
};
+/// Stores info about objects anchored to a given paragraph.
+struct AnchoredObjectInfo
+{
+ css::uno::Reference<css::text::XTextRange> m_xParagraph;
+ std::vector<css::uno::Reference<css::text::XTextContent>> m_aAnchoredObjects;
+};
+
struct SymbolData
{
sal_Unicode cSymbol;
@@ -915,6 +928,9 @@ public:
/// Pending floating tables: they may be converted to text frames at the section end.
std::vector<FloatingTableInfo> m_aPendingFloatingTables;
+ /// Paragraphs with anchored objects in the current section.
+ std::vector<AnchoredObjectInfo> m_aAnchoredObjectAnchors;
+
/// Append a property to a sub-grabbag if necessary (e.g. 'lineRule', 'auto')
void appendGrabBag(std::vector<css::beans::PropertyValue>& rInteropGrabBag, const OUString& aKey, const OUString& aValue);
void appendGrabBag(std::vector<css::beans::PropertyValue>& rInteropGrabBag, const OUString& aKey, std::vector<css::beans::PropertyValue>& rValue);
diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx
index b1ee1fd971a3..84625c073d57 100644
--- a/writerfilter/source/dmapper/PropertyMap.cxx
+++ b/writerfilter/source/dmapper/PropertyMap.cxx
@@ -1126,6 +1126,72 @@ void SectionPropertyMap::InheritOrFinalizePageStyles( DomainMapper_Impl& rDM_Imp
}
}
+void SectionPropertyMap::HandleIncreasedAnchoredObjectSpacing(DomainMapper_Impl& rDM_Impl)
+{
+ // Ignore Word 2010 and older.
+ if (rDM_Impl.GetSettingsTable()->GetWordCompatibilityMode() < 15)
+ return;
+
+ sal_Int32 nPageWidth = GetPageWidth();
+ sal_Int32 nTextAreaWidth = nPageWidth - GetLeftMargin() - GetRightMargin();
+
+ std::vector<AnchoredObjectInfo>& rAnchoredObjectAnchors = rDM_Impl.m_aAnchoredObjectAnchors;
+ for (auto& rAnchor : rAnchoredObjectAnchors)
+ {
+ // Analyze the anchored objects of this paragraph, now that we know the
+ // page width.
+ sal_Int32 nShapesWidth = 0;
+ for (const auto& rAnchored : rAnchor.m_aAnchoredObjects)
+ {
+ uno::Reference<drawing::XShape> xShape(rAnchored, uno::UNO_QUERY);
+ if (!xShape.is())
+ continue;
+
+ uno::Reference<beans::XPropertySet> xPropertySet(rAnchored, uno::UNO_QUERY);
+ if (!xPropertySet.is())
+ continue;
+
+ // Ignore objects with no wrapping.
+ text::WrapTextMode eWrap = text::WrapTextMode_THROUGH;
+ xPropertySet->getPropertyValue("Surround") >>= eWrap;
+ if (eWrap == text::WrapTextMode_THROUGH)
+ continue;
+
+ sal_Int32 nLeftMargin = 0;
+ xPropertySet->getPropertyValue("LeftMargin") >>= nLeftMargin;
+ sal_Int32 nRightMargin = 0;
+ xPropertySet->getPropertyValue("RightMargin") >>= nRightMargin;
+ nShapesWidth += xShape->getSize().Width + nLeftMargin + nRightMargin;
+ }
+
+ // Ignore cases when we have enough horizontal space for the shapes.
+ if (nTextAreaWidth > nShapesWidth)
+ continue;
+
+ sal_Int32 nHeight = 0;
+ for (const auto& rAnchored : rAnchor.m_aAnchoredObjects)
+ {
+ uno::Reference<drawing::XShape> xShape(rAnchored, uno::UNO_QUERY);
+ if (!xShape.is())
+ continue;
+
+ nHeight += xShape->getSize().Height;
+ }
+
+ uno::Reference<beans::XPropertySet> xParagraph(rAnchor.m_xParagraph, uno::UNO_QUERY);
+ if (xParagraph.is())
+ {
+ sal_Int32 nTopMargin = 0;
+ xParagraph->getPropertyValue("ParaTopMargin") >>= nTopMargin;
+ // Increase top spacing of the paragraph to match Word layout
+ // behavior.
+ nTopMargin = std::max(nTopMargin, nHeight);
+ xParagraph->setPropertyValue("ParaTopMargin", uno::makeAny(nTopMargin));
+ }
+ }
+ rAnchoredObjectAnchors.clear();
+}
+
void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
{
// The default section type is nextPage.
@@ -1143,6 +1209,8 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl )
}
rPendingFloatingTables.clear();
+ HandleIncreasedAnchoredObjectSpacing(rDM_Impl);
+
if ( m_nLnnMod )
{
bool bFirst = rDM_Impl.IsLineNumberingSet();
diff --git a/writerfilter/source/dmapper/PropertyMap.hxx b/writerfilter/source/dmapper/PropertyMap.hxx
index d7f416f79607..2412c8e0126e 100644
--- a/writerfilter/source/dmapper/PropertyMap.hxx
+++ b/writerfilter/source/dmapper/PropertyMap.hxx
@@ -59,6 +59,7 @@ namespace dmapper {
class DomainMapper_Impl;
struct FloatingTableInfo;
+struct AnchoredObjectInfo;
enum BorderPosition
{
@@ -278,6 +279,9 @@ private:
// Determines if conversion of a given floating table is wanted or not.
bool FloatingTableConversion( DomainMapper_Impl& rDM_Impl, FloatingTableInfo& rInfo );
+ /// Increases paragraph spacing according to Word 2013+ needs if necessary.
+ void HandleIncreasedAnchoredObjectSpacing(DomainMapper_Impl& rDM_Impl);
+
public:
enum PageType
{
diff --git a/writerfilter/source/dmapper/SettingsTable.cxx b/writerfilter/source/dmapper/SettingsTable.cxx
index b747eb37abdb..d782b2c11603 100644
--- a/writerfilter/source/dmapper/SettingsTable.cxx
+++ b/writerfilter/source/dmapper/SettingsTable.cxx
@@ -617,6 +617,33 @@ void SettingsTable::ApplyProperties(uno::Reference<text::XTextDocument> const& x
}
}
+sal_Int32 SettingsTable::GetWordCompatibilityMode() const
+{
+ for (const auto& rProp : m_pImpl->m_aCompatSettings)
+ {
+ if (rProp.Name == "compatSetting")
+ {
+ css::uno::Sequence<css::beans::PropertyValue> aCurrentCompatSettings;
+ rProp.Value >>= aCurrentCompatSettings;
+
+ OUString sName;
+ OUString sUri;
+ OUString sVal;
+
+ aCurrentCompatSettings[0].Value >>= sName;
+ aCurrentCompatSettings[1].Value >>= sUri;
+ aCurrentCompatSettings[2].Value >>= sVal;
+
+ if (sName == "compatibilityMode" && sUri == "http://schemas.microsoft.com/office/word")
+ {
+ return sVal.toInt32();
+ }
+ }
+ }
+
+ return -1; // Word compatibility mode not found
+}
+
}//namespace dmapper
} //namespace writerfilter
diff --git a/writerfilter/source/dmapper/SettingsTable.hxx b/writerfilter/source/dmapper/SettingsTable.hxx
index 2a80bd186fc1..dafba061947b 100644
--- a/writerfilter/source/dmapper/SettingsTable.hxx
+++ b/writerfilter/source/dmapper/SettingsTable.hxx
@@ -83,6 +83,8 @@ class SettingsTable : public LoggedProperties, public LoggedTable
void ApplyProperties(css::uno::Reference<css::text::XTextDocument> const& xDoc);
+ sal_Int32 GetWordCompatibilityMode() const;
+
private:
// Properties
virtual void lcl_attribute(Id Name, Value & val) override;