summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitaliy Anderson <vanderson@smartru.com>2017-04-04 17:11:12 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2017-04-17 13:11:53 +0200
commit9a31d1c83e08600507689dc18f6f0973bc7e4389 (patch)
treecb2920d25d6fbbd8dba3064de18ed24e4055744e
parent664980f34bb26f34a3365ded3d05e177d2c888d1 (diff)
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@libreoffice.org> Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
-rw-r--r--sw/qa/extras/ooxmlexport/data/table-cell-margin.docx (renamed from sw/qa/extras/ooxmlexport/data/table-position.docx)bin13708 -> 13708 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/data/table-position-14.docxbin0 -> 13708 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/data/table-position-15.docxbin0 -> 13683 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport2.cxx35
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport8.cxx76
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx62
-rw-r--r--writerfilter/source/dmapper/DomainMapperTableHandler.cxx39
7 files changed, 169 insertions, 43 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/table-position.docx b/sw/qa/extras/ooxmlexport/data/table-cell-margin.docx
index f59a5da11a95..f59a5da11a95 100644
--- a/sw/qa/extras/ooxmlexport/data/table-position.docx
+++ b/sw/qa/extras/ooxmlexport/data/table-cell-margin.docx
Binary files differ
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
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/table-position-14.docx
Binary files 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
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/table-position-15.docx
Binary files 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 );