sw/qa/extras/htmlexport/xhtmlexport.cxx                           |    8 
 sw/qa/extras/odfexport/data/tdf37128-start-end-to-left-right.fodt |  150 
++++++++++
 sw/qa/extras/odfexport/odfexport4.cxx                             |   26 +
 xmloff/source/style/adjushdl.cxx                                  |    4 
 4 files changed, 182 insertions(+), 6 deletions(-)

New commits:
commit a01051d04ab57f9f3ab0a388e52c8e5237f469f3
Author:     Jonathan Clark <[email protected]>
AuthorDate: Wed Oct 22 06:00:16 2025 -0600
Commit:     Jonathan Clark <[email protected]>
CommitDate: Fri Oct 24 11:49:56 2025 +0200

    tdf#37128 xmloff: remove incorrect emit of start/end for ParagraphAdjust
    
    Currently, we do not correctly implement fo:text-align "start" or "end".
    Support for these attribute values is faked at the parser level by
    always treating "start" to mean "left", and "end" to mean "right".
    
    In addition to this, previously, the ODF serializer always printed
    "start" for left alignment, and "end" for right alignment. This behavior
    is harmless for documents that only contain LTR paragraphs, but mirrors
    the alignment of all RTL paragraphs per the ODF standard. Other programs
    cannot view these documents as intended.
    
    This change updates the ODF serializer to instead print "left" for left
    alignment, and "right" for right alignment, reflecting our actual
    document layout.
    
    Change-Id: I3a1134924f4adf71b7a0ea3f672e8c1580770841
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192858
    Tested-by: Jenkins
    Reviewed-by: Jonathan Clark <[email protected]>

diff --git a/sw/qa/extras/htmlexport/xhtmlexport.cxx 
b/sw/qa/extras/htmlexport/xhtmlexport.cxx
index afde3e63d57b..8faca4785d41 100644
--- a/sw/qa/extras/htmlexport/xhtmlexport.cxx
+++ b/sw/qa/extras/htmlexport/xhtmlexport.cxx
@@ -46,10 +46,10 @@ CPPUNIT_TEST_FIXTURE(XHtmlExportTest, testTdf131812)
     CPPUNIT_ASSERT(pStream);
     sal_uInt64 nLength = pStream->TellEnd();
     OString aStream(read_uInt8s_ToOString(*pStream, nLength));
-    CPPUNIT_ASSERT(
-        aStream.indexOf(".paragraph-P1{ font-size:12pt; 
font-family:\'Liberation Serif\'; "
-                        "writing-mode:horizontal-tb; direction:rtl; 
text-align:right ! important;}")
-        != -1);
+    CPPUNIT_ASSERT(aStream.indexOf(
+                       ".paragraph-P1{ font-size:12pt; 
font-family:\'Liberation Serif\'; "
+                       "writing-mode:horizontal-tb; direction:rtl; 
text-align:right ! important; }")
+                   != -1);
 }
 
 CPPUNIT_TEST_FIXTURE(XHtmlExportTest, testTdf146264)
diff --git a/sw/qa/extras/odfexport/data/tdf37128-start-end-to-left-right.fodt 
b/sw/qa/extras/odfexport/data/tdf37128-start-end-to-left-right.fodt
new file mode 100644
index 000000000000..ee9649e7e564
--- /dev/null
+++ b/sw/qa/extras/odfexport/data/tdf37128-start-end-to-left-right.fodt
@@ -0,0 +1,150 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/"; 
xmlns:grddl="http://www.w3.org/2003/g/data-view#"; 
xmlns:xhtml="http://www.w3.org/1999/xhtml"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xforms="http://www.w3.org/2002/xforms"; 
xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:drawooo="http://openoffice.org/2010/draw"; 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:dc="http://purl.org/dc/elements/1.1/"; xmlns:c
 alcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext: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:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
xmlns:tableooo="http://openoffice.org/2009/table"; 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" 
xmlns:rpt="http://openoffice.org/2005/report"; 
xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"
 xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
xmlns:officeooo="http://openoffice.org/2009/office"; 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:
 meta:1.0" 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 office:version="1.4" office:mimetype="application/vnd.oasis.opendocument.text">
+ 
<office:meta><meta:creation-date>2025-10-22T05:31:47.251184918</meta:creation-date><meta:generator>LibreOffice/25.2.6.2$Linux_X86_64
 
LibreOffice_project/520$Build-2</meta:generator><dc:date>2025-10-22T05:36:27.933616336</dc:date><meta:editing-duration>PT4M39S</meta:editing-duration><meta:editing-cycles>3</meta:editing-cycles><meta:document-statistic
 meta:table-count="0" meta:image-count="0" meta:object-count="0" 
