[Libreoffice-commits] core.git: sw/qa sw/source writerfilter/source

Vitaliy Anderson vanderson at smartru.com
Mon Apr 17 11:12:19 UTC 2017


 sw/qa/extras/ooxmlexport/data/table-position-14.docx     |binary
 sw/qa/extras/ooxmlexport/data/table-position-15.docx     |binary
 sw/qa/extras/ooxmlexport/ooxmlexport2.cxx                |   35 ------
 sw/qa/extras/ooxmlexport/ooxmlexport8.cxx                |   76 +++++++++++++++
 sw/source/filter/ww8/docxattributeoutput.cxx             |   62 +++++++++++-
 writerfilter/source/dmapper/DomainMapperTableHandler.cxx |   39 +++++++
 6 files changed, 169 insertions(+), 43 deletions(-)

New commits:
commit 9a31d1c83e08600507689dc18f6f0973bc7e4389
Author: Vitaliy Anderson <vanderson at smartru.com>
Date:   Tue Apr 4 17:11:12 2017 +0300

    tdf#106742: OOXML import/export: treat "tblInd" properly.
    
    Since MS Word 2013+ if you change cell margin at the table, the border won't be shifted.
    
    The decision is to do the same ( see https://bugs.documentfoundation.org/show_bug.cgi?id=106742 ).
    
    Change-Id: Ia58693c44f63ed21dca2cd99591002ba68927b65
    Reviewed-on: https://gerrit.libreoffice.org/36084
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>

diff --git a/sw/qa/extras/ooxmlexport/data/table-position.docx b/sw/qa/extras/ooxmlexport/data/table-cell-margin.docx
similarity index 100%
rename from sw/qa/extras/ooxmlexport/data/table-position.docx
rename to sw/qa/extras/ooxmlexport/data/table-cell-margin.docx
diff --git a/sw/qa/extras/ooxmlexport/data/table-position-14.docx b/sw/qa/extras/ooxmlexport/data/table-position-14.docx
new file mode 100644
index 000000000000..f59a5da11a95
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/table-position-14.docx differ
diff --git a/sw/qa/extras/ooxmlexport/data/table-position-15.docx b/sw/qa/extras/ooxmlexport/data/table-position-15.docx
new file mode 100644
index 000000000000..d3dcaec40e78
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/table-position-15.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx
index a0bd7e490320..3b4445f8585e 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx
@@ -363,41 +363,6 @@ DECLARE_OOXMLEXPORT_TEST(testTable, "table.odt")
     assertXPath(parseExport("word/styles.xml"), "//w:style[@w:styleId='Normal']/w:qFormat", 1);
 }
 
-DECLARE_OOXMLEXPORT_TEST(testTablePosition, "table-position.docx")
-{
-    sal_Int32 aXCoordsFromOffice[] = { 2500, -1000, 0, 0 };
-    sal_Int32 cellLeftMarginFromOffice[] = { 250, 100, 0, 0 };
-
-    uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
-    uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
-    uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables( ), uno::UNO_QUERY);
-
-    for (int i=0; i<4; i++) {
-        uno::Reference<text::XTextTable> xTable1 (xTables->getByIndex(i), uno::UNO_QUERY);
-        // Verify X coord
-        uno::Reference<view::XSelectionSupplier> xCtrl(xModel->getCurrentController(), uno::UNO_QUERY);
-        xCtrl->select(uno::makeAny(xTable1));
-        uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xCtrl, uno::UNO_QUERY);
-        uno::Reference<text::XTextViewCursor> xCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY);
-        awt::Point pos = xCursor->getPosition();
-        CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Incorrect X coord computed from docx",
-            aXCoordsFromOffice[i], pos.X, 1);
-
-        // Verify left margin of 1st cell :
-        //  * Office left margins are measured relative to the right of the border
-        //  * LO left spacing is measured from the center of the border
-        uno::Reference<table::XCell> xCell = xTable1->getCellByName("A1");
-        uno::Reference< beans::XPropertySet > xPropSet(xCell, uno::UNO_QUERY_THROW);
-        sal_Int32 aLeftMargin = -1;
-        xPropSet->getPropertyValue("LeftBorderDistance") >>= aLeftMargin;
-        uno::Any aLeftBorder = xPropSet->getPropertyValue("LeftBorder");
-        table::BorderLine2 aLeftBorderLine;
-        aLeftBorder >>= aLeftBorderLine;
-        CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Incorrect left spacing computed from docx cell margin",
-            cellLeftMarginFromOffice[i], aLeftMargin - 0.5 * aLeftBorderLine.LineWidth, 1);
-    }
-}
-
 struct SingleLineBorders {
     sal_Int16 top, bottom, left, right;
     SingleLineBorders(int t=0, int b=0, int l=0, int r=0)
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
index 5b62695446fc..d751899dee8e 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport8.cxx
@@ -47,6 +47,7 @@
 #include <com/sun/star/style/ParagraphAdjust.hpp>
 #include <com/sun/star/table/ShadowFormat.hpp>
 #include <com/sun/star/view/XFormLayerAccess.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
 #include <com/sun/star/table/BorderLine2.hpp>
 #include <com/sun/star/table/TableBorder2.hpp>
 #include <com/sun/star/text/SizeType.hpp>
@@ -2096,6 +2097,81 @@ DECLARE_OOXMLEXPORT_TEST(testTdf99140, "tdf99140.docx")
     CPPUNIT_ASSERT_EQUAL(text::HoriOrientation::LEFT_AND_WIDTH, getProperty<sal_Int16>(xTableProperties, "HoriOrient"));
 }
 
