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)