vcl/source/font/PhysicalFontCollection.cxx |  129 +++++++++++++++++------------
 1 file changed, 76 insertions(+), 53 deletions(-)

New commits:
commit a37bf2e33025d8476625adeb6ca1f8c3a72df80c
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Thu Jul 31 20:42:37 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Fri Aug 1 19:42:55 2025 +0200

    Fix a TODO: drop the reference
    
    It is actually easier to see what we are using / modifying; and the
    replaced reference is not much shorter.
    
    Change-Id: I12a8ddebbf02033a35179ac752a8aa38a2aad89b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188743
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/vcl/source/font/PhysicalFontCollection.cxx 
b/vcl/source/font/PhysicalFontCollection.cxx
index e22978481ff6..7be28165fee3 100644
--- a/vcl/source/font/PhysicalFontCollection.cxx
+++ b/vcl/source/font/PhysicalFontCollection.cxx
@@ -996,49 +996,48 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
 
     bool bMultiToken = false;
     sal_Int32 nTokenPos = 0;
-    OUString& aSearchName = rFSD.maSearchName; // TODO: get rid of reference
     for(;;)
     {
         rFSD.maTargetName = GetNextFontToken( rFSD.GetFamilyName(), nTokenPos 
);
-        aSearchName = rFSD.maTargetName;
+        rFSD.maSearchName = rFSD.maTargetName;
 
         // Until features are properly supported, they are appended to the
         // font name, so we need to strip them off so the font is found.
-        sal_Int32 nFeat = aSearchName.indexOf(FontSelectPattern::FEAT_PREFIX);
+        sal_Int32 nFeat = 
rFSD.maSearchName.indexOf(FontSelectPattern::FEAT_PREFIX);
         OUString aOrigName = rFSD.maTargetName;
-        OUString aBaseFontName = aSearchName.copy( 0, (nFeat != -1) ? nFeat : 
aSearchName.getLength() );
+        OUString aBaseFontName
+            = rFSD.maSearchName.copy(0, (nFeat != -1) ? nFeat : 
rFSD.maSearchName.getLength());
 
         if (nFeat != -1)
         {
-            aSearchName = aBaseFontName;
+            rFSD.maSearchName = aBaseFontName;
             rFSD.maTargetName = aBaseFontName;
         }
 
-        aSearchName = GetEnglishSearchFontName( aSearchName );
-        ImplFontSubstitute(aSearchName);
+        rFSD.maSearchName = GetEnglishSearchFontName(rFSD.maSearchName);
+        ImplFontSubstitute(rFSD.maSearchName);
         // #114999# special emboldening for Ricoh fonts
         // TODO: smarter check for special cases by using PreMatch 
infrastructure?
-        if( (rFSD.GetWeight() > WEIGHT_MEDIUM) &&
-            aSearchName.startsWithIgnoreAsciiCase( "hg" ) )
+        if ((rFSD.GetWeight() > WEIGHT_MEDIUM) && 
rFSD.maSearchName.startsWithIgnoreAsciiCase("hg"))
         {
             OUString aBoldName;
-            if( aSearchName.startsWithIgnoreAsciiCase( "hggothicb" ) )
+            if (rFSD.maSearchName.startsWithIgnoreAsciiCase("hggothicb"))
                 aBoldName = "hggothice";
-            else if( aSearchName.startsWithIgnoreAsciiCase( "hgpgothicb" ) )
+            else if (rFSD.maSearchName.startsWithIgnoreAsciiCase("hgpgothicb"))
                 aBoldName = "hgpgothice";
-            else if( aSearchName.startsWithIgnoreAsciiCase( "hgminchol" ) )
+            else if (rFSD.maSearchName.startsWithIgnoreAsciiCase("hgminchol"))
                 aBoldName = "hgminchob";
-            else if( aSearchName.startsWithIgnoreAsciiCase( "hgpminchol" ) )
+            else if (rFSD.maSearchName.startsWithIgnoreAsciiCase("hgpminchol"))
                 aBoldName = "hgpminchob";
-            else if( aSearchName.equalsIgnoreAsciiCase( "hgminchob" ) )
+            else if (rFSD.maSearchName.equalsIgnoreAsciiCase("hgminchob"))
                 aBoldName = "hgminchoe";
-            else if( aSearchName.equalsIgnoreAsciiCase( "hgpminchob" ) )
+            else if (rFSD.maSearchName.equalsIgnoreAsciiCase("hgpminchob"))
                 aBoldName = "hgpminchoe";
 
             if( !aBoldName.isEmpty() && ImplFindFontFamilyBySearchName( 
aBoldName ) )
             {
                 // the other font is available => use it
-                aSearchName = aBoldName;
+                rFSD.maSearchName = aBoldName;
                 // prevent synthetic emboldening of bold version
                 rFSD.SetWeight(WEIGHT_DONTKNOW);
             }
@@ -1048,7 +1047,7 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
         rFSD.maTargetName = aOrigName;
 
         // check if the current font name token or its substitute is valid
-        PhysicalFontFamily* pFoundData = 
ImplFindFontFamilyBySearchName(aSearchName);
+        PhysicalFontFamily* pFoundData = 
ImplFindFontFamilyBySearchName(rFSD.maSearchName);
         if( pFoundData )
             return pFoundData;
 
@@ -1070,22 +1069,22 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
         if (sStrippedName != rFSD.maTargetName)
         {
             rFSD.maTargetName = sStrippedName;
-            aSearchName = GetEnglishSearchFontName(rFSD.maTargetName);
-            pFoundData = ImplFindFontFamilyBySearchName(aSearchName);
+            rFSD.maSearchName = GetEnglishSearchFontName(rFSD.maTargetName);
+            pFoundData = ImplFindFontFamilyBySearchName(rFSD.maSearchName);
             if( pFoundData )
                 return pFoundData;
         }
 
         if (mpPreMatchHook && mpPreMatchHook->FindFontSubstitute(rFSD))
         {
-            aSearchName = GetEnglishSearchFontName(aSearchName);
+            rFSD.maSearchName = GetEnglishSearchFontName(rFSD.maSearchName);
         }
 
         // the prematch hook uses the target name to search, but we now need
         // to restore the features to make the font selection data unique
         rFSD.maTargetName = aOrigName;
 
-        pFoundData = ImplFindFontFamilyBySearchName( aSearchName );
+        pFoundData = ImplFindFontFamilyBySearchName(rFSD.maSearchName);
         if( pFoundData )
             return pFoundData;
 
@@ -1105,17 +1104,17 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
         if( bMultiToken )
         {
             rFSD.maTargetName = GetNextFontToken( rFSD.GetFamilyName(), 
nTokenPos );
-            aSearchName = GetEnglishSearchFontName( rFSD.maTargetName );
+            rFSD.maSearchName = GetEnglishSearchFontName(rFSD.maTargetName);
         }
         else
             nTokenPos = -1;
         if (FindMetricCompatibleFont(rFSD) ||
             (mpPreMatchHook && mpPreMatchHook->FindFontSubstitute(rFSD)))
         {
-            aSearchName = GetEnglishSearchFontName( aSearchName );
+            rFSD.maSearchName = GetEnglishSearchFontName(rFSD.maSearchName);
         }
-        ImplFontSubstitute(aSearchName);
-        PhysicalFontFamily* pFoundData = 
ImplFindFontFamilyBySearchName(aSearchName);
+        ImplFontSubstitute(rFSD.maSearchName);
+        PhysicalFontFamily* pFoundData = 
ImplFindFontFamilyBySearchName(rFSD.maSearchName);
         if( pFoundData )
             return pFoundData;
     }
@@ -1126,7 +1125,7 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
     {
         nTokenPos = 0;
         rFSD.maTargetName = GetNextFontToken( rFSD.GetFamilyName(), nTokenPos 
);
-        aSearchName = GetEnglishSearchFontName( rFSD.maTargetName );
+        rFSD.maSearchName = GetEnglishSearchFontName(rFSD.maTargetName);
     }
 
     OUString      aSearchShortName;
@@ -1134,12 +1133,12 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
     FontWeight    eSearchWeight   = rFSD.GetWeight();
     FontWidth     eSearchWidth    = rFSD.GetWidthType();
     ImplFontAttrs nSearchType     = ImplFontAttrs::None;
-    utl::FontSubstConfiguration::getMapName( aSearchName, aSearchShortName, 
aSearchFamilyName,
+    utl::FontSubstConfiguration::getMapName( rFSD.maSearchName, 
aSearchShortName, aSearchFamilyName,
                                              eSearchWeight, eSearchWidth, 
nSearchType );
 
     // note: the search name was already translated to english (if possible)
     // use the font's shortened name if needed
-    if ( aSearchShortName != aSearchName )
+    if (aSearchShortName != rFSD.maSearchName)
     {
         PhysicalFontFamily* pFoundData = 
ImplFindFontFamilyBySearchName(aSearchShortName);
         if( pFoundData )
@@ -1149,7 +1148,7 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
             a korean bitmap font that is not suitable here. Use the font 
replacement table,
             that automatically leads to the desired "HG Mincho Light J". Same 
story for
             MS Gothic, there are thai and korean "Gothic" fonts, so we even 
prefer Andale */
-            if ((aSearchName != "msmincho") && (aSearchName != "msgothic"))
+            if ((rFSD.maSearchName != "msmincho") && (rFSD.maSearchName != 
"msgothic"))
                 // TODO: add heuristic to only throw out the fake ms* fonts
 #endif
             {
@@ -1160,13 +1159,13 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
 
     // use font fallback
     const utl::FontNameAttr* pFontAttr = nullptr;
-    if (!aSearchName.isEmpty() && !comphelper::IsFuzzing())
+    if (!rFSD.maSearchName.isEmpty() && !comphelper::IsFuzzing())
     {
         // get fallback info using FontSubstConfiguration and
         // the target name, it's shortened name and family name in that order
         const utl::FontSubstConfiguration& rFontSubst = 
utl::FontSubstConfiguration::get();
-        pFontAttr = rFontSubst.getSubstInfo( aSearchName );
-        if ( !pFontAttr && (aSearchShortName != aSearchName) )
+        pFontAttr = rFontSubst.getSubstInfo(rFSD.maSearchName);
+        if (!pFontAttr && (aSearchShortName != rFSD.maSearchName))
             pFontAttr = rFontSubst.getSubstInfo( aSearchShortName );
         if ( !pFontAttr && (aSearchFamilyName != aSearchShortName) )
             pFontAttr = rFontSubst.getSubstInfo( aSearchFamilyName );
@@ -1185,10 +1184,10 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
     {
         LanguageTag aDefaultLanguageTag(u"en"_ustr);
         if (comphelper::IsFuzzing())
-            aSearchName = "OpenSymbol";
+            rFSD.maSearchName = "OpenSymbol";
         else
-            aSearchName = utl::DefaultFontConfiguration::get().getDefaultFont( 
aDefaultLanguageTag, DefaultFontType::SYMBOL );
-        PhysicalFontFamily* pFoundData = 
FindFontFamilyByTokenNames(aSearchName);
+            rFSD.maSearchName = 
utl::DefaultFontConfiguration::get().getDefaultFont( aDefaultLanguageTag, 
DefaultFontType::SYMBOL );
+        PhysicalFontFamily* pFoundData = 
FindFontFamilyByTokenNames(rFSD.maSearchName);
         if( pFoundData )
             return pFoundData;
     }
@@ -1200,18 +1199,18 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
         if( rFSD.maTargetName.isEmpty() )
             continue;
 
-        aSearchName = GetEnglishSearchFontName( rFSD.maTargetName );
+        rFSD.maSearchName = GetEnglishSearchFontName(rFSD.maTargetName);
 
         OUString      aTempShortName;
         OUString      aTempFamilyName;
         ImplFontAttrs nTempType   = ImplFontAttrs::None;
         FontWeight    eTempWeight = rFSD.GetWeight();
         FontWidth     eTempWidth  = WIDTH_DONTKNOW;
-        utl::FontSubstConfiguration::getMapName( aSearchName, aTempShortName, 
aTempFamilyName,
+        utl::FontSubstConfiguration::getMapName( rFSD.maSearchName, 
aTempShortName, aTempFamilyName,
                                                  eTempWeight, eTempWidth, 
nTempType );
 
         // use a shortened token name if available
-        if( aTempShortName != aSearchName )
+        if (aTempShortName != rFSD.maSearchName)
         {
             PhysicalFontFamily* pFoundData = 
ImplFindFontFamilyBySearchName(aTempShortName);
             if( pFoundData )
@@ -1225,9 +1224,9 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
             // get fallback info using FontSubstConfiguration and
             // the target name, it's shortened name and family name in that 
order
             const utl::FontSubstConfiguration& rFontSubst = 
utl::FontSubstConfiguration::get();
-            pTempFontAttr = rFontSubst.getSubstInfo( aSearchName );
+            pTempFontAttr = rFontSubst.getSubstInfo(rFSD.maSearchName);
 
-            if ( !pTempFontAttr && (aTempShortName != aSearchName) )
+            if (!pTempFontAttr && (aTempShortName != rFSD.maSearchName))
                 pTempFontAttr = rFontSubst.getSubstInfo( aTempShortName );
 
             if ( !pTempFontAttr && (aTempFamilyName != aTempShortName) )
commit b0d91b4e08964e4ec297030da8f18adb03c31311
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Thu Jul 31 18:49:47 2025 +0500
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Fri Aug 1 19:42:46 2025 +0200

    Use known compatible substitutions for Bundes* fonts
    
    As recommended on
    https://styleguide.bundesregierung.de/sg-de/basiselemente/schriften.
    
    Because of https://github.com/google/fonts/issues/9720, we have to
    use MS fonts as first choice; and use another attempt on the first
    result, when it's also absent on system, to get our bundled fonts.
    
    Change-Id: I2ac0731be468a8d12c4bb8ef61726bae341b3b07
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188742
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    Tested-by: Jenkins

diff --git a/vcl/source/font/PhysicalFontCollection.cxx 
b/vcl/source/font/PhysicalFontCollection.cxx
index 9ce93fea5b1f..e22978481ff6 100644
--- a/vcl/source/font/PhysicalFontCollection.cxx
+++ b/vcl/source/font/PhysicalFontCollection.cxx
@@ -930,23 +930,32 @@ std::unique_ptr<PhysicalFontFaceCollection> 
PhysicalFontCollection::GetFontFaceC
 // These are the metric-compatible replacement fonts that are bundled with
 // LibreOffice, we prefer them over generic substitutions that might be
 // provided by the system.
-const std::vector<std::pair<OUString, OUString>> aMetricCompatibleMap =
+constexpr std::pair<std::u16string_view, std::u16string_view> 
aMetricCompatibleMap[] =
 {
-    { "Times New Roman", "Liberation Serif" },
-    { "Arial",           "Liberation Sans" },
-    { "Arial Narrow",    "Liberation Sans Narrow" },
-    { "Courier New",     "Liberation Mono" },
-    { "Cambria",         "Caladea" },
-    { "Calibri",         "Carlito" },
+    { u"Times New Roman", u"Liberation Serif" },
+    { u"Arial",           u"Liberation Sans" },
+    { u"Arial Narrow",    u"Liberation Sans Narrow" },
+    { u"Courier New",     u"Liberation Mono" },
+    { u"Cambria",         u"Caladea" },
+    { u"Calibri",         u"Carlito" },
+
+    // Official replacements for Bundes* fonts. 
https://github.com/google/fonts/issues/9720
+    // prevents from using Carlito as direct metric-compatible replacement.
+    { u"BundesSans",          u"Calibri" },
+    { u"BundesSans Office",   u"Calibri" },
+    { u"BundesSans Regular",  u"Calibri" },
+    { u"BundesSerif",         u"Cambria" },
+    { u"BundesSerif Office",  u"Cambria" },
+    { u"BundesSerif Regular", u"Cambria" },
 };
 
-static bool FindMetricCompatibleFont(FontSelectPattern& rFontSelData)
+static bool FindMetricCompatibleFont_impl(FontSelectPattern& rFontSelData)
 {
-    for (const auto& aSub : aMetricCompatibleMap)
+    for (const auto& [font, metric_compatible_font] : aMetricCompatibleMap)
     {
-        if (rFontSelData.maSearchName == GetEnglishSearchFontName(aSub.first))
+        if (rFontSelData.maSearchName == GetEnglishSearchFontName(font))
         {
-            rFontSelData.maSearchName = aSub.second;
+            rFontSelData.maSearchName = 
GetEnglishSearchFontName(metric_compatible_font);
             return true;
         }
     }
@@ -972,6 +981,19 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
         return pFont;
     }
 
+    auto FindMetricCompatibleFont = [this](FontSelectPattern& rFontSelData) -> 
PhysicalFontFamily*
+    {
+        while (FindMetricCompatibleFont_impl(rFontSelData))
+        {
+            if (auto* pFont = 
ImplFindFontFamilyBySearchName(rFontSelData.maSearchName))
+                return pFont;
+            // Try again, with the updated maSearchName: maybe there is a 
metric-compatible font
+            // for metric-compatible font? E.g., Bundes* family of fonts has 
preferred substitute
+            // MS fonts; and those have their substitutions.
+        }
+        return nullptr;
+    };
+
     bool bMultiToken = false;
     sal_Int32 nTokenPos = 0;
     OUString& aSearchName = rFSD.maSearchName; // TODO: get rid of reference
@@ -1030,6 +1052,9 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
         if( pFoundData )
             return pFoundData;
 
+        if (pFoundData = FindMetricCompatibleFont(rFSD); pFoundData)
+            return pFoundData;
+
         // some systems provide special customization
         // e.g. they suggest "serif" as UI-font, but this name cannot be used 
directly
         //      because the system wants to map it to another font first, e.g. 
"Helvetica"
@@ -1051,8 +1076,7 @@ PhysicalFontFamily* 
PhysicalFontCollection::FindFontFamily(FontSelectPattern& rF
                 return pFoundData;
         }
 
-        if (FindMetricCompatibleFont(rFSD) ||
-            (mpPreMatchHook && mpPreMatchHook->FindFontSubstitute(rFSD)))
+        if (mpPreMatchHook && mpPreMatchHook->FindFontSubstitute(rFSD))
         {
             aSearchName = GetEnglishSearchFontName(aSearchName);
         }

Reply via email to