+DECLARE_OOXMLEXPORT_TEST( testTableCellMargin, "table-cell-margin.docx" )
+{
+    sal_Int32 cellLeftMarginFromOffice[] = { 250, 100, 0, 0 };
+
+    uno::Reference< text::XTextTablesSupplier > xTablesSupplier( mxComponent, uno::UNO_QUERY );
+    uno::Reference< frame::XModel >             xModel( mxComponent, uno::UNO_QUERY );
+    uno::Reference< container::XIndexAccess >   xTables( xTablesSupplier->getTextTables(), uno::UNO_QUERY );
+
+    for ( int i = 0; i < 4; i++ )
+    {
+        uno::Reference< text::XTextTable > xTable1( xTables->getByIndex( i ), uno::UNO_QUERY );
+
+        // Verify left margin of 1st cell :
+        //  * Office left margins are measured relative to the right of the border
+        //  * LO left spacing is measured from the center of the border
+        uno::Reference< table::XCell > xCell = xTable1->getCellByName( "A1" );
+        uno::Reference< beans::XPropertySet > xPropSet( xCell, uno::UNO_QUERY_THROW );
+        sal_Int32 aLeftMargin = -1;
+        xPropSet->getPropertyValue( "LeftBorderDistance" ) >>= aLeftMargin;
+        uno::Any aLeftBorder = xPropSet->getPropertyValue( "LeftBorder" );
+        table::BorderLine2 aLeftBorderLine;
+        aLeftBorder >>= aLeftBorderLine;
+        CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Incorrect left spacing computed from docx cell margin",
+            cellLeftMarginFromOffice[i], aLeftMargin - 0.5 * aLeftBorderLine.LineWidth, 1 );
+    }
+}
+
+// tdf#106742 for DOCX with compatibility level <= 14 (MS Word up to and incl. ver.2010), we should use cell margins when calculating table left border position
+DECLARE_OOXMLEXPORT_TEST( testTablePosition14, "table-position-14.docx" )
+{
+    sal_Int32 aXCoordsFromOffice[] = { 2500, -1000, 0, 0 };
+
+    uno::Reference< text::XTextTablesSupplier > xTablesSupplier( mxComponent, uno::UNO_QUERY );
+    uno::Reference< frame::XModel >             xModel( mxComponent, uno::UNO_QUERY );
+    uno::Reference< container::XIndexAccess >   xTables( xTablesSupplier->getTextTables(), uno::UNO_QUERY );
+
+    for ( int i = 0; i < 4; i++ )
+    {
+        uno::Reference< text::XTextTable > xTable1( xTables->getByIndex( i ), uno::UNO_QUERY );
+
+        // Verify X coord
+        uno::Reference< view::XSelectionSupplier > xCtrl( xModel->getCurrentController(), uno::UNO_QUERY );
+        xCtrl->select( uno::makeAny( xTable1 ) );
+        uno::Reference< text::XTextViewCursorSupplier > xTextViewCursorSupplier( xCtrl, uno::UNO_QUERY );
+        uno::Reference< text::XTextViewCursor > xCursor( xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY );
+        awt::Point pos = xCursor->getPosition();
+        CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Incorrect X coord computed from docx",
+            aXCoordsFromOffice[i], pos.X, 1 );
+    }
+}
+
+// tdf#106742 for DOCX with compatibility level > 14 (MS Word since ver.2013), we should NOT use cell margins when calculating table left border position
+DECLARE_OOXMLEXPORT_TEST( testTablePosition15, "table-position-15.docx" )
+{
+    sal_Int32 aXCoordsFromOffice[] = { 2751, -899, 1, 106 };
+
+    uno::Reference< text::XTextTablesSupplier > xTablesSupplier( mxComponent, uno::UNO_QUERY );
+    uno::Reference< frame::XModel >             xModel( mxComponent, uno::UNO_QUERY );
+    uno::Reference< container::XIndexAccess >   xTables( xTablesSupplier->getTextTables(), uno::UNO_QUERY );
+
+    for ( int i = 0; i < 4; i++ )
+    {
+        uno::Reference< text::XTextTable > xTable1( xTables->getByIndex( i ), uno::UNO_QUERY );
+
+        // Verify X coord
+        uno::Reference< view::XSelectionSupplier > xCtrl( xModel->getCurrentController(), uno::UNO_QUERY );
+        xCtrl->select( uno::makeAny( xTable1 ) );
+        uno::Reference< text::XTextViewCursorSupplier > xTextViewCursorSupplier( xCtrl, uno::UNO_QUERY );
+        uno::Reference< text::XTextViewCursor > xCursor( xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY );
+        awt::Point pos = xCursor->getPosition();
+        CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Incorrect X coord computed from docx",
+            aXCoordsFromOffice[i], pos.X, 1 );
+    }
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index fe8ec152a934..a1be3420d4fe 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -3206,6 +3206,51 @@ OString lcl_padStartToLength(OString const & aString, sal_Int32 nLen, sal_Char c
         return aString;
 }
 
