From c625247680cd5737723154b9a73c45e786611b44 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Mon, 25 Aug 2025 09:30:16 +0200 Subject: [PATCH] tdf#167761 sw format redline, char style+direct: add ODT export The bugdoc contains a format redline that changes the character style from Strong to Quote and the font size from 24 to 36. Exporting to ODT, loading the ODT and rejecting the redline, the font size is set to 24, but the character style is set to default instead of Strong. What happens is that the item set of the format redline contains the necessary SvxFontHeightItem, but contains no SwFormatCharFormat. This is because the ODT export writes no parents for char automatic styles, because char formatting outside the redline table has 2 pool items for such char formatting: a dedicated SwFormatCharFormat for the char style and a separate SwFormatAutoFormat for other char props, so the ODT export "knows" to ignore the autoformat parent and creates this markup: t Fix the problem by explicitly exporting the parent style name when we write an automatic style that is referred from the redline table (and not from the body text). This is similar to what e.g. "frame" autostyles already do, which also have parents. The result is this markup: ... which contains both the named character style name and the automatic style, describing the direct formatting. The ODT import side still needs fixing. Change-Id: I19a67cf5e2c538cfcfa1b13097241954667d2c89 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190181 Reviewed-by: Miklos Vajna Tested-by: Jenkins --- include/xmloff/txtparae.hxx | 6 +- xmloff/CppunitTest_xmloff_text.mk | 1 + .../text/data/format-charstyle-direct.docx | Bin 0 -> 14390 bytes xmloff/qa/unit/text/txtparae.cxx | 53 ++++++++++++++++++ xmloff/source/text/XMLRedlineExport.cxx | 15 ++++- xmloff/source/text/txtparae.cxx | 19 ++++++- 6 files changed, 87 insertions(+), 7 deletions(-) create mode 100644 xmloff/qa/unit/text/data/format-charstyle-direct.docx create mode 100644 xmloff/qa/unit/text/txtparae.cxx diff --git a/include/xmloff/txtparae.hxx b/include/xmloff/txtparae.hxx index 6df40e45cd3b..74a07f3042c3 100644 --- a/include/xmloff/txtparae.hxx +++ b/include/xmloff/txtparae.hxx @@ -195,7 +195,8 @@ public: const css::uno::Reference< css::beans::XPropertySet > & rPropSet, bool& rbHasCharStyle, bool& rbHasAutoStyle, - const XMLPropertyState** pAddState = nullptr) const; + const XMLPropertyState** pAddState = nullptr, + const OUString* pParentName = nullptr) const; void exportTextRangeEnumeration( const css::uno::Reference< css::container::XEnumeration > & rRangeEnum, @@ -400,7 +401,8 @@ public: void Add( XmlStyleFamily nFamily, const css::uno::Reference< css::beans::XPropertySet > & rPropSet, - std::span aAddStates = {} ); + std::span aAddStates = {}, + bool bCheckParent = false ); /// find style name for specified family and parent OUString Find( diff --git a/xmloff/CppunitTest_xmloff_text.mk b/xmloff/CppunitTest_xmloff_text.mk index 73e5dbb8eaaa..47bfd0ab4696 100644 --- a/xmloff/CppunitTest_xmloff_text.mk +++ b/xmloff/CppunitTest_xmloff_text.mk @@ -19,6 +19,7 @@ $(eval $(call gb_CppunitTest_use_externals,xmloff_text,\ $(eval $(call gb_CppunitTest_add_exception_objects,xmloff_text, \ xmloff/qa/unit/text \ xmloff/qa/unit/text/txtprmap \ + xmloff/qa/unit/text/txtparae \ )) $(eval $(call gb_CppunitTest_use_libraries,xmloff_text, \ diff --git a/xmloff/qa/unit/text/data/format-charstyle-direct.docx b/xmloff/qa/unit/text/data/format-charstyle-direct.docx new file mode 100644 index 0000000000000000000000000000000000000000..5f973391a7d1803d6130ddccef0e63618f11f744 GIT binary patch literal 14390 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 l75;ZO`&YOJ<6q$acDnLX5O1~x0KmR|UfvutA + +using namespace com::sun::star; + +namespace +{ +/// Covers xmloff/source/text/txtparae.cxx fixes. +class Test : public UnoApiXmlTest +{ +public: + Test(); +}; + +Test::Test() + : UnoApiXmlTest(u"/xmloff/qa/unit/text/data/"_ustr) +{ +} + +CPPUNIT_TEST_FIXTURE(Test, testRedlineFormatCharStyleDirectExport) +{ + // Given a document that contains a format redline: both the character style and direct + // formatting changes: + loadFromFile(u"format-charstyle-direct.docx"); + + // When exporting the document to ODT: + save(u"writer8"_ustr); + + // Then make sure the named style is not lost in the redline: + xmlDocUniquePtr pXmlDoc = parseExport(u"content.xml"_ustr); + OString aAutoName + = getXPath(pXmlDoc, "//text:tracked-changes/text:changed-region/text:format-change", + "style-name") + .toUtf8(); + // Without the accompanying fix in place, this test would have failed with: + // - XPath '//office:automatic-styles/style:style[@style:name='T2']' no attribute 'parent-style-name' exist + // i.e. the named character style in the format redline was lost. + OUString aParentName = getXPath( + pXmlDoc, "//office:automatic-styles/style:style[@style:name='" + aAutoName + "']", + "parent-style-name"); + CPPUNIT_ASSERT_EQUAL(u"Strong_20_Emphasis"_ustr, aParentName); +} +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/xmloff/source/text/XMLRedlineExport.cxx b/xmloff/source/text/XMLRedlineExport.cxx index 9eab647b1662..f85d9671878b 100644 --- a/xmloff/source/text/XMLRedlineExport.cxx +++ b/xmloff/source/text/XMLRedlineExport.cxx @@ -269,7 +269,10 @@ void XMLRedlineExport::ExportChangeAutoStyle( aAny >>= xAutoFormat; if (xAutoFormat.is()) { - rExport.GetTextParagraphExport()->Add(XmlStyleFamily::TEXT_TEXT, xAutoFormat); + // Check for parent style when declaring the automatic style. + rExport.GetTextParagraphExport()->Add(XmlStyleFamily::TEXT_TEXT, xAutoFormat, + /*aAddStates=*/{}, + /*bCheckParent=*/true); } } @@ -373,7 +376,15 @@ void XMLRedlineExport::ExportChangedRegion( { bool bIsUICharStyle; bool bHasAutoStyle; - OUString sStyle = rExport.GetTextParagraphExport()->FindTextStyle(xAutoStyle, bIsUICharStyle, bHasAutoStyle); + OUString aParentName; + uno::Reference xPropSetInfo = xAutoStyle->getPropertySetInfo(); + if (xPropSetInfo->hasPropertyByName("CharStyleName")) + { + // Consider parent style when referring to the declared automatic style. + xAutoStyle->getPropertyValue("CharStyleName") >>= aParentName; + } + OUString sStyle = rExport.GetTextParagraphExport()->FindTextStyle( + xAutoStyle, bIsUICharStyle, bHasAutoStyle, /*pAddState=*/nullptr, &aParentName); if (!sStyle.isEmpty()) { rExport.AddAttribute(XML_NAMESPACE_LO_EXT, XML_STYLE_NAME, rExport.EncodeStyleName(sStyle)); diff --git a/xmloff/source/text/txtparae.cxx b/xmloff/source/text/txtparae.cxx index 3ac362785ad5..fd9e76be62f3 100644 --- a/xmloff/source/text/txtparae.cxx +++ b/xmloff/source/text/txtparae.cxx @@ -653,7 +653,8 @@ void FieldParamExporter::ExportParameter(const OUString& sKey, const OUString& s void XMLTextParagraphExport::Add( XmlStyleFamily nFamily, const Reference < XPropertySet > & rPropSet, - const std::span aAddStates ) + const std::span aAddStates, + bool bCheckParent ) { rtl::Reference < SvXMLExportPropertyMapper > xPropMapper; switch( nFamily ) @@ -737,6 +738,11 @@ void XMLTextParagraphExport::Add( XmlStyleFamily nFamily, break; case XmlStyleFamily::TEXT_TEXT: { + if (bCheckParent && xPropSetInfo->hasPropertyByName(gsCharStyleName)) + { + rPropSet->getPropertyValue(gsCharStyleName) >>= sParent; + } + // Get parent and remove hyperlinks (they aren't of interest) rtl::Reference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper()); sal_uInt16 nIgnoreProps = 0; @@ -912,7 +918,8 @@ OUString XMLTextParagraphExport::FindTextStyle( const Reference < XPropertySet > & rPropSet, bool& rbHasCharStyle, bool& rbHasAutoStyle, - const XMLPropertyState** ppAddStates ) const + const XMLPropertyState** ppAddStates, + const OUString* pParentName) const { rtl::Reference < SvXMLExportPropertyMapper > xPropMapper(GetTextPropMapper()); std::vector aPropStates(xPropMapper->Filter(GetExport(), rPropSet)); @@ -975,9 +982,15 @@ OUString XMLTextParagraphExport::FindTextStyle( aPropStates.erase( aSecondDel ); aPropStates.erase( aFirstDel ); } + OUString aParentName; + if (pParentName) + { + // Format redlines can have an autostyle with a parent. + aParentName = *pParentName; + } sName = GetAutoStylePool().Find( XmlStyleFamily::TEXT_TEXT, - OUString(), // AutoStyles should not have parents! + aParentName, aPropStates ); rbHasAutoStyle = true; }