xmloff/qa/unit/text.cxx | 43 +++++++++++++++++++++++++++++++ xmloff/source/text/txtparae.cxx | 54 +++++++++++++++++++++++++++++----------- 2 files changed, 83 insertions(+), 14 deletions(-)
New commits: commit b578fa08a25a83abccad2386e12b707586fffb26 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Wed Mar 16 15:35:50 2022 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Mar 16 16:44:24 2022 +0100 ODT export: fix fallback svg:width/height for text frames with relative sizes In case <draw:frame> has style:rel-width="..." and style:rel-height="...", then the ODF spec says that: > To support consumers that do not support relative width, producers > should also provide the width in a svg:width 19.575 attribute. If the motivation is to support simple consumers, then it's better if we write the up to date layout size as the fallback value, not what was the layout size at insert time. (But don't ignore this at import time: 80% width and "scale" for height is a valid combination, and then height/width is needed to know the ratio.) Change-Id: Iefeb43cdb141b01a732086c37186201a3fef0952 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131662 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins diff --git a/xmloff/qa/unit/text.cxx b/xmloff/qa/unit/text.cxx index c24e6855f543..3b067120eb7b 100644 --- a/xmloff/qa/unit/text.cxx +++ b/xmloff/qa/unit/text.cxx @@ -340,6 +340,49 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testClearingBreakImport) CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int16>(3), eClear); } +CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testRelativeWidth) +{ + // Given a document with an 50% wide text frame: + getComponent() = loadFromDesktop("private:factory/swriter"); + uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(getComponent(), + uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xStyleFamilies + = xStyleFamiliesSupplier->getStyleFamilies(); + uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName("PageStyles"), + uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xStyle(xStyleFamily->getByName("Standard"), uno::UNO_QUERY); + // Body frame width is 6cm (2+2cm margin). + xStyle->setPropertyValue("Width", uno::makeAny(static_cast<sal_Int32>(10000))); + uno::Reference<lang::XMultiServiceFactory> xMSF(getComponent(), uno::UNO_QUERY); + uno::Reference<text::XTextDocument> xTextDocument(getComponent(), uno::UNO_QUERY); + uno::Reference<text::XTextContent> xTextFrame( + xMSF->createInstance("com.sun.star.text.TextFrame"), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xTextFrameProps(xTextFrame, uno::UNO_QUERY); + xTextFrameProps->setPropertyValue("RelativeWidth", uno::makeAny(static_cast<sal_Int16>(50))); + uno::Reference<text::XText> xText = xTextDocument->getText(); + uno::Reference<text::XTextCursor> xCursor = xText->createTextCursor(); + xText->insertTextContent(xCursor, xTextFrame, /*bAbsorb=*/false); + // Body frame width is 16cm. + xStyle->setPropertyValue("Width", uno::makeAny(static_cast<sal_Int32>(20000))); + + uno::Reference<frame::XStorable> xStorable(getComponent(), uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> aStoreProps = comphelper::InitPropertySequence({ + { "FilterName", uno::makeAny(OUString("writer8")) }, + }); + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + xStorable->storeToURL(aTempFile.GetURL(), aStoreProps); + + std::unique_ptr<SvStream> pStream = parseExportStream(aTempFile, "content.xml"); + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + // Without the accompanying fix in place, this failed with: + // - Expected: 3.1492in (8cm) + // - Actual : 0.0161in (0.04 cm) + // i.e. the fallback width value wasn't the expected half of the body frame width, but a smaller + // value. + assertXPath(pXmlDoc, "//draw:frame", "width", "3.1492in"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx index bfd7d2f2f6fa..b813885f0812 100644 --- a/xmloff/source/text/txtparae.cxx +++ b/xmloff/source/text/txtparae.cxx @@ -2662,6 +2662,32 @@ XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes( Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo()); + bool bSyncWidth = false; + if (xPropSetInfo->hasPropertyByName(gsIsSyncWidthToHeight)) + { + bSyncWidth = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsSyncWidthToHeight)); + } + sal_Int16 nRelWidth = 0; + if (!bSyncWidth && xPropSetInfo->hasPropertyByName(gsRelativeWidth)) + { + rPropSet->getPropertyValue(gsRelativeWidth) >>= nRelWidth; + } + bool bSyncHeight = false; + if (xPropSetInfo->hasPropertyByName(gsIsSyncHeightToWidth)) + { + bSyncHeight = *o3tl::doAccess<bool>(rPropSet->getPropertyValue(gsIsSyncHeightToWidth)); + } + sal_Int16 nRelHeight = 0; + if (!bSyncHeight && xPropSetInfo->hasPropertyByName(gsRelativeHeight)) + { + rPropSet->getPropertyValue(gsRelativeHeight) >>= nRelHeight; + } + awt::Size aLayoutSize; + if ((nRelWidth > 0 || nRelHeight > 0) && xPropSetInfo->hasPropertyByName("LayoutSize")) + { + rPropSet->getPropertyValue("LayoutSize") >>= aLayoutSize; + } + // svg:width sal_Int16 nWidthType = SizeType::FIX; if( xPropSetInfo->hasPropertyByName( gsWidthType ) ) @@ -2687,6 +2713,13 @@ XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes( } else { + if (nRelWidth > 0 || bSyncWidth) + { + // Relative width: write the layout size for the fallback width. + sValue.setLength(0); + GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue, aLayoutSize.Width); + } + GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH, sValue.makeStringAndClear() ); if(nullptr != pCenter) @@ -2696,18 +2729,14 @@ XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes( } } } - bool bSyncWidth = false; if( xPropSetInfo->hasPropertyByName( gsIsSyncWidthToHeight ) ) { - bSyncWidth = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsSyncWidthToHeight )); if( bSyncWidth ) GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH, XML_SCALE ); } if( !bSyncWidth && xPropSetInfo->hasPropertyByName( gsRelativeWidth ) ) { - sal_Int16 nRelWidth = 0; - rPropSet->getPropertyValue( gsRelativeWidth ) >>= nRelWidth; SAL_WARN_IF( nRelWidth < 0 || nRelWidth > 254, "xmloff", "Got illegal relative width from API" ); if( nRelWidth > 0 ) @@ -2724,16 +2753,6 @@ XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes( { rPropSet->getPropertyValue( gsSizeType ) >>= nSizeType; } - bool bSyncHeight = false; - if( xPropSetInfo->hasPropertyByName( gsIsSyncHeightToWidth ) ) - { - bSyncHeight = *o3tl::doAccess<bool>(rPropSet->getPropertyValue( gsIsSyncHeightToWidth )); - } - sal_Int16 nRelHeight = 0; - if( !bSyncHeight && xPropSetInfo->hasPropertyByName( gsRelativeHeight ) ) - { - rPropSet->getPropertyValue( gsRelativeHeight ) >>= nRelHeight; - } if( xPropSetInfo->hasPropertyByName( gsHeight ) ) { sal_Int32 nHeight = 0; @@ -2750,6 +2769,13 @@ XMLShapeExportFlags XMLTextParagraphExport::addTextFrameAttributes( } else { + if (nRelHeight > 0 || bSyncHeight) + { + // Relative height: write the layout size for the fallback height. + sValue.setLength(0); + GetExport().GetMM100UnitConverter().convertMeasureToXML(sValue, aLayoutSize.Height); + } + GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT, sValue.makeStringAndClear() ); if(nullptr != pCenter)