sd/qa/unit/export-tests.cxx             |    4 -
 svx/CppunitTest_svx_removewhichrange.mk |    1 
 svx/source/svdraw/svdpdf.cxx            |   66 +++++++++++++++++++++++++++-----
 3 files changed, 59 insertions(+), 12 deletions(-)

New commits:
commit 070be7bf8b79b4a9a04f37de5f7431195440ab40
Author:     Caolán McNamara <[email protected]>
AuthorDate: Thu Sep 25 17:54:44 2025 +0100
Commit:     Caolán McNamara <[email protected]>
CommitDate: Tue Oct 14 17:15:28 2025 +0200

    make extracted ligatures non-discretionary
    
    If they appear in the cmaps then they are used and we want them, so
    assume they are liga instead of dlig.
    
    Change-Id: Ic044cc4c98385a52849e64b081f0af8d60249858
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191514
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>
    (cherry picked from commit 49e9cd83908c69f293115723f8b738e4416666fd)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192339
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/sd/qa/unit/export-tests.cxx b/sd/qa/unit/export-tests.cxx
index 0b63a7274a63..e0a823ca5247 100644
--- a/sd/qa/unit/export-tests.cxx
+++ b/sd/qa/unit/export-tests.cxx
@@ -1092,7 +1092,7 @@ CPPUNIT_TEST_FIXTURE(SdExportTest, testExplodedPdfFont)
         CPPUNIT_ASSERT_EQUAL(u"normal"_ustr, sItalic);
         // check that the others remain as expected
         OUString sFontName = getXPath(pXml, "//font[2]", "name");
-        CPPUNIT_ASSERT_EQUAL(u"Liberation Serif:dlig"_ustr, sFontName);
+        CPPUNIT_ASSERT_EQUAL(u"Liberation Serif"_ustr, sFontName);
         int nFontHeight = getXPath(pXml, "//font[2]", "height").toInt32();
         CPPUNIT_ASSERT_EQUAL(494, nFontHeight);
     }
@@ -1104,7 +1104,7 @@ CPPUNIT_TEST_FIXTURE(SdExportTest, testExplodedPdfFont)
         CPPUNIT_ASSERT_EQUAL(u"bold"_ustr, sWeight);
         // check that the others remain as expected
         OUString sFontName = getXPath(pXml, "//font[4]", "name");
-        CPPUNIT_ASSERT_EQUAL(u"Liberation Sans:dlig"_ustr, sFontName);
+        CPPUNIT_ASSERT_EQUAL(u"Liberation Sans"_ustr, sFontName);
         int nFontHeight = getXPath(pXml, "//font[4]", "height").toInt32();
         CPPUNIT_ASSERT_EQUAL(564, nFontHeight);
     }
