Impress Remote 1.0.5, tag sdremote-1.0.5
[LibreOffice.git] / vcl / generic / fontmanager / fontsubst.cxx
blob23ac9688522e13a8ab057034985a51806ca78931
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 "generic/geninst.h"
21 #include "generic/genpspgraphics.h"
22 #include "generic/glyphcache.hxx"
24 #include "vcl/sysdata.hxx"
25 #include "outfont.hxx"
27 #include "generic/printergfx.hxx"
28 #include "salbmp.hxx"
29 #include "impfont.hxx"
30 #include "outfont.hxx"
31 #include "outdev.h"
32 #include "fontsubset.hxx"
33 #include "salprn.hxx"
34 #include "region.h"
36 #include <list>
38 // ===========================================================================
39 // platform specific font substitution hooks
40 // ===========================================================================
42 struct FontSelectPatternAttributesHash
44 size_t operator()(const FontSelectPatternAttributes& rAttributes) const
45 { return rAttributes.hashCode(); }
48 class FcPreMatchSubstititution
49 : public ImplPreMatchFontSubstitution
51 public:
52 bool FindFontSubstitute( FontSelectPattern& ) const;
53 typedef ::std::pair<FontSelectPatternAttributes, FontSelectPatternAttributes> value_type;
54 private:
55 typedef ::std::list<value_type> CachedFontMapType;
56 mutable CachedFontMapType maCachedFontMap;
59 class FcGlyphFallbackSubstititution
60 : public ImplGlyphFallbackFontSubstitution
62 // TODO: add a cache
63 public:
64 bool FindFontSubstitute( FontSelectPattern&, rtl::OUString& rMissingCodes ) const;
67 int SalGenericInstance::FetchFontSubstitutionFlags()
69 // init font substitution defaults
70 int nDisableBits = 0;
71 #ifdef SOLARIS
72 nDisableBits = 1; // disable "font fallback" here on default
73 #endif
74 // apply the environment variable if any
75 const char* pEnvStr = ::getenv( "SAL_DISABLE_FC_SUBST" );
76 if( pEnvStr )
78 if( (*pEnvStr >= '0') && (*pEnvStr <= '9') )
79 nDisableBits = (*pEnvStr - '0');
80 else
81 nDisableBits = ~0U; // no specific bits set: disable all
83 return nDisableBits;
86 void SalGenericInstance::RegisterFontSubstitutors( ImplDevFontList* pList )
88 // init font substitution defaults
89 int nDisableBits = 0;
90 #ifdef SOLARIS
91 nDisableBits = 1; // disable "font fallback" here on default
92 #endif
93 // apply the environment variable if any
94 const char* pEnvStr = ::getenv( "SAL_DISABLE_FC_SUBST" );
95 if( pEnvStr )
97 if( (*pEnvStr >= '0') && (*pEnvStr <= '9') )
98 nDisableBits = (*pEnvStr - '0');
99 else
100 nDisableBits = ~0U; // no specific bits set: disable all
103 // register font fallback substitutions (unless disabled by bit0)
104 if( (nDisableBits & 1) == 0 )
106 static FcPreMatchSubstititution aSubstPreMatch;
107 pList->SetPreMatchHook( &aSubstPreMatch );
110 // register glyph fallback substitutions (unless disabled by bit1)
111 if( (nDisableBits & 2) == 0 )
113 static FcGlyphFallbackSubstititution aSubstFallback;
114 pList->SetFallbackHook( &aSubstFallback );
118 // -----------------------------------------------------------------------
120 static FontSelectPattern GetFcSubstitute(const FontSelectPattern &rFontSelData, rtl::OUString& rMissingCodes )
122 FontSelectPattern aSubstituted(rFontSelData);
123 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
124 rMgr.Substitute(aSubstituted, rMissingCodes);
125 return aSubstituted;
128 namespace
130 bool uselessmatch(const FontSelectPattern &rOrig, const FontSelectPattern &rNew)
132 return
134 rOrig.maTargetName == rNew.maSearchName &&
135 rOrig.meWeight == rNew.meWeight &&
136 rOrig.meItalic == rNew.meItalic &&
137 rOrig.mePitch == rNew.mePitch &&
138 rOrig.meWidthType == rNew.meWidthType
142 class equal
144 private:
145 const FontSelectPatternAttributes& mrAttributes;
146 public:
147 equal(const FontSelectPatternAttributes& rAttributes)
148 : mrAttributes(rAttributes)
151 bool operator()(const FcPreMatchSubstititution::value_type& rOther) const
152 { return rOther.first == mrAttributes; }
156 //--------------------------------------------------------------------------
158 bool FcPreMatchSubstititution::FindFontSubstitute( FontSelectPattern &rFontSelData ) const
160 // We dont' actually want to talk to Fontconfig at all for symbol fonts
161 if( rFontSelData.IsSymbolFont() )
162 return false;
163 // StarSymbol is a unicode font, but it still deserves the symbol flag
164 if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10)
165 || 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) )
166 return false;
168 //see fdo#41556 and fdo#47636
169 //fontconfig can return e.g. an italic font for a non-italic input and/or
170 //different fonts depending on fontsize, bold, etc settings so don't cache
171 //just on the name, cache map all the input and all the output not just map
172 //from original selection to output fontname
173 FontSelectPatternAttributes& rPatternAttributes = rFontSelData;
174 CachedFontMapType &rCachedFontMap = const_cast<CachedFontMapType &>(maCachedFontMap);
175 CachedFontMapType::iterator itr = std::find_if(rCachedFontMap.begin(), rCachedFontMap.end(), equal(rPatternAttributes));
176 if (itr != rCachedFontMap.end())
178 // Cached substitution
179 rFontSelData.copyAttributes(itr->second);
180 if (itr != rCachedFontMap.begin())
182 // MRU, move it to the front
183 rCachedFontMap.splice(rCachedFontMap.begin(), rCachedFontMap, itr);
185 return true;
188 rtl::OUString aDummy;
189 const FontSelectPattern aOut = GetFcSubstitute( rFontSelData, aDummy );
191 if( !aOut.maSearchName.Len() )
192 return false;
194 const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut );
196 #ifdef DEBUG
197 const rtl::OString aOrigName(rtl::OUStringToOString(rFontSelData.maTargetName,
198 RTL_TEXTENCODING_UTF8));
199 const rtl::OString aSubstName(rtl::OUStringToOString(aOut.maSearchName,
200 RTL_TEXTENCODING_UTF8));
201 printf( "FcPreMatchSubstititution \"%s\" bipw=%d%d%d%d -> ",
202 aOrigName.getStr(), rFontSelData.meWeight, rFontSelData.meItalic,
203 rFontSelData.mePitch, rFontSelData.meWidthType );
204 if( !bHaveSubstitute )
205 printf( "no substitute available\n" );
206 else
207 printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.getStr(),
208 aOut.meWeight, aOut.meItalic, aOut.mePitch, aOut.meWidthType );
209 #endif
211 if( bHaveSubstitute )
213 rCachedFontMap.push_front(value_type(rFontSelData, aOut));
214 //fairly arbitrary limit in this case, but I recall measuring max 8
215 //fonts as the typical max amount of fonts in medium sized documents
216 if (rCachedFontMap.size() > 8)
217 rCachedFontMap.pop_back();
218 rFontSelData = aOut;
221 return bHaveSubstitute;
224 // -----------------------------------------------------------------------
226 bool FcGlyphFallbackSubstititution::FindFontSubstitute( FontSelectPattern& rFontSelData,
227 rtl::OUString& rMissingCodes ) const
229 // We dont' actually want to talk to Fontconfig at all for symbol fonts
230 if( rFontSelData.IsSymbolFont() )
231 return false;
232 // StarSymbol is a unicode font, but it still deserves the symbol flag
233 if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10)
234 || 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) )
235 return false;
237 const FontSelectPattern aOut = GetFcSubstitute( rFontSelData, rMissingCodes );
238 // TODO: cache the unicode + srcfont specific result
239 // FC doing it would be preferable because it knows the invariables
240 // e.g. FC knows the FC rule that all Arial gets replaced by LiberationSans
241 // whereas we would have to check for every size or attribute
242 if( !aOut.maSearchName.Len() )
243 return false;
245 const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut );
247 #ifdef DEBUG
248 const rtl::OString aOrigName(rtl::OUStringToOString(rFontSelData.maTargetName,
249 RTL_TEXTENCODING_UTF8));
250 const rtl::OString aSubstName(rtl::OUStringToOString(aOut.maSearchName,
251 RTL_TEXTENCODING_UTF8));
252 printf( "FcGFSubstititution \"%s\" bipw=%d%d%d%d ->",
253 aOrigName.getStr(), rFontSelData.meWeight, rFontSelData.meItalic,
254 rFontSelData.mePitch, rFontSelData.meWidthType );
255 if( !bHaveSubstitute )
256 printf( "no substitute available\n" );
257 else
258 printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.getStr(),
259 aOut.meWeight, aOut.meItalic, aOut.mePitch, aOut.meWidthType );
260 #endif
262 if( bHaveSubstitute )
263 rFontSelData = aOut;
265 return bHaveSubstitute;
268 // ===========================================================================
271 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */