cui/source/tabpages/macroass.cxx      |   11 +++++-
 sw/Module_sw.mk                       |    1 
 sw/UITest_sw_uibase_shells.mk         |   16 ++++++++++
 sw/qa/uitest/data/image-rel-size.fodt |   40 +++++++++++++++++++++++++
 sw/qa/uitest/uibase/shells/shells.py  |   38 +++++++++++++++++++++++
 sw/source/uibase/shells/grfsh.cxx     |   10 ++++++
 xmloff/qa/unit/text.cxx               |   46 ++++++++++++++++++++++++++++
 xmloff/source/text/txtparae.cxx       |   54 +++++++++++++++++++++++++---------
 8 files changed, 199 insertions(+), 17 deletions(-)

New commits:
commit 9b0f881a15f3128fefcf0f0f0d048f845592f610
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Mar 17 17:36:18 2022 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Mar 18 11:27:35 2022 +0100

    sw image dialog: fix fallback width/height for images with relative sizes
    
    Make sure that we work with the up to date layout size of the image in
    the dialog, otherwise 80% shows up as 237%.
    
    Also fix SfxMacroTabPage::FillItemSet() to not put anything to the
    output item set when the macro table is empty, this way clicking OK in
    the image dialog results in an unmodified document when the user doesn't
    change anything.
    
    (cherry picked from commit 9e8712ed6f9fb5dbd971e352a5709bd45fadc74f)
    
    Conflicts:
            sw/Module_sw.mk
            sw/qa/uitest/writer_tests/data/image-rel-size.fodt
    
    Change-Id: I4b987bd3e3818ee737e37ea10861f9043c25bc93

diff --git a/cui/source/tabpages/macroass.cxx b/cui/source/tabpages/macroass.cxx
index df3e47bf489b..accec8992e12 100644
--- a/cui/source/tabpages/macroass.cxx
+++ b/cui/source/tabpages/macroass.cxx
@@ -156,9 +156,14 @@ bool SfxMacroTabPage::FillItemSet( SfxItemSet* rSet )
     SvxMacroItem aItem( GetWhich( aPageRg[0] ) );
     const_cast<SvxMacroTableDtor&>(aItem.GetMacroTable()) = aTbl;
 
-    const SfxPoolItem* pItem;
-    if( SfxItemState::SET != GetItemSet().GetItemState( aItem.Which(), true, 
&pItem )
-        || aItem != *static_cast<const SvxMacroItem*>(pItem) )
+    const SfxPoolItem* pItem = nullptr;
+    SfxItemState eState = GetItemSet().GetItemState(aItem.Which(), true, 
&pItem);
+    if (eState == SfxItemState::DEFAULT && aTbl.empty())
+    {
+        // Don't touch the item set if there was no input and our table is 
empty.
+        return false;
+    }
+    if (SfxItemState::SET != eState || aItem != *static_cast<const 
SvxMacroItem*>(pItem))
     {
         rSet->Put( aItem );
         return true;
diff --git a/sw/Module_sw.mk b/sw/Module_sw.mk
index 50e7d11cd9d9..047b69db1b41 100644
--- a/sw/Module_sw.mk
+++ b/sw/Module_sw.mk
@@ -171,6 +171,7 @@ $(eval $(call gb_Module_add_uicheck_targets,sw,\
        UITest_librelogo \
        UITest_options \
        UITest_sw_ui_fmtui \
+       UITest_sw_uibase_shells \
        UITest_classification \
        UITest_writer_macro_tests \
        UITest_writer_dialogs \
diff --git a/sw/UITest_sw_uibase_shells.mk b/sw/UITest_sw_uibase_shells.mk
new file mode 100644
index 000000000000..de9cb7c8a9d9
--- /dev/null
+++ b/sw/UITest_sw_uibase_shells.mk
@@ -0,0 +1,16 @@
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call  gb_UITest_UITest,sw_uibase_shells))
+
+$(eval $(call gb_UITest_add_modules,sw_uibase_shells,$(SRCDIR)/sw/qa/uitest,\
+       uibase/shells/ \
+))
+
+$(eval $(call gb_UITest_set_defs,sw_uibase_shells, \
+    TDOC="$(SRCDIR)/sw/qa/uitest/data" \
+))
diff --git a/sw/qa/uitest/data/image-rel-size.fodt 
b/sw/qa/uitest/data/image-rel-size.fodt
new file mode 100644
index 000000000000..9df285861616
--- /dev/null
+++ b/sw/qa/uitest/data/image-rel-size.fodt
@@ -0,0 +1,40 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<office:document 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+  <office:automatic-styles>
+    <style:style style:name="fr1" style:family="graphic" 
style:parent-style-name="Graphics">
+      <style:graphic-properties style:vertical-pos="top" 
style:vertical-rel="baseline"/>
+    </style:style>
+    <style:page-layout style:name="pm1">
+      <style:page-layout-properties fo:page-width="21.001cm" 
fo:page-height="29.7cm" fo:margin-top="2cm" fo:margin-bottom="2cm" 
fo:margin-left="2cm" fo:margin-right="2cm">
+      </style:page-layout-properties>
+      <style:header-style/>
+      <style:footer-style/>
+    </style:page-layout>
+    <style:style style:name="dp1" style:family="drawing-page">
+      <style:drawing-page-properties draw:background-size="full"/>
+    </style:style>
+  </office:automatic-styles>
+  <office:master-styles>
+    <style:master-page style:name="Standard" style:page-layout-name="pm1" 
draw:style-name="dp1"/>
+  </office:master-styles>
+  <office:body>
+    <office:text>
+      <text:p text:style-name="Standard"><draw:frame draw:style-name="fr1" 
draw:name="Bild1" text:anchor-type="as-char" svg:width="40.282cm" 
style:rel-width="80%" svg:height="15.88cm" style:rel-height="scale" 
draw:z-index="0"><draw:image 
draw:mime-type="image/png"><office:binary-data>iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAQAAAAAYLlVAAAABGdBTUEAALGPC/xhBQAAAAFz
+       UkdCAK7OHOkAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAA
+       AAJiS0dEAACqjSMyAAAACW9GRnMAAAAGAAAAAAAMc1XTAAAACXBIWXMAAA3XAAAN1wFCKJt4
+       AAAACXZwQWcAAABMAAAAQACdMTgbAAABzUlEQVRo3u3ZPU/CQBjA8X+Jxs3ESUDj4iK+LA5+
+       BBfjqBE1cXB2MlFAEqMgxvhNNL4sLsK3UPQL6ObkoAETz+FKW2mxCPRYnucWUu76/OC59C49
+       cGOCKqrD9kHRc6ddPv7oW2WCwMh0nF63Myz7Tm8hPTNu0pgHMER3scepTbgK6enJNND83RLn
+       /878yRaPmgBZFDuMsNLeWB9gmFQHP77MIg9gsYciR50NFKvtjIy10yk84pSZA7DYpwR8scmF
+       QQCMuoQMpzbh0iAARrlnVn90CWHTsZcAiHPPdINQAuqsc2MQAAnKDUKWEhZ10twaBEDSJWQo
+       YlFj7S9CzwEegkXWIbQsRAQASFJhpplwbRAACS+hANRJBxMiAkDcJeQ4sQkBhYgMoJ+Ozlwo
+       2YQ7AJ6CRxyiUGnVy3hVKb0Af9v7hUG2Wy9TEQCUelFTDULB2S+YKYGOMcpM6UIccOQnRA6A
+       cSp6ibfI+wkGADBGpTEd8xz1AaAfTQ7huA8AvUw5hVjuA0D/C5OaMN8XACRZ8F0zCggKAQhA
+       AAIQgAAEIAABCEAAAhCAAAQgAAH4zg3feY4w3Xs44M5+oW0qvCWoGcvaIlM3x/f/ab+O738A
+       hOCNQr34oD4AAAAldEVYdGNyZWF0ZS1kYXRlADIwMTAtMTItMjBUMTc6MDg6MzYrMDE6MDB6
+       5RscAAAAJXRFWHRtb2RpZnktZGF0ZQAyMDEwLTEyLTIwVDE3OjA4OjM3KzAxOjAwgyNmnAAA
+       AABJRU5ErkJggg==
+      </office:binary-data></draw:image></draw:frame></text:p>
+    </office:text>
+  </office:body>
+</office:document>
diff --git a/sw/qa/uitest/uibase/shells/shells.py 
b/sw/qa/uitest/uibase/shells/shells.py
new file mode 100644
index 000000000000..e96eaa10c887
--- /dev/null
+++ b/sw/qa/uitest/uibase/shells/shells.py
@@ -0,0 +1,38 @@
+# -*- tab-width: 4; indent-tabs-mode: nil; py-indent-offset: 4 -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+from uitest.framework import UITestCase
+from uitest.uihelper.common import get_state_as_dict
+from uitest.path import get_srcdir_url
+import time
+
+
+def get_url_for_data_file(file_name):
+    return get_srcdir_url() + "/sw/qa/uitest/data/" + file_name
+
+class TestSwGrfShell(UITestCase):
+    def testFormatGraphicDlg(self):
+        # Given a document with an image with a relative size:
+        component = 
self.ui_test.load_file(get_url_for_data_file("image-rel-size.fodt"))
+        self.xUITest.executeCommand(".uno:JumpToNextFrame")
+        # 120 ms in the SwView ctor
+        time.sleep(0.2)
+        # When opening the properties dialog for the image:
+        self.ui_test.execute_dialog_through_command(".uno:GraphicDialog")
+        dialog = self.xUITest.getTopFocusWindow()
+        # Then make sure the width is 80% as in the file:
+        widthField = dialog.getChild('width')
+        # Without the accompanying fix in place, this test would have failed 
with:
+        # AssertionError: '237%' != '80%'
+        # i.e. the percent width of the image was wrong.
+        self.assertEqual(get_state_as_dict(widthField)["Text"], "80%")
+        ok = dialog.getChild("ok")
+        ok.executeAction("CLICK", tuple())
+
+# vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/uibase/shells/grfsh.cxx 
b/sw/source/uibase/shells/grfsh.cxx
index f48e3d79eb1c..9d04319a50b7 100644
--- a/sw/source/uibase/shells/grfsh.cxx
+++ b/sw/source/uibase/shells/grfsh.cxx
@@ -60,6 +60,7 @@
 #include <swslots.hxx>
 #include <swabstdlg.hxx>
 #include <unocrsr.hxx>
+#include <flyfrm.hxx>
 #include <memory>
 
 #define TOOLBOX_NAME "colorbar"
@@ -317,6 +318,15 @@ void SwGrfShell::Execute(SfxRequest &rReq)
             aSet.Put( aFrameSize );
 
             aSet.Put( aMgr.GetAttrSet() );
+            SwFlyFrame* pFly = rSh.GetSelectedFlyFrame();
+            if (pFly)
+            {
+                // Work with the up to date layout size if possible.
+                SwFormatFrameSize aSize = aSet.Get(RES_FRM_SIZE);
+                aSize.SetWidth(pFly->getFrameArea().Width());
+                aSize.SetHeight(pFly->getFrameArea().Height());
+                aSet.Put(aSize);
+            }
             aSet.SetParent( aMgr.GetAttrSet().GetParent() );
 
             // At percentage values initialize size
commit 9c630789e65c33d7d1c5a68b7ca6e74d1ef594f2
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed Mar 16 15:35:50 2022 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Mar 18 11:12: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.)
    
    (cherry picked from commit b578fa08a25a83abccad2386e12b707586fffb26)
    
    Conflicts:
            xmloff/qa/unit/text.cxx
    
    Change-Id: Iefeb43cdb141b01a732086c37186201a3fef0952

diff --git a/xmloff/qa/unit/text.cxx b/xmloff/qa/unit/text.cxx
index 9bd802e813d5..f19419ba0a48 100644
--- a/xmloff/qa/unit/text.cxx
+++ b/xmloff/qa/unit/text.cxx
@@ -14,6 +14,9 @@
 #include <com/sun/star/frame/Desktop.hpp>
 #include <com/sun/star/frame/XStorable.hpp>
 #include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/text/XTextDocument.hpp>
 
 #include <comphelper/propertysequence.hxx>
 #include <unotools/tempfile.hxx>
@@ -90,6 +93,49 @@ CPPUNIT_TEST_FIXTURE(XmloffStyleTest, testListId)
     assertXPathNoAttribute(pXmlDoc, "//text:list", "id");
 }
 
+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 278942252e2a..8945c38ad7f9 100644
--- a/xmloff/source/text/txtparae.cxx
+++ b/xmloff/source/text/txtparae.cxx
@@ -2649,6 +2649,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 ) )
@@ -2674,6 +2700,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)
@@ -2683,18 +2716,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 )
@@ -2711,16 +2740,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;
@@ -2737,6 +2756,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