+sal_Int32 lcl_getWordCompatibilityMode( const SwDoc& rDoc )
+{
+    uno::Reference< beans::XPropertySet >     xPropSet( rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW );
+    uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo();
+
+    if ( xPropSetInfo->hasPropertyByName( UNO_NAME_MISC_OBJ_INTEROPGRABBAG ) )
+    {
+        uno::Sequence< beans::PropertyValue > propList;
+        xPropSet->getPropertyValue( UNO_NAME_MISC_OBJ_INTEROPGRABBAG ) >>= propList;
+
+        for ( sal_Int32 i = 0; i < propList.getLength(); ++i )
+        {
+            if ( propList[i].Name == "CompatSettings" )
+            {
+                css::uno::Sequence< css::beans::PropertyValue > aCurrentCompatSettings;
+                propList[i].Value >>= aCurrentCompatSettings;
+
+                for ( sal_Int32 j = 0; j < aCurrentCompatSettings.getLength(); ++j )
+                {
+                    uno::Sequence< beans::PropertyValue > aCompatSetting;
+                    aCurrentCompatSettings[j].Value >>= aCompatSetting;
+
+                    OUString sName;
+                    OUString sUri;
+                    OUString sVal;
+
+                    for ( sal_Int32 k = 0; k < aCompatSetting.getLength(); ++k )
+                    {
+                        if ( aCompatSetting[k].Name == "name" ) aCompatSetting[k].Value >>= sName;
+                        if ( aCompatSetting[k].Name == "uri" )  aCompatSetting[k].Value >>= sUri;
+                        if ( aCompatSetting[k].Name == "val" )  aCompatSetting[k].Value >>= sVal;
+                    }
+
+                    if ( sName == "compatibilityMode" && sUri == "http://schemas.microsoft.com/office/word" )
+                    {
+                        return sVal.toInt32();
+                    }
+                }
+            }
+        }
+    }
+
+    return -1; // Word compatibility mode not found
+}
+
 }
 
 void DocxAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
@@ -3428,17 +3473,24 @@ void DocxAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t
                 pJcVal = "left";
             else
                 pJcVal = "start";
-            nIndent = sal_Int32( pTableFormat->GetLRSpace( ).GetLeft( ) );
+            nIndent = sal_Int32( pTableFormat->GetLRSpace().GetLeft() );
+
             // Table indentation has different meaning in Word, depending if the table is nested or not.
             // If nested, tblInd is added to parent table's left spacing and defines left edge position
             // If not nested, text position of left-most cell must be at absolute X = tblInd
             // so, table_spacing + table_spacing_to_content = tblInd
-            if (m_tableReference->m_nTableDepth == 0)
+
+            // 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_rExport.m_pDoc );
+
+            if ( nMode > 0 && nMode <= 14 && m_tableReference->m_nTableDepth == 0 )
             {
-                const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
-                const SwFrameFormat * pFrameFormat = pTabBox->GetFrameFormat();
-                nIndent += sal_Int32( pFrameFormat->GetBox( ).GetDistance( SvxBoxItemLine::LEFT ) );
+                const SwTableBox*    pTabBox = pTableTextNodeInfoInner->getTableBox();
+                const SwFrameFormat* pFrameFormat = pTabBox->GetFrameFormat();
+                nIndent += sal_Int32( pFrameFormat->GetBox().GetDistance( SvxBoxItemLine::LEFT ) );
             }
+
             break;
         }
     }
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
index c4d26e514429..8fa604a3710c 100644
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
@@ -313,6 +313,34 @@ 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
@@ -546,13 +574,18 @@ TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo
         // - top level tables: the goal is to have in-cell text starting at table indent pos (tblInd),
         //   so table's position depends on table's cells margin
         // - nested tables: the goal is to have left-most border starting at table_indent pos
-        if (rInfo.nNestLevel > 1)
+
+        // 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() );
+
+        if ( nMode > 0 && nMode <= 14 && rInfo.nNestLevel == 1 )
         {
-            m_aTableProperties->Insert( PROP_LEFT_MARGIN, uno::makeAny( nLeftMargin - nGapHalf ));
+            m_aTableProperties->Insert( PROP_LEFT_MARGIN, uno::makeAny( nLeftMargin - nGapHalf - rInfo.nLeftBorderDistance ) );
         }
         else
         {
-            m_aTableProperties->Insert( PROP_LEFT_MARGIN, uno::makeAny( nLeftMargin - nGapHalf - rInfo.nLeftBorderDistance ));
+            m_aTableProperties->Insert( PROP_LEFT_MARGIN, uno::makeAny( nLeftMargin - nGapHalf ) );
         }
 
         m_aTableProperties->getValue( TablePropertyMap::TABLE_WIDTH, nTableWidth );


More information about the Libreoffice-commits mailing list