diff --git a/svx/source/svdraw/svdpdf.cxx b/svx/source/svdraw/svdpdf.cxx
index 6232f0f32f8d..37db6b706166 100644
--- a/svx/source/svdraw/svdpdf.cxx
+++ b/svx/source/svdraw/svdpdf.cxx
@@ -1229,7 +1229,7 @@ static void buildCMapAndFeatures(const OUString& CMapUrl, 
const OUString& Featur
 
         SvFileStream Features(FeaturesUrl, StreamMode::READWRITE | 
StreamMode::TRUNC);
         Features.WriteLine("languagesystem DFLT dflt;");
-        Features.WriteLine("feature dlig {");
+        Features.WriteLine("feature liga {");
         for (const auto& ligature : ligatureGlyphToChars)
         {
             sal_Int32 nLigatureGlyph = ligature.first;
@@ -1244,7 +1244,7 @@ static void buildCMapAndFeatures(const OUString& CMapUrl, 
const OUString& Featur
             ligatureLine += " by \" + OString::number(nLigatureGlyph) + ";";
             Features.WriteLine(ligatureLine);
         }
-        Features.WriteLine("} dlig;");
+        Features.WriteLine("} liga;");
         Features.Close();
 
         bFeatures = true;
@@ -1370,7 +1370,7 @@ static EmbeddedFontInfo mergeFontSubsets(const OUString& 
mergedFontUrl,
     {
         SvFileStream Features(mergedFeaturesUrl, StreamMode::READWRITE | 
StreamMode::TRUNC);
         Features.WriteLine("languagesystem DFLT dflt;");
-        Features.WriteLine("feature dlig {");
+        Features.WriteLine("feature liga {");
         for (const auto& ligature : ligatureGlyphToChars)
         {
             sal_Int32 nLigatureGlyph = ligature.first;
@@ -1385,7 +1385,7 @@ static EmbeddedFontInfo mergeFontSubsets(const OUString& 
mergedFontUrl,
             ligatureLine += " by \" + OString::number(nLigatureGlyph) + ";";
             Features.WriteLine(ligatureLine);
         }
-        Features.WriteLine("} dlig;");
+        Features.WriteLine("} liga;");
         Features.Close();
     }
 
@@ -1498,10 +1498,7 @@ void 
ImpSdrPdfImport::ImportText(std::unique_ptr<vcl::pdf::PDFiumPageObject> con
     aFnt.SetFontSize(aFontSize);
 
     if (!sFontName.isEmpty())
-    {
-        //TODO: any way to know if we need to force discretionally ligatures
-        aFnt.SetFamilyName(sFontName + ":dlig");
-    }
+        aFnt.SetFamilyName(sFontName);
 
     const int italicAngle = pPageObject->getFontAngle();
     aFnt.SetItalic(italicAngle == 0 ? ITALIC_NONE
commit 0c5dafe056d6642d7a1bf93f1ce23dfb39d16787
Author:     Caolán McNamara <[email protected]>
AuthorDate: Thu Sep 25 17:53:28 2025 +0100
Commit:     Caolán McNamara <[email protected]>
CommitDate: Tue Oct 14 17:15:14 2025 +0200

    Add in legacy unicode ligature decomposition mapping explictly
    
    Change-Id: I22978bd0e5a00c064bfafd36c7ff137744b62c48
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191513
    Reviewed-by: Miklos Vajna <[email protected]>
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    (cherry picked from commit 6856e4c93d97695cf5a1bbdb763272e947436484)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192338
    Tested-by: Caolán McNamara <[email protected]>
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/svx/CppunitTest_svx_removewhichrange.mk 
b/svx/CppunitTest_svx_removewhichrange.mk
index 9fea95320f7b..e29e3744b9f8 100644
--- a/svx/CppunitTest_svx_removewhichrange.mk
+++ b/svx/CppunitTest_svx_removewhichrange.mk
@@ -15,6 +15,7 @@ $(eval $(call 
gb_CppunitTest_add_exception_objects,svx_removewhichrange, \
 
 $(eval $(call gb_CppunitTest_use_externals,svx_removewhichrange, \
     boost_headers \
+    icuuc \
     libxml2 \
 ))
 
diff --git a/svx/source/svdraw/svdpdf.cxx b/svx/source/svdraw/svdpdf.cxx
index ee414709cbe6..6232f0f32f8d 100644
--- a/svx/source/svdraw/svdpdf.cxx
+++ b/svx/source/svdraw/svdpdf.cxx
@@ -74,6 +74,7 @@
 #include <o3tl/string_view.hxx>
 #include <osl/diagnose.h>
 #include <osl/file.hxx>
+#include <unicode/normalizer2.h>
 
 using namespace com::sun::star;
 
@@ -1074,6 +1075,40 @@ static bool toPfaCID(SubSetInfo& rSubSetInfo, const 
OUString& fileUrl,
     return true;
 }
 
+static OString decomposeLegacyUnicodeLigature(UChar32 cUnicode)
+{
+    UErrorCode eCode(U_ZERO_ERROR);
+
+    // Put in any legacy unicode ligature decompositions, which we detect as 
U_DT_COMPAT and
+    // a multi-character decomposition.
+    UDecompositionType decompType = static_cast<UDecompositionType>(
+        u_getIntPropertyValue(cUnicode, UCHAR_DECOMPOSITION_TYPE));
+    if (decompType == UDecompositionType::U_DT_COMPAT)
+    {
+        const icu::Normalizer2* pInstance = 
icu::Normalizer2::getNFKDInstance(eCode);
+
+        if (pInstance && eCode == U_ZERO_ERROR)
+        {
+            icu::UnicodeString sDecomposed;
+            pInstance->getRawDecomposition(cUnicode, sDecomposed);
+            if (sDecomposed.length() > 1)
+            {
+                OStringBuffer aBuffer;
+                for (int32_t i = 0, nLen = sDecomposed.length(); i < nLen; ++i)
+                {
+                    OString sCodePoint = OString::number(sDecomposed[i], 16);
+                    for (sal_Int32 j = sCodePoint.getLength(); j < 4; ++j)
+                        aBuffer.append('0');
+                    aBuffer.append(sCodePoint);
+                }
+                return aBuffer.toString();
+            }
+        }
+    }
+
+    return OString();
+}
+
 const char cmapprefix[] = "%!PS-Adobe-3.0 Resource-CMap
"
                           "/WMode 0 def
"
                           "
"
@@ -1146,6 +1181,8 @@ static void buildCMapAndFeatures(const OUString& CMapUrl, 
const OUString& Featur
             sal_Int32 nEnd = charline.indexOf('>', 1);
             assert(charline[nEnd] == '>');
             sal_Int32 nGlyphIndex = o3tl::toInt32(charline.subView(1, nEnd - 
1), 16);
+            if (bNameKeyed)
+                nGlyphIndex = nameIndexToGlyph[nGlyphIndex];
             OString sChars(o3tl::trim(charline.subView(nEnd + 1)));
             assert(sChars[0] == '<' && sChars[sChars.getLength() - 1] == '>');
             OString sContents = sChars.copy(1, sChars.getLength() - 2);
@@ -1153,8 +1190,13 @@ static void buildCMapAndFeatures(const OUString& 
CMapUrl, const OUString& Featur
             sal_Int32 nCharsPerCode = sContents.getLength() / 4;
             if (nCharsPerCode > 1)
                 ligatureGlyphToChars[nGlyphIndex] = sContents;
-            if (bNameKeyed)
-                nGlyphIndex = nameIndexToGlyph[nGlyphIndex];
+            else
+            {
+                OString sLegacy
+                    = 
decomposeLegacyUnicodeLigature(static_cast<UChar32>(sContents.toUInt32(16)));
+                if (!sLegacy.isEmpty())
+                    ligatureGlyphToChars[nGlyphIndex] = sLegacy;
+            }
             OString cidcharline = sChars + " " + OString::number(nGlyphIndex);
             glyphs.push_back(nGlyphIndex);
             rSubSetInfo.aComponents.back().glyphToChars[nGlyphIndex] = 
sContents;
@@ -1304,6 +1346,13 @@ static EmbeddedFontInfo mergeFontSubsets(const OUString& 
mergedFontUrl,
                 sal_Int32 nCharsPerCode = sCharContents.getLength() / 4;
                 if (nCharsPerCode > 1)
                     ligatureGlyphToChars[glyph] = sCharContents;
+                else
+                {
+                    OString sLegacy = decomposeLegacyUnicodeLigature(
+                        static_cast<UChar32>(sCharContents.toUInt32(16)));
+                    if (!sLegacy.isEmpty())
+                        ligatureGlyphToChars[glyph] = sLegacy;
+                }
 
                 charsToGlyph[entry.second] = glyph;
                 mergedCMap.WriteLine(cidcharline);

Reply via email to