sw/source/core/text/itrform2.cxx                         |    1 
 sw/source/core/text/txthyph.cxx                          |    7 
 vcl/qa/cppunit/pdfexport/data/tdf162194-soft-hyphen.fodt |  125 +++++++++++++++
 vcl/qa/cppunit/pdfexport/pdfexport2.cxx                  |   41 ++++
 4 files changed, 174 insertions(+)

New commits:
commit 142ce290a2a29f9794ba9a689f35d6f7e3ff588c
Author:     Jonathan Clark <jonat...@libreoffice.org>
AuthorDate: Tue Jul 30 04:43:28 2024 -0600
Commit:     Jonathan Clark <jonat...@libreoffice.org>
CommitDate: Tue Jul 30 17:49:15 2024 +0200

    tdf#162194 sw: Fix for auto-hyphens inside ligatures
    
    Fixes an issue causing Writer to print ligature glyphs in front of
    automatic hyphens, instead of breaking ligatures at the hyphen insertion
    point.
    
    Regression from commit ab0a4543cab77ae0c7c0a79feb8aebab71163dd7
    (tdf#124116 Correct Writer text shaping across formatting changes)
    
    Change-Id: I7d6fbfdc892cce0c50552629f520deedc5304c65
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171245
    Tested-by: Jenkins
    Reviewed-by: Jonathan Clark <jonat...@libreoffice.org>

diff --git a/sw/source/core/text/itrform2.cxx b/sw/source/core/text/itrform2.cxx
index 0085603f7e1f..862a164a6dbc 100644
--- a/sw/source/core/text/itrform2.cxx
+++ b/sw/source/core/text/itrform2.cxx
@@ -1466,6 +1466,7 @@ SwTextPortion *SwTextFormatter::NewTextPortion( 
SwTextFormatInfo &rInf )
                 case CH_TXT_ATR_FIELDSTART:
                 case CH_TXT_ATR_FIELDSEP:
                 case CH_TXT_ATR_FIELDEND:
+                case CHAR_SOFTHYPHEN:
                     bAtEnd = true;
                     break;
 
diff --git a/sw/source/core/text/txthyph.cxx b/sw/source/core/text/txthyph.cxx
index 8f419984323a..7992114f6221 100644
--- a/sw/source/core/text/txthyph.cxx
+++ b/sw/source/core/text/txthyph.cxx
@@ -324,8 +324,15 @@ bool SwTextPortion::CreateHyphen( SwTextFormatInfo &rInf, 
SwTextGuess const &rGu
          ( nPorEnd == rInf.GetIdx() && rInf.GetLineStart() != rInf.GetIdx() ) )
     {
         aInf.SetLen( nPorEnd - rInf.GetIdx() );
+        if (auto stClampedContext = aInf.GetLayoutContext(); 
stClampedContext.has_value())
+        {
+            stClampedContext->m_nEnd = nPorEnd.get();
+            aInf.SetLayoutContext(stClampedContext);
+        }
+
         pHyphPor->SetAscent( GetAscent() );
         SetLen( aInf.GetLen() );
+        SetLayoutContext(aInf.GetLayoutContext());
         CalcTextSize( aInf );
 
         Insert( pHyphPor.release() );
diff --git a/vcl/qa/cppunit/pdfexport/data/tdf162194-soft-hyphen.fodt 
b/vcl/qa/cppunit/pdfexport/data/tdf162194-soft-hyphen.fodt
new file mode 100644
index 000000000000..b81b19a3d8d5
--- /dev/null
+++ b/vcl/qa/cppunit/pdfexport/data/tdf162194-soft-hyphen.fodt
@@ -0,0 +1,125 @@
+<?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.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ 
<office:meta><meta:creation-date>2024-07-29T07:07:06.825804078</meta:creation-date><meta:editing-cycles>0</meta:editing-cycles><meta:editing-duration>P0D</meta:editing-duration><meta:generator>LibreOffice/24.2.5.2$Linux_X86_64
 
LibreOffice_project/d6e8b0f3fc6e8af2b00cf4969fd0d2fa45b9a62e</meta:generator><meta:document-statistic
 meta:table-count="0" meta:image-count="0" meta:object-count="0" 
meta:page-count="1" meta:paragraph-count="2" meta:word-count="3" 
meta:character-count="17" 
meta:non-whitespace-character-count="16"/></office:meta>
+ <office:font-face-decls>
+  <style:font-face style:name="DejaVu Sans" svg:font-family="'DejaVu Sans'" 
style:font-family-generic="swiss" style:font-pitch="variable"/>
+  <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 Sans1" svg:font-family="'Noto Sans'" 
style:font-family-generic="system" style:font-pitch="variable"/>
+  <style:font-face style:name="Noto Serif CJK SC" svg:font-family="'Noto Serif 
CJK SC'" 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.1181in" draw:shadow-offset-y="0.1181in" 
draw:start-line-spacing-horizontal="0.1114in" 
draw:start-line-spacing-vertical="0.1114in" 
draw:end-line-spacing-horizontal="0.1114in" 
draw:end-line-spacing-vertical="0.1114in" style:writing-mode="lr-tb" 
style:flow-with-text="false"/>
+   <style:paragraph-properties style:text-autospace="ideograph-alpha" 
style:line-break="strict" loext:tab-stop-distance="0in" 
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="US" style:letter-kerning="true" 
style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" 
style:language-asian="zh" style:country-asian="CN" 
style:font-name-complex="Noto Sans1" 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" style:text-autospace="ideograph-alpha" 
style:punctuation-wrap="hanging" style:line-break="strict" 
style:tab-stop-distance="0.4925in" 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="US" style:letter-kerning="true" 
style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" 
style:language-asian="zh" style:country-asian="CN" 
style:font-name-complex="Noto Sans1" 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"/>
+  <text:outline-style style:name="Outline">
+   <text:outline-level-style text:level="1" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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" loext:num-list-format="%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.1965in" 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:font-name="DejaVu Sans" fo:font-size="96pt" 
style:font-size-asian="96pt" style:font-size-complex="96pt"/>
+  </style:style>
+  <style:style style:name="P2" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:text-properties style:font-name="DejaVu Sans" fo:font-size="96pt" 
style:font-size-asian="96pt" style:font-size-complex="96pt"/>
+  </style:style>
+  <style:style style:name="T1" style:family="text">
+   <style:text-properties/>
+  </style:style>
+  <style:style style:name="T2" style:family="text">
+   <style:text-properties/>
+  </style:style>
+  <style:page-layout style:name="pm1">
+   <style:page-layout-properties fo:page-width="8.2681in" 
fo:page-height="11.6929in" style:num-format="1" 
style:print-orientation="portrait" fo:margin-top="0.7874in" 
fo:margin-bottom="0.7874in" fo:margin-left="0.7874in" 
fo:margin-right="0.7874in" style:writing-mode="lr-tb" 
style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" 
style:layout-grid-base-height="0.278in" style:layout-grid-ruby-height="0.139in" 
style:layout-grid-mode="none" style:layout-grid-ruby-below="false" 
style:layout-grid-print="false" style:layout-grid-display="false" 
style:footnote-max-height="0in" loext:margin-gutter="0in">
+    <style:footnote-sep style:width="0.0071in" 
style:distance-before-sep="0.0398in" style:distance-after-sep="0.0398in" 
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>
+  <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: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="P2">Waffle</text:p>
+   <text:p text:style-name="P1"><text:span 
text:style-name="T1">AA</text:span><text:span 
text:style-name="T2">A</text:span><text:span text:style-name="T1"> 
</text:span>Waf­fle</text:p>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport2.cxx 
b/vcl/qa/cppunit/pdfexport/pdfexport2.cxx
index f34f5914efaa..1b00d1cc52c0 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport2.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport2.cxx
@@ -5391,6 +5391,47 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf162205Rtl)
     fnWithinRange(aRect.at(7), aRect.at(5));
 }
 
