summaryrefslogtreecommitdiff
path: root/sw
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2023-05-10 20:39:12 +0300
committerMike Kaganski <mike.kaganski@collabora.com>2023-05-11 18:06:02 +0200
commit1a88efa8e02a6d765dab13c7110443bb9e6acecf (patch)
treefcefc280189d41ff6b6277017232085bfe334743 /sw
parentabd630e81bc150d05e4129cc22752ecf461777c7 (diff)
tdf#155238: Reimplement how ListAutoFormat is stored to ODF
This reimplements commits 6249858a8972aef077e0249bd93cfe8f01bce4d6 (sw: ODT import/export of DOCX's paragraph marker formatting, 2022-12-19) and 209dce614c43f63f63f5b42a746665c0ec1cbfe3 (sw: fix ODT import of paragraph marker formatting, 2022-12-20). Instead of using an empty trailing span for the ListAutoFormat data, introduce a new loext:marker-style-name attribute for text:p element, referencing a text autostyle. The problems with the previous implementation were that (1) it was impossible (or very difficult) to disambiguate several empty trailing spans, in case it was needed; and (2) this was incompatible change, with other ODF implementations treating the trailing span normally. I couldn't manage to incorporate the attribute to paragraph autostyle, because of problems referencing different autostyles one from another, so put it directly to the paragraph attributes. Change-Id: I33473147f1f774c24cbbc57bf0c4f3a1d83ce5bc Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151645 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
Diffstat (limited to 'sw')
-rw-r--r--sw/qa/extras/odfexport/data/ParagraphMarkerMarkup.fodt22
-rw-r--r--sw/qa/extras/odfexport/odfexport2.cxx10
-rw-r--r--sw/qa/extras/odfimport/data/emptyParagraphLoosesFontHeight.fodt21
-rw-r--r--sw/qa/extras/odfimport/odfimport.cxx21
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport2.cxx3
-rw-r--r--sw/source/core/unocore/unoobj.cxx71
-rw-r--r--sw/source/core/unocore/unoparagraph.cxx15
-rw-r--r--sw/source/core/unocore/unoportenum.cxx5
8 files changed, 101 insertions, 67 deletions
diff --git a/sw/qa/extras/odfexport/data/ParagraphMarkerMarkup.fodt b/sw/qa/extras/odfexport/data/ParagraphMarkerMarkup.fodt
new file mode 100644
index 000000000000..c3a21261da26
--- /dev/null
+++ b/sw/qa/extras/odfexport/data/ParagraphMarkerMarkup.fodt
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:styles>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text">
+ <style:text-properties fo:font-size="11pt"/>
+ </style:style>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="T1" style:family="text">
+ <style:text-properties fo:font-size="8pt"/>
+ </style:style>
+ <style:style style:name="T2" style:family="text">
+ <style:text-properties fo:font-size="9pt" fo:color="#ff0000"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:body>
+ <office:text>
+ <text:p text:style-name="Standard" loext:marker-style-name="T2"><text:span text:style-name="T1">text</text:span></text:p>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/odfexport/odfexport2.cxx b/sw/qa/extras/odfexport/odfexport2.cxx
index 269525a8756b..7c3d7fb9b841 100644
--- a/sw/qa/extras/odfexport/odfexport2.cxx
+++ b/sw/qa/extras/odfexport/odfexport2.cxx
@@ -1061,6 +1061,16 @@ DECLARE_ODFEXPORT_TEST(testTdf78510, "WordTest_edit.odt")
#endif
}
+CPPUNIT_TEST_FIXTURE(Test, testParagraphMarkerMarkupRoundtrip)
+{
+ loadAndReload("ParagraphMarkerMarkup.fodt");
+ // Test that the markup stays at save-and-reload
+ xmlDocUniquePtr pXmlDoc = parseExport("content.xml");
+ assertXPath(pXmlDoc, "/office:document-content/office:body/office:text/text:p", "marker-style-name", "T2");
+ assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:name='T2']/style:text-properties", "font-size", "9pt");
+ assertXPath(pXmlDoc, "/office:document-content/office:automatic-styles/style:style[@style:name='T2']/style:text-properties", "color", "#ff0000");
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/odfimport/data/emptyParagraphLoosesFontHeight.fodt b/sw/qa/extras/odfimport/data/emptyParagraphLoosesFontHeight.fodt
new file mode 100644
index 000000000000..7843d7e00f5f
--- /dev/null
+++ b/sw/qa/extras/odfimport/data/emptyParagraphLoosesFontHeight.fodt
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:styles>
+ <style:style style:name="Standard" style:family="paragraph" style:class="text">
+ <style:text-properties fo:font-size="11pt"/>
+ </style:style>
+ </office:styles>
+ <office:automatic-styles>
+ <style:style style:name="T1" style:family="text">
+ <style:text-properties fo:font-size="8pt"/>
+ </style:style>
+ </office:automatic-styles>
+ <office:body>
+ <office:text>
+ <text:p text:style-name="Standard"><text:span text:style-name="T1">value1</text:span><text:span text:style-name="T1"/></text:p>
+ <text:p text:style-name="Standard"><text:span text:style-name="T1"></text:span><text:span text:style-name="T1"/></text:p>
+ <text:p text:style-name="Standard"><text:span text:style-name="T1">value2</text:span><text:span text:style-name="T1"/></text:p>
+ </office:text>
+ </office:body>
+</office:document> \ No newline at end of file
diff --git a/sw/qa/extras/odfimport/odfimport.cxx b/sw/qa/extras/odfimport/odfimport.cxx
index 7225be2d4b8e..29df94d9afd6 100644
--- a/sw/qa/extras/odfimport/odfimport.cxx
+++ b/sw/qa/extras/odfimport/odfimport.cxx
@@ -1513,5 +1513,26 @@ CPPUNIT_TEST_FIXTURE(Test, testWindowsFileZone)
#endif
}
+CPPUNIT_TEST_FIXTURE(Test, testEmptyTrailingSpans)
+{
+ createSwDoc("emptyParagraphLoosesFontHeight.fodt");
+
+ CPPUNIT_ASSERT_EQUAL(3, getParagraphs());
+
+ auto xPara2 = getParagraph(2);
+ CPPUNIT_ASSERT_EQUAL(float(11), getProperty<float>(xPara2, "CharHeight"));
+ auto xRun = getRun(xPara2, 1);
+ CPPUNIT_ASSERT_EQUAL(float(8), getProperty<float>(xRun, "CharHeight"));
+ // Both empty spans merge -> no more runs
+ CPPUNIT_ASSERT_THROW(getRun(xPara2, 2), css::container::NoSuchElementException);
+
+ xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+
+ auto height1 = getXPath(pXmlDoc, "/root/page/body/txt[1]/infos/bounds", "height").toInt32();
+ auto height2 = getXPath(pXmlDoc, "/root/page/body/txt[2]/infos/bounds", "height").toInt32();
+ CPPUNIT_ASSERT_EQUAL(height1, height2);
+ CPPUNIT_ASSERT_DOUBLES_EQUAL(184, height2, 1); // allow a bit of room for rounding just in case
+}
+
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx
index 8a816ae9f9dd..9248670760ac 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport2.cxx
@@ -861,8 +861,7 @@ DECLARE_OOXMLEXPORT_TEST(testFdo64238_b, "fdo64238_b.docx")
xRunEnum->nextElement();
numOfRuns++;
}
- // "This is the ", "ODD", " [", "LEFT", "] header" and the colored paragraph marker
- CPPUNIT_ASSERT_EQUAL(sal_Int32(6), numOfRuns);
+ CPPUNIT_ASSERT_EQUAL(sal_Int32(5), numOfRuns);
}
DECLARE_OOXMLEXPORT_TEST(testFdo56679, "fdo56679.docx")
diff --git a/sw/source/core/unocore/unoobj.cxx b/sw/source/core/unocore/unoobj.cxx
index 7ef11b9462ab..2e65cf97bfcd 100644
--- a/sw/source/core/unocore/unoobj.cxx
+++ b/sw/source/core/unocore/unoobj.cxx
@@ -230,57 +230,6 @@ lcl_setAutoStyle(IStyleAccess & rStyleAccess, const uno::Any & rValue,
rSet.Put(aFormat);
};
-/// Tries to map rValue to RES_PARATR_LIST_AUTOFMT on the current paragraph, returns true on
-/// success.
-static bool lcl_setListAutoStyle(SwPaM& rPam, const uno::Any& rValue, SfxItemSet& rItemSet)
-{
- // See if this is an empty range at the end of a paragraph.
- if (rPam.Start()->GetNodeIndex() != rPam.End()->GetNodeIndex())
- {
- return false;
- }
-
- if (rPam.Start()->GetContentIndex() != rPam.End()->GetContentIndex())
- {
- return false;
- }
-
- SwTextNode* pTextNode = rPam.GetPointNode().GetTextNode();
- if (!pTextNode)
- {
- return false;
- }
-
- if (rPam.Start()->GetContentIndex() != pTextNode->Len())
- {
- return false;
- }
-
- // Look up the style content based on the name.
- OUString sStyle;
- if (!(rValue >>= sStyle))
- {
- return false;
- }
-
- IStyleAccess& rStyleAccess = rPam.GetDoc().GetIStyleAccess();
- std::shared_ptr<SfxItemSet> pStyle
- = rStyleAccess.getByName(sStyle, IStyleAccess::AUTO_STYLE_CHAR);
- if (!pStyle)
- {
- return false;
- }
-
- // Set the style on the text node.
- SwFormatAutoFormat aItem(RES_PARATR_LIST_AUTOFMT);
- aItem.SetStyleHandle(pStyle);
- pTextNode->SetAttr(aItem);
- // Clear the style from the hints array. Without clearing, it would contain some style which
- // happened to be there previously.
- rItemSet.ClearItem(RES_TXTATR_AUTOFMT);
- return true;
-}
-
void
SwUnoCursorHelper::SetTextFormatColl(const uno::Any & rAny, SwPaM & rPaM)
{
@@ -499,11 +448,6 @@ SwUnoCursorHelper::SetCursorPropertyValue(
lcl_setCharStyle(rPam.GetDoc(), rValue, rItemSet);
break;
case RES_TXTATR_AUTOFMT:
- if (lcl_setListAutoStyle(rPam, rValue, rItemSet))
- {
- break;
- }
-
lcl_setAutoStyle(rPam.GetDoc().GetIStyleAccess(),
rValue, rItemSet, false);
break;
@@ -567,8 +511,8 @@ SwUnoCursorHelper::SetCursorPropertyValue(
}
else if (FN_UNO_PARA_NUM_AUTO_FORMAT == rEntry.nWID)
{
- uno::Sequence<beans::NamedValue> props;
- if (rValue >>= props)
+ std::shared_ptr<SfxItemSet> pAutoStyle;
+ if (uno::Sequence<beans::NamedValue> props; rValue >>= props)
{
// TODO create own map for this, it contains UNO_NAME_DISPLAY_NAME? or make property readable so ODF export can map it to a automatic style?
SfxItemPropertySet const& rPropSet(*aSwMapProvider.GetPropertySet(PROPERTY_MAP_CHAR_AUTO_STYLE));
@@ -603,8 +547,15 @@ SwUnoCursorHelper::SetCursorPropertyValue(
IStyleAccess& rStyleAccess = rPam.GetDoc().GetIStyleAccess();
// Add it to the autostyle pool, needed by the ODT export.
- const std::shared_ptr<SfxItemSet> pAutoStyle
- = rStyleAccess.getAutomaticStyle(items, IStyleAccess::AUTO_STYLE_CHAR);
+ pAutoStyle = rStyleAccess.getAutomaticStyle(items, IStyleAccess::AUTO_STYLE_CHAR);
+ }
+ else if (OUString styleName; rValue >>= styleName)
+ {
+ IStyleAccess& rStyleAccess = rPam.GetDoc().GetIStyleAccess();
+ pAutoStyle = rStyleAccess.getByName(styleName, IStyleAccess::AUTO_STYLE_CHAR);
+ }
+ if (pAutoStyle)
+ {
SwFormatAutoFormat item(RES_PARATR_LIST_AUTOFMT);
// note: paragraph auto styles have ParaStyleName property for the parent style; character auto styles currently do not because there's a separate hint, but for this it would be a good way to add it in order to export it as style:parent-style-name, see XMLTextParagraphExport::Add()
item.SetStyleHandle(pAutoStyle);
diff --git a/sw/source/core/unocore/unoparagraph.cxx b/sw/source/core/unocore/unoparagraph.cxx
index 55c71ca730a4..1d0fae809f41 100644
--- a/sw/source/core/unocore/unoparagraph.cxx
+++ b/sw/source/core/unocore/unoparagraph.cxx
@@ -26,6 +26,7 @@
#include <comphelper/diagnose_ex.hxx>
#include <cmdid.h>
+#include <fmtautofmt.hxx>
#include <unomid.h>
#include <unoparaframeenum.hxx>
#include <unotext.hxx>
@@ -527,6 +528,20 @@ uno::Sequence< uno::Any > SwXParagraph::Impl::GetPropertyValues_Impl(
const SwAttrSet& rAttrSet( rTextNode.GetSwAttrSet() );
for (sal_Int32 nProp = 0; nProp < rPropertyNames.getLength(); nProp++)
{
+ if (pPropertyNames[nProp] == "ParaMarkerAutoStyleSpan")
+ {
+ // A hack to tunnel the fake text span to ODF export
+ // see XMLTextParagraphExport::exportParagraph
+ if (rTextNode.GetAttr(RES_PARATR_LIST_AUTOFMT).GetStyleHandle())
+ {
+ SwUnoCursor aEndCursor(*aPam.GetMark());
+ css::uno::Reference<css::beans::XPropertySet> xFakeSpan(
+ new SwXTextPortion(&aEndCursor, {}, PORTION_LIST_AUTOFMT));
+ pValues[nProp] <<= xFakeSpan;
+ }
+ continue;
+ }
+
SfxItemPropertyMapEntry const*const pEntry =
rMap.getByName( pPropertyNames[nProp] );
if (!pEntry)
diff --git a/sw/source/core/unocore/unoportenum.cxx b/sw/source/core/unocore/unoportenum.cxx
index db567f3cbf05..fd6cc626336b 100644
--- a/sw/source/core/unocore/unoportenum.cxx
+++ b/sw/source/core/unocore/unoportenum.cxx
@@ -1504,11 +1504,6 @@ static void lcl_CreatePortions(
// text portion because there may be a hyperlink attribute
xRef = new SwXTextPortion(pUnoCursor, i_xParentText, PORTION_TEXT);
}
- else if (bAtEnd && !xRef.is() && pTextNode->GetSwAttrSet().HasItem(RES_PARATR_LIST_AUTOFMT))
- {
- // We have explicit paragraph marker formatting, export it.
- xRef = new SwXTextPortion(pUnoCursor, i_xParentText, PORTION_LIST_AUTOFMT);
- }
else if (bAtEnd && !xRef.is() && pHints)
{
// See if there is an empty autofmt at the paragraph end. If so, export it, since that