tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / vcl / unx / generic / fontmanager / fontsubst.cxx
bloba5c34a112d78e76a62afa57dd51178f392835b65
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
22 #include <unx/geninst.h>
23 #include <font/PhysicalFontCollection.hxx>
24 #include <font/fontsubstitution.hxx>
25 #include <unx/fontmanager.hxx>
27 // platform specific font substitution hooks
29 namespace {
31 class FcPreMatchSubstitution
32 : public vcl::font::PreMatchFontSubstitution
34 public:
35 bool FindFontSubstitute( vcl::font::FontSelectPattern& ) const override;
36 typedef ::std::pair<vcl::font::FontSelectPattern, vcl::font::FontSelectPattern> value_type;
37 private:
38 typedef ::std::list<value_type> CachedFontMapType;
39 mutable CachedFontMapType maCachedFontMap;
42 class FcGlyphFallbackSubstitution
43 : public vcl::font::GlyphFallbackFontSubstitution
45 // TODO: add a cache
46 public:
47 bool FindFontSubstitute(vcl::font::FontSelectPattern&, LogicalFontInstance* pLogicalFont, OUString& rMissingCodes) const override;
52 void SalGenericInstance::RegisterFontSubstitutors(vcl::font::PhysicalFontCollection* pFontCollection)
54 // register font fallback substitutions
55 static FcPreMatchSubstitution aSubstPreMatch;
56 pFontCollection->SetPreMatchHook( &aSubstPreMatch );
58 // register glyph fallback substitutions
59 static FcGlyphFallbackSubstitution aSubstFallback;
60 pFontCollection->SetFallbackHook( &aSubstFallback );
63 static vcl::font::FontSelectPattern GetFcSubstitute(const vcl::font::FontSelectPattern &rFontSelData, OUString& rMissingCodes)
65 vcl::font::FontSelectPattern aSubstituted(rFontSelData);
66 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
67 rMgr.Substitute(aSubstituted, rMissingCodes);
68 return aSubstituted;
71 namespace
73 bool uselessmatch(const vcl::font::FontSelectPattern &rOrig, const vcl::font::FontSelectPattern &rNew)
75 return
77 rOrig.maTargetName == rNew.maSearchName &&
78 rOrig.GetWeight() == rNew.GetWeight() &&
79 rOrig.GetItalic() == rNew.GetItalic() &&
80 rOrig.GetPitch() == rNew.GetPitch() &&
81 rOrig.GetWidthType() == rNew.GetWidthType()
85 class equal
87 private:
88 const vcl::font::FontSelectPattern& mrAttributes;
89 public:
90 explicit equal(const vcl::font::FontSelectPattern& rAttributes)
91 : mrAttributes(rAttributes)
94 bool operator()(const FcPreMatchSubstitution::value_type& rOther) const
95 { return rOther.first == mrAttributes; }
99 bool FcPreMatchSubstitution::FindFontSubstitute(vcl::font::FontSelectPattern &rFontSelData) const
101 // We don't actually want to talk to Fontconfig at all for symbol fonts
102 if( rFontSelData.IsMicrosoftSymbolEncoded() )
103 return false;
104 // OpenSymbol is a unicode font, but it still deserves to be treated as a symbol font
105 if ( IsOpenSymbol(rFontSelData.maSearchName) )
106 return false;
108 //see fdo#41556 and fdo#47636
109 //fontconfig can return e.g. an italic font for a non-italic input and/or
110 //different fonts depending on fontsize, bold, etc settings so don't cache
111 //just on the name, cache map all the input and all the output not just map
112 //from original selection to output fontname
113 vcl::font::FontSelectPattern& rPatternAttributes = rFontSelData;
114 CachedFontMapType &rCachedFontMap = maCachedFontMap;
115 CachedFontMapType::iterator itr = std::find_if(rCachedFontMap.begin(), rCachedFontMap.end(), equal(rPatternAttributes));
116 if (itr != rCachedFontMap.end())
118 // Cached substitution
119 rFontSelData = itr->second;
120 if (itr != rCachedFontMap.begin())
122 // MRU, move it to the front
123 rCachedFontMap.splice(rCachedFontMap.begin(), rCachedFontMap, itr);
125 return true;
128 OUString aDummy;
129 const vcl::font::FontSelectPattern aOut = GetFcSubstitute( rFontSelData, aDummy );
131 if( aOut.maSearchName.isEmpty() )
132 return false;
134 const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut );
136 #if OSL_DEBUG_LEVEL >= 2
137 std::ostringstream oss;
138 oss << "FcPreMatchSubstitution \""
139 << rFontSelData.maTargetName
140 << "\" bipw="
141 << rFontSelData.GetWeight()
142 << rFontSelData.GetItalic()
143 << rFontSelData.GetPitch()
144 << rFontSelData.GetWidthType()
145 << " -> ";
146 if( !bHaveSubstitute )
147 oss << "no substitute available.";
148 else
149 oss << "\""
150 << aOut.maSearchName
151 << "\" bipw="
152 << aOut.GetWeight()
153 << aOut.GetItalic()
154 << aOut.GetPitch()
155 << aOut.GetWidthType();
156 SAL_INFO("vcl.fonts", oss.str());
157 #endif
159 if( bHaveSubstitute )
161 rCachedFontMap.push_front(value_type(rFontSelData, aOut));
162 // Fairly arbitrary limit in this case, but I recall measuring max 8
163 // fonts as the typical max amount of fonts in medium sized documents, so make it
164 // a fair chunk larger to accommodate weird documents./
165 if (rCachedFontMap.size() > 256)
166 rCachedFontMap.pop_back();
167 rFontSelData = aOut;
170 return bHaveSubstitute;
173 bool FcGlyphFallbackSubstitution::FindFontSubstitute(vcl::font::FontSelectPattern& rFontSelData,
174 LogicalFontInstance* /*pLogicalFont*/,
175 OUString& rMissingCodes ) const
177 // We don't actually want to talk to Fontconfig at all for symbol fonts
178 if( rFontSelData.IsMicrosoftSymbolEncoded() )
179 return false;
180 // OpenSymbol is a unicode font, but it still deserves to be treated as a symbol font
181 if ( IsOpenSymbol(rFontSelData.maSearchName) )
182 return false;
184 const vcl::font::FontSelectPattern aOut = GetFcSubstitute( rFontSelData, rMissingCodes );
185 // TODO: cache the unicode + srcfont specific result
186 // FC doing it would be preferable because it knows the invariables
187 // e.g. FC knows the FC rule that all Arial gets replaced by LiberationSans
188 // whereas we would have to check for every size or attribute
189 if( aOut.maSearchName.isEmpty() )
190 return false;
192 const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut );
194 #if OSL_DEBUG_LEVEL >= 2
195 std::ostringstream oss;
196 oss << "FcGFSubstitution \""
197 << rFontSelData.maTargetName
198 << "\" bipw="
199 << rFontSelData.GetWeight()
200 << rFontSelData.GetItalic()
201 << rFontSelData.GetPitch()
202 << rFontSelData.GetWidthType()
203 << " -> ";
204 if( !bHaveSubstitute )
205 oss << "no substitute available.";
206 else
207 oss << "\""
208 << aOut.maSearchName
209 << "\" bipw="
210 << aOut.GetWeight()
211 << aOut.GetItalic()
212 << aOut.GetPitch()
213 << aOut.GetWidthType();
214 SAL_INFO("vcl.fonts", oss.str());
215 #endif
217 if( bHaveSubstitute )
218 rFontSelData = aOut;
220 return bHaveSubstitute;
223 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */