1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
29 #include "impfont.hxx"
30 #include "outfont.hxx"
32 #include "fontsubset.hxx"
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
52 bool FindFontSubstitute( FontSelectPattern
& ) const;
53 typedef ::std::pair
<FontSelectPatternAttributes
, FontSelectPatternAttributes
> value_type
;
55 typedef ::std::list
<value_type
> CachedFontMapType
;
56 mutable CachedFontMapType maCachedFontMap
;
59 class FcGlyphFallbackSubstititution
60 : public ImplGlyphFallbackFontSubstitution
64 bool FindFontSubstitute( FontSelectPattern
&, rtl::OUString
& rMissingCodes
) const;
67 int SalGenericInstance::FetchFontSubstitutionFlags()
69 // init font substitution defaults
72 nDisableBits
= 1; // disable "font fallback" here on default
74 // apply the environment variable if any
75 const char* pEnvStr
= ::getenv( "SAL_DISABLE_FC_SUBST" );
78 if( (*pEnvStr
>= '0') && (*pEnvStr
<= '9') )
79 nDisableBits
= (*pEnvStr
- '0');
81 nDisableBits
= ~0U; // no specific bits set: disable all
86 void SalGenericInstance::RegisterFontSubstitutors( ImplDevFontList
* pList
)
88 // init font substitution defaults
91 nDisableBits
= 1; // disable "font fallback" here on default
93 // apply the environment variable if any
94 const char* pEnvStr
= ::getenv( "SAL_DISABLE_FC_SUBST" );
97 if( (*pEnvStr
>= '0') && (*pEnvStr
<= '9') )
98 nDisableBits
= (*pEnvStr
- '0');
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
);
130 bool uselessmatch(const FontSelectPattern
&rOrig
, const FontSelectPattern
&rNew
)
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
145 const FontSelectPatternAttributes
& mrAttributes
;
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() )
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) )
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
);
188 rtl::OUString aDummy
;
189 const FontSelectPattern aOut
= GetFcSubstitute( rFontSelData
, aDummy
);
191 if( !aOut
.maSearchName
.Len() )
194 const bool bHaveSubstitute
= !uselessmatch( rFontSelData
, aOut
);
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" );
207 printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName
.getStr(),
208 aOut
.meWeight
, aOut
.meItalic
, aOut
.mePitch
, aOut
.meWidthType
);
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();
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() )
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) )
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() )
245 const bool bHaveSubstitute
= !uselessmatch( rFontSelData
, aOut
);
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" );
258 printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName
.getStr(),
259 aOut
.meWeight
, aOut
.meItalic
, aOut
.mePitch
, aOut
.meWidthType
);
262 if( bHaveSubstitute
)
265 return bHaveSubstitute
;
268 // ===========================================================================
271 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */