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)

Reply via email to