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) } };