meta:page-count="1" meta:paragraph-count="8" meta:word-count="48" 
meta:character-count="282" 
meta:non-whitespace-character-count="242"/></office:meta>
+ <office:font-face-decls>
+  <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation 
Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
+  <style:font-face style:name="Noto Sans Devanagari1" svg:font-family="'Noto 
Sans Devanagari'" style:font-family-generic="system" 
style:font-pitch="variable"/>
+  <style:font-face style:name="Noto Serif CJK JP" svg:font-family="'Noto Serif 
CJK JP'" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+  <style:default-style style:family="graphic">
+   <style:graphic-properties svg:stroke-color="#3465a4" 
draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" 
draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" 
draw:start-line-spacing-vertical="0.283cm" 
draw:end-line-spacing-horizontal="0.283cm" 
draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/>
+   <style:paragraph-properties style:text-autospace="ideograph-alpha" 
style:line-break="strict" loext:tab-stop-distance="0cm" 
style:writing-mode="lr-tb" style:font-independent-line-spacing="false">
+    <style:tab-stops/>
+   </style:paragraph-properties>
+   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" 
fo:language="en" fo:country="CA" style:letter-kerning="true" 
style:font-name-asian="Noto Serif CJK JP" style:font-size-asian="10.5pt" 
style:language-asian="ja" style:country-asian="JP" 
style:font-name-complex="Noto Sans Devanagari1" style:font-size-complex="12pt" 
style:language-complex="hi" style:country-complex="IN"/>
+  </style:default-style>
+  <style:default-style style:family="paragraph">
+   <style:paragraph-properties fo:orphans="2" fo:widows="2" 
fo:hyphenation-ladder-count="no-limit" fo:hyphenation-keep="auto" 
loext:hyphenation-keep-type="column" style:text-autospace="ideograph-alpha" 
style:punctuation-wrap="hanging" style:line-break="strict" 
style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" 
fo:language="en" fo:country="CA" style:letter-kerning="true" 
style:font-name-asian="Noto Serif CJK JP" style:font-size-asian="10.5pt" 
style:language-asian="ja" style:country-asian="JP" 
style:font-name-complex="Noto Sans Devanagari1" style:font-size-complex="12pt" 
style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" 
fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" 
loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" 
loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/>
+  </style:default-style>
+  <style:default-style style:family="table">
+   <style:table-properties table:border-model="collapsing"/>
+  </style:default-style>
+  <style:default-style style:family="table-row">
+   <style:table-row-properties fo:keep-together="auto"/>
+  </style:default-style>
+  <style:style style:name="Standard" style:family="paragraph" 
style:class="text"/>
+  <style:style style:name="LTRLeft" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:paragraph-properties fo:text-align="left"/>
+  </style:style>
+  <style:style style:name="LTRStart" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:paragraph-properties fo:text-align="start"/>
+  </style:style>
+  <style:style style:name="LTRRight" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:paragraph-properties fo:text-align="right"/>
+  </style:style>
+  <style:style style:name="LTREnd" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:paragraph-properties fo:text-align="end"/>
+  </style:style>
+  <style:style style:name="RTLLeft" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:paragraph-properties fo:text-align="left" 
style:writing-mode="rl-tb"/>
+  </style:style>
+  <style:style style:name="RTLStart" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:paragraph-properties fo:text-align="start" 
style:writing-mode="rl-tb"/>
+  </style:style>
+  <style:style style:name="RTLRight" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:paragraph-properties fo:text-align="right" 
style:writing-mode="rl-tb"/>
+  </style:style>
+  <style:style style:name="RTLEnd" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:paragraph-properties fo:text-align="end" style:writing-mode="rl-tb"/>
+  </style:style>
+  <text:outline-style style:name="Outline">
+   <text:outline-level-style text:level="1" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="2" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="3" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="4" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="5" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="6" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="7" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="8" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="9" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="10" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+  </text:outline-style>
+  <text:notes-configuration text:note-class="footnote" style:num-format="1" 
text:start-value="0" text:footnotes-position="page" 
text:start-numbering-at="document"/>
+  <text:notes-configuration text:note-class="endnote" style:num-format="i" 
text:start-value="0"/>
+  <text:linenumbering-configuration text:number-lines="false" 
text:offset="0.499cm" style:num-format="1" text:number-position="left" 
text:increment="5"/>
+  </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="P1" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:text-properties/>
+  </style:style>
+  <style:page-layout style:name="pm1">
+   <style:page-layout-properties fo:page-width="21.59cm" 
fo:page-height="27.94cm" style:num-format="1" 
style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" 
fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" 
style:footnote-max-height="0cm" loext:margin-gutter="0cm">
+    <style:footnote-sep style:width="0.018cm" 
style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" 
style:line-style="solid" style:adjustment="left" style:rel-width="25%" 
style:color="#000000"/>
+   </style:page-layout-properties>
+   <style:header-style/>
+   <style:footer-style/>
+  </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+  <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+  <office:text>
+   <text:sequence-decls>
+    <text:sequence-decl text:display-outline-level="0" 
text:name="Illustration"/>
+    <text:sequence-decl text:display-outline-level="0" text:name="Table"/>
+    <text:sequence-decl text:display-outline-level="0" text:name="Text"/>
+    <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
+    <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
+   </text:sequence-decls>
+   <text:p text:style-name="LTRLeft">This paragraph is LTR aligned 
left.</text:p>
+   <text:p text:style-name="P1"/>
+   <text:p text:style-name="LTRStart">This paragraph is LTR aligned 
start.</text:p>
+   <text:p text:style-name="P1"/>
+   <text:p text:style-name="LTRRight">This paragraph is LTR aligned 
right.</text:p>
+   <text:p text:style-name="P1"/>
+   <text:p text:style-name="LTREnd">This paragraph is LTR aligned end.</text:p>
+   <text:p text:style-name="P1"/>
+   <text:p text:style-name="RTLLeft">This paragraph is RTL aligned 
left.</text:p>
+   <text:p text:style-name="P1"/>
+   <text:p text:style-name="RTLStart">This paragraph is RTL aligned 
start.</text:p>
+   <text:p text:style-name="P1"/>
+   <text:p text:style-name="RTLRight">This paragraph is RTL aligned 
right.</text:p>
+   <text:p text:style-name="P1"/>
+   <text:p text:style-name="RTLEnd">This paragraph is RTL aligned end.</text:p>
+   <text:p text:style-name="RTLEnd"/>
+  </office:text>
+ </office:body>
+</office:document>
diff --git a/sw/qa/extras/odfexport/odfexport4.cxx 
b/sw/qa/extras/odfexport/odfexport4.cxx
index b7b5e8364871..d75937da016c 100644
--- a/sw/qa/extras/odfexport/odfexport4.cxx
+++ b/sw/qa/extras/odfexport/odfexport4.cxx
@@ -1643,6 +1643,32 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf168980)
     saveAndReload(u"OpenDocument Text Flat XML"_ustr);
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf37128ConvertStartEndOnResave)
+{
+    // LO doesn't support start/end fo:text-align. These are always loaded as
+    // left/right, respectively. They should be resaved as left/right, too.
+    loadAndReload("tdf37128-start-end-to-left-right.fodt");
+    CPPUNIT_ASSERT_EQUAL(1, getPages());
+    xmlDocUniquePtr pXmlDoc = parseExport(u"styles.xml"_ustr);
+
+    assertXPath(pXmlDoc, 
"//style:style[@style:name='LTRLeft']/style:paragraph-properties",
+                "text-align", u"left");
+    assertXPath(pXmlDoc, 
"//style:style[@style:name='LTRStart']/style:paragraph-properties",
+                "text-align", u"left");
+    assertXPath(pXmlDoc, 
"//style:style[@style:name='LTRRight']/style:paragraph-properties",
+                "text-align", u"right");
+    assertXPath(pXmlDoc, 
"//style:style[@style:name='LTREnd']/style:paragraph-properties",
+                "text-align", u"right");
+    assertXPath(pXmlDoc, 
"//style:style[@style:name='RTLLeft']/style:paragraph-properties",
+                "text-align", u"left");
+    assertXPath(pXmlDoc, 
"//style:style[@style:name='RTLStart']/style:paragraph-properties",
+                "text-align", u"left");
+    assertXPath(pXmlDoc, 
"//style:style[@style:name='RTLRight']/style:paragraph-properties",
+                "text-align", u"right");
+    assertXPath(pXmlDoc, 
"//style:style[@style:name='RTLEnd']/style:paragraph-properties",
+                "text-align", u"right");
+}
+
 } // end of anonymous namespace
 CPPUNIT_PLUGIN_IMPLEMENT();
 