+// tdf#162194 - Verifies soft hyphens inside ligatures are rendered correctly.
+CPPUNIT_TEST_FIXTURE(PdfExportTest2, testTdf162194SoftHyphen)
+{
+    aMediaDescriptor[u"FilterName"_ustr] <<= u"writer_pdf_Export"_ustr;
+    saveAsPDF(u"tdf162194-soft-hyphen.fodt");
+
+    auto pPdfDocument = parsePDFExport();
+    CPPUNIT_ASSERT_EQUAL(1, pPdfDocument->getPageCount());
+
+    auto pPdfPage = pPdfDocument->openPage(/*nIndex*/ 0);
+    CPPUNIT_ASSERT(pPdfPage);
+    auto pTextPage = pPdfPage->getTextPage();
+    CPPUNIT_ASSERT(pTextPage);
+
+    int nPageObjectCount = pPdfPage->getObjectCount();
+    CPPUNIT_ASSERT_EQUAL(4, nPageObjectCount);
+
+    std::vector<OUString> aText;
+    std::vector<basegfx::B2DRectangle> aRect;
+
+    int nTextObjectCount = 0;
+    for (int i = 0; i < nPageObjectCount; ++i)
+    {
+        auto pPageObject = pPdfPage->getObject(i);
+        CPPUNIT_ASSERT_MESSAGE("no object", pPageObject != nullptr);
+        if (pPageObject->getType() == vcl::pdf::PDFPageObjectType::Text)
+        {
+            aText.push_back(pPageObject->getText(pTextPage));
+            aRect.push_back(pPageObject->getBounds());
+            ++nTextObjectCount;
+        }
+    }
+
+    CPPUNIT_ASSERT_EQUAL(4, nTextObjectCount);
+
+    CPPUNIT_ASSERT_EQUAL(u"Waffle"_ustr, aText.at(0).trim());
+    CPPUNIT_ASSERT_EQUAL(u"AAA Waf"_ustr, aText.at(1).trim());
+    CPPUNIT_ASSERT_EQUAL(u""_ustr, aText.at(2).trim());
+    CPPUNIT_ASSERT_EQUAL(u"fle"_ustr, aText.at(3).trim());
+}
+
 } // end anonymous namespace
 
 CPPUNIT_PLUGIN_IMPLEMENT();

Reply via email to