sw/qa/extras/ooxmlexport/data/tdf115719.docx             |binary
 sw/qa/extras/ooxmlexport/ooxmlexport9.cxx                |    7 +
 writerfilter/source/dmapper/DomainMapperTableHandler.cxx |   30 ------
 writerfilter/source/dmapper/DomainMapper_Impl.cxx        |   17 +++
 writerfilter/source/dmapper/DomainMapper_Impl.hxx        |   16 +++
 writerfilter/source/dmapper/PropertyMap.cxx              |   68 +++++++++++++++
 writerfilter/source/dmapper/PropertyMap.hxx              |    4 
 writerfilter/source/dmapper/SettingsTable.cxx            |   27 +++++
 writerfilter/source/dmapper/SettingsTable.hxx            |    2 
 9 files changed, 142 insertions(+), 29 deletions(-)

New commits:
commit 8ce3110540804112efb530878517ab51147b7c66
Author: Miklos Vajna <[email protected]>
Date:   Wed Feb 14 15:31:35 2018 +0100

    tdf#115719 DOCX import: increase paragraph spacing for anchored objects
    
    ... like Word 2013 does, when the version string indicates that the new
    layout is wanted.
    
    An alternative to this change would be to add a new sw layout
    compatibility flag and handle this at a layout level (somewhere in
    SwAnchoredObject::GetObjRectWithSpaces()). The downside of that approach
    is that once a layout flag is added, it's not preferred to tweak its
    behavior, while doing the same at import time is not a problem.
    
    Also it's better to have a flag for something which has clear behavior
    in some spec / implementer notes, which is not the case for this
    problem. (I've mailed dochelp@microsoft, no answer so far.)
    
    (cherry picked from commit 8b73bafbc18acb4dd8911d2f2de8158d98eb6144)
    
    Conflicts:
            sw/qa/extras/ooxmlexport/ooxmlexport11.cxx
    
    Change-Id: Ibad28d27e4bcbe1991a3be1c686064e18e9ffa4d
    Reviewed-on: https://gerrit.libreoffice.org/49803
    Tested-by: Jenkins <[email protected]>
    Reviewed-by: Andras Timar <[email protected]>

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
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf115719.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
index 74cb6c7143e8..f5553c5b7d1d 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx
@@ -703,6 +703,13 @@ DECLARE_OOXMLEXPORT_TEST(testGraphicObjectFliph, 
"graphic-object-fliph.docx")
     CPPUNIT_ASSERT(getProperty<bool>(getShape(1), "HoriMirroredOnOddPages"));
 }
 
+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());
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx 
b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index db2c4fa4d5c9..0015a90eb39a 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
@@ -576,7 +548,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 3ad6fb7e8fa7..0eef1be53d00 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -1258,6 +1258,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;
 
@@ -5014,8 +5025,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 65274fcc7d46..247a7875778f 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -206,6 +206,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)
     {
@@ -324,6 +330,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;
@@ -859,6 +872,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 41a023cffc45..96799cb2cbc7 100644
--- a/writerfilter/source/dmapper/PropertyMap.cxx
+++ b/writerfilter/source/dmapper/PropertyMap.cxx
@@ -1123,6 +1123,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.
@@ -1140,6 +1206,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 96883755159f..14ef8cd6fe81 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
 {
@@ -286,6 +287,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 6693accb2b9a..0da30f52ad6e 100644
--- a/writerfilter/source/dmapper/SettingsTable.cxx
+++ b/writerfilter/source/dmapper/SettingsTable.cxx
@@ -426,6 +426,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 28db5c26fb73..5c7de7ae618d 100644
--- a/writerfilter/source/dmapper/SettingsTable.hxx
+++ b/writerfilter/source/dmapper/SettingsTable.hxx
@@ -81,6 +81,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;
_______________________________________________
Libreoffice-commits mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to