From b360322c63d62b54b5e6adac4def3f8b761dc1da Mon Sep 17 00:00:00 2001 From: Justin Luth Date: Mon, 18 Sep 2017 14:57:47 -0400 Subject: tdf#97648 ooxmlimport: calculate percentage-based widths MSO seems to write 100% width horizontal lines with a "suggested" width of 0, so we need to calculate what the proper width is. A better fix would be to add "percentage-width" support to the shape class itself, but that complex enhancement is way beyond my abilities. Limiting the patch ONLY to shapes with an undefined width because it otherwise slightly increases the size of various other unit tests, and I'm not sure if those are desirable changes or not. The list of the unit tests is documented in the bug report. Change-Id: Ied80beca42a7513b8ea3b94b9c4ea9898e787200 Reviewed-on: https://gerrit.libreoffice.org/42128 Tested-by: Jenkins Reviewed-by: Miklos Vajna --- .../ooxmlexport/data/tdf97648_relativeWidth.docx | Bin 38145 -> 17613 bytes sw/qa/extras/ooxmlexport/ooxmlexport9.cxx | 10 +++---- sw/qa/extras/rtfimport/rtfimport.cxx | 6 ++-- writerfilter/source/dmapper/DomainMapper_Impl.cxx | 15 ++++++++-- writerfilter/source/dmapper/PropertyMap.cxx | 32 +++++++++++++++++++++ writerfilter/source/dmapper/PropertyMap.hxx | 4 +++ 6 files changed, 54 insertions(+), 13 deletions(-) diff --git a/sw/qa/extras/ooxmlexport/data/tdf97648_relativeWidth.docx b/sw/qa/extras/ooxmlexport/data/tdf97648_relativeWidth.docx index 8419113f1617..686fd6803ade 100644 Binary files a/sw/qa/extras/ooxmlexport/data/tdf97648_relativeWidth.docx and b/sw/qa/extras/ooxmlexport/data/tdf97648_relativeWidth.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx index dddc7b2b918c..66eda44719f8 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport9.cxx @@ -228,12 +228,10 @@ DECLARE_OOXMLEXPORT_TEST(tdf105490_negativeMargins, "tdf105490_negativeMargins.d DECLARE_OOXMLEXPORT_TEST(testTdf97648_relativeWidth,"tdf97648_relativeWidth.docx") { - int i = mbExported ? 0 : 1; - //divide everything by 10 to avoid rounding errors etc - CPPUNIT_ASSERT_EQUAL( sal_Int32(15995/10), getShape(++i)->getSize().Width/10); - CPPUNIT_ASSERT_EQUAL( sal_Int32(8001/10), getShape(++i)->getSize().Width/10); - CPPUNIT_ASSERT_EQUAL( sal_Int32(4001/10), getShape(++i)->getSize().Width/10); - CPPUNIT_ASSERT_EQUAL( sal_Int32(1600/10), getShape(++i)->getSize().Width/10); + CPPUNIT_ASSERT_DOUBLES_EQUAL( sal_Int32(7616), getShape(1)->getSize().Width, 10); + CPPUNIT_ASSERT_DOUBLES_EQUAL( sal_Int32(8001), getShape(2)->getSize().Width, 10); + CPPUNIT_ASSERT_DOUBLES_EQUAL( sal_Int32(4001), getShape(3)->getSize().Width, 10); + CPPUNIT_ASSERT_DOUBLES_EQUAL( sal_Int32(1600), getShape(4)->getSize().Width, 10); } DECLARE_OOXMLEXPORT_TEST(testTdf104061_tableSectionColumns,"tdf104061_tableSectionColumns.docx") diff --git a/sw/qa/extras/rtfimport/rtfimport.cxx b/sw/qa/extras/rtfimport/rtfimport.cxx index fabf17d152e9..b3bb4f4e0a5f 100644 --- a/sw/qa/extras/rtfimport/rtfimport.cxx +++ b/sw/qa/extras/rtfimport/rtfimport.cxx @@ -418,11 +418,9 @@ DECLARE_RTFIMPORT_TEST(testFdo79319, "fdo79319.rtf") // the thin horizontal rule was imported as a big fat rectangle uno::Reference xShape(getShape(1), uno::UNO_QUERY); CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty(xShape, "RelativeWidth")); - // FIXME the width/height numbers here are bogus; they should be 15238 / 53 - // (as they are when opening the file in a full soffice) + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(15238), xShape->getSize().Width, 10); + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(53), xShape->getSize().Height, 10); #if 0 - CPPUNIT_ASSERT_EQUAL(sal_Int32(15238), xShape->getSize().Width); - CPPUNIT_ASSERT_EQUAL(sal_Int32(53), xShape->getSize().Height); CPPUNIT_ASSERT_EQUAL(text::VertOrientation::CENTER, getProperty(xShape, "VertOrient")); CPPUNIT_ASSERT_EQUAL(text::HoriOrientation::CENTER, getProperty(xShape, "HoriOrient")); #endif diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx index e5eee0325289..745daba638b8 100644 --- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx +++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx @@ -2176,6 +2176,7 @@ void DomainMapper_Impl::PopShapeContext() // this is normal: the shape is already attached } + const uno::Reference xShape( xObj, uno::UNO_QUERY_THROW ); // Remove the shape if required (most likely replacement shape for OLE object) // or anchored to a discarded header or footer if ( m_aAnchoredStack.top().bToRemove || m_bDiscardHeaderFooter ) @@ -2185,15 +2186,23 @@ void DomainMapper_Impl::PopShapeContext() uno::Reference xDrawPageSupplier(m_xTextDocument, uno::UNO_QUERY_THROW); uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); if ( xDrawPage.is() ) - { - uno::Reference xShape( xObj, uno::UNO_QUERY_THROW ); xDrawPage->remove( xShape ); - } } catch( const uno::Exception& ) { } } + + // Relative width calculations deferred until section's margins are defined. + // Being cautious: only deferring undefined/minimum-width shapes in order to avoid causing potential regressions + if( xShape->getSize().Width <= 2 ) + { + const uno::Reference xShapePropertySet( xShape, uno::UNO_QUERY ); + SectionPropertyMap* pSectionContext = GetSectionContext(); + if ( pSectionContext && !getTableManager().isInTable() && xShapePropertySet->getPropertySetInfo()->hasPropertyByName(getPropertyName(PROP_RELATIVE_WIDTH)) ) + pSectionContext->addRelativeWidthShape(xShape); + } + m_aAnchoredStack.pop(); } m_bFrameBtLr = false; diff --git a/writerfilter/source/dmapper/PropertyMap.cxx b/writerfilter/source/dmapper/PropertyMap.cxx index c416ba52ba69..03508ec263c0 100644 --- a/writerfilter/source/dmapper/PropertyMap.cxx +++ b/writerfilter/source/dmapper/PropertyMap.cxx @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -1405,6 +1406,37 @@ void SectionPropertyMap::CloseSectionGroup( DomainMapper_Impl& rDM_Impl ) OSL_FAIL( "Exception in SectionPropertyMap::CloseSectionGroup" ); } } + + // Now that the margins are known, resize relative width shapes because some shapes in LO do not support percentage-sizes + sal_Int32 nParagraphWidth = GetPageWidth() - m_nLeftMargin - m_nRightMargin; + if ( m_nColumnCount > 0 ) + { + // skip custom-width columns since we don't know what column the shape is in. + if ( m_aColWidth.size() ) + nParagraphWidth = 0; + else + nParagraphWidth = (nParagraphWidth - (m_nColumnDistance * m_nColumnCount)) / (m_nColumnCount + 1); + } + if ( nParagraphWidth > 0 ) + { + const OUString sPropRelativeWidth = getPropertyName(PROP_RELATIVE_WIDTH); + for ( const auto& xShape : m_xRelativeWidthShapes ) + { + const uno::Reference xShapePropertySet( xShape, uno::UNO_QUERY ); + if ( xShapePropertySet->getPropertySetInfo()->hasPropertyByName(sPropRelativeWidth) ) + { + sal_uInt16 nPercent = 0; + xShapePropertySet->getPropertyValue( sPropRelativeWidth ) >>= nPercent; + if ( nPercent ) + { + const sal_Int32 nWidth = nParagraphWidth * nPercent / 100; + xShape->setSize( awt::Size( nWidth, xShape->getSize().Height ) ); + } + } + } + } + m_xRelativeWidthShapes.clear(); + rDM_Impl.SetIsLastSectionGroup( false ); rDM_Impl.SetIsFirstParagraphInSection( true ); diff --git a/writerfilter/source/dmapper/PropertyMap.hxx b/writerfilter/source/dmapper/PropertyMap.hxx index d7f416f79607..cc20cd56518d 100644 --- a/writerfilter/source/dmapper/PropertyMap.hxx +++ b/writerfilter/source/dmapper/PropertyMap.hxx @@ -236,6 +236,8 @@ private: sal_Int32 m_ndxaLnn; sal_Int32 m_nLnnMin; + std::vector> m_xRelativeWidthShapes; + // The "Link To Previous" flag indicates whether the header/footer // content should be taken from the previous section bool m_bDefaultHeaderLinkToPrevious; @@ -347,6 +349,8 @@ public: void SetdxaLnn( sal_Int32 nValue ) { m_ndxaLnn = nValue; } void SetLnnMin( sal_Int32 nValue ) { m_nLnnMin = nValue; } + void addRelativeWidthShape( css::uno::Reference xShape ) { m_xRelativeWidthShapes.push_back( xShape ); } + // determine which style gets the borders void ApplyBorderToPageStyles( const css::uno::Reference< css::container::XNameContainer >& xStyles, const css::uno::Reference< css::lang::XMultiServiceFactory >& xTextFactory, -- cgit v1.2.3