diff --git a/xmloff/source/style/adjushdl.cxx b/xmloff/source/style/adjushdl.cxx
index 41a93d57f6f0..61878c720504 100644
--- a/xmloff/source/style/adjushdl.cxx
+++ b/xmloff/source/style/adjushdl.cxx
@@ -31,13 +31,13 @@ using namespace ::xmloff::token;
 
 SvXMLEnumMapEntry<style::ParagraphAdjust> const pXML_Para_Adjust_Enum[] =
 {
+    { XML_LEFT,         style::ParagraphAdjust_LEFT },
+    { XML_RIGHT,        style::ParagraphAdjust_RIGHT },
     { XML_START,        style::ParagraphAdjust_LEFT },
     { XML_END,          style::ParagraphAdjust_RIGHT },
     { XML_CENTER,       style::ParagraphAdjust_CENTER },
     { XML_JUSTIFY,      style::ParagraphAdjust_BLOCK },
     { XML_JUSTIFIED,    style::ParagraphAdjust_BLOCK }, // obsolete
-    { XML_LEFT,         style::ParagraphAdjust_LEFT },
-    { XML_RIGHT,        style::ParagraphAdjust_RIGHT },
     { XML_TOKEN_INVALID, style::ParagraphAdjust(0) }
 };
 

Reply via email to