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"
31 #include "PhysicalFontCollection.hxx"
32 #include "fontsubset.hxx"
35 #include <unotools/fontdefs.hxx>
38 // platform specific font substitution hooks
40 class FcPreMatchSubstititution
41 : public ImplPreMatchFontSubstitution
44 bool FindFontSubstitute( FontSelectPattern
& ) const SAL_OVERRIDE
;
45 typedef ::std::pair
<FontSelectPatternAttributes
, FontSelectPatternAttributes
> value_type
;
47 typedef ::std::list
<value_type
> CachedFontMapType
;
48 mutable CachedFontMapType maCachedFontMap
;
51 class FcGlyphFallbackSubstititution
52 : public ImplGlyphFallbackFontSubstitution
56 bool FindFontSubstitute( FontSelectPattern
&, OUString
& rMissingCodes
) const SAL_OVERRIDE
;
59 int SalGenericInstance::FetchFontSubstitutionFlags()
61 // init font substitution defaults
64 nDisableBits
= 1; // disable "font fallback" here on default
66 // apply the environment variable if any
67 const char* pEnvStr
= ::getenv( "SAL_DISABLE_FC_SUBST" );
70 if( (*pEnvStr
>= '0') && (*pEnvStr
<= '9') )
71 nDisableBits
= (*pEnvStr
- '0');
73 nDisableBits
= ~0U; // no specific bits set: disable all
78 void SalGenericInstance::RegisterFontSubstitutors( PhysicalFontCollection
* pFontCollection
)
80 // init font substitution defaults
83 nDisableBits
= 1; // disable "font fallback" here on default
85 // apply the environment variable if any
86 const char* pEnvStr
= ::getenv( "SAL_DISABLE_FC_SUBST" );
89 if( (*pEnvStr
>= '0') && (*pEnvStr
<= '9') )
90 nDisableBits
= (*pEnvStr
- '0');
92 nDisableBits
= ~0U; // no specific bits set: disable all
95 // register font fallback substitutions (unless disabled by bit0)
96 if( (nDisableBits
& 1) == 0 )
98 static FcPreMatchSubstititution aSubstPreMatch
;
99 pFontCollection
->SetPreMatchHook( &aSubstPreMatch
);
102 // register glyph fallback substitutions (unless disabled by bit1)
103 if( (nDisableBits
& 2) == 0 )
105 static FcGlyphFallbackSubstititution aSubstFallback
;
106 pFontCollection
->SetFallbackHook( &aSubstFallback
);
110 static FontSelectPattern
GetFcSubstitute(const FontSelectPattern
&rFontSelData
, OUString
& rMissingCodes
)
112 FontSelectPattern
aSubstituted(rFontSelData
);
113 psp::PrintFontManager
& rMgr
= psp::PrintFontManager::get();
114 rMgr
.Substitute(aSubstituted
, rMissingCodes
);
120 bool uselessmatch(const FontSelectPattern
&rOrig
, const FontSelectPattern
&rNew
)
124 rOrig
.maTargetName
== rNew
.maSearchName
&&
125 rOrig
.GetWeight() == rNew
.GetWeight() &&
126 rOrig
.GetSlant() == rNew
.GetSlant() &&
127 rOrig
.GetPitch() == rNew
.GetPitch() &&
128 rOrig
.GetWidthType() == rNew
.GetWidthType()
135 const FontSelectPatternAttributes
& mrAttributes
;
137 equal(const FontSelectPatternAttributes
& rAttributes
)
138 : mrAttributes(rAttributes
)
141 bool operator()(const FcPreMatchSubstititution::value_type
& rOther
) const
142 { return rOther
.first
== mrAttributes
; }
146 bool FcPreMatchSubstititution::FindFontSubstitute( FontSelectPattern
&rFontSelData
) const
148 // We don't actually want to talk to Fontconfig at all for symbol fonts
149 if( rFontSelData
.IsSymbolFont() )
151 // StarSymbol is a unicode font, but it still deserves the symbol flag
152 if ( IsStarSymbol(rFontSelData
.maSearchName
) )
155 //see fdo#41556 and fdo#47636
156 //fontconfig can return e.g. an italic font for a non-italic input and/or
157 //different fonts depending on fontsize, bold, etc settings so don't cache
158 //just on the name, cache map all the input and all the output not just map
159 //from original selection to output fontname
160 FontSelectPatternAttributes
& rPatternAttributes
= rFontSelData
;
161 CachedFontMapType
&rCachedFontMap
= const_cast<CachedFontMapType
&>(maCachedFontMap
);
162 CachedFontMapType::iterator itr
= std::find_if(rCachedFontMap
.begin(), rCachedFontMap
.end(), equal(rPatternAttributes
));
163 if (itr
!= rCachedFontMap
.end())
165 // Cached substitution
166 rFontSelData
.copyAttributes(itr
->second
);
167 if (itr
!= rCachedFontMap
.begin())
169 // MRU, move it to the front
170 rCachedFontMap
.splice(rCachedFontMap
.begin(), rCachedFontMap
, itr
);
176 const FontSelectPattern aOut
= GetFcSubstitute( rFontSelData
, aDummy
);
178 if( aOut
.maSearchName
.isEmpty() )
181 const bool bHaveSubstitute
= !uselessmatch( rFontSelData
, aOut
);
184 const OString
aOrigName(OUStringToOString(rFontSelData
.maTargetName
,
185 RTL_TEXTENCODING_UTF8
));
186 const OString
aSubstName(OUStringToOString(aOut
.maSearchName
,
187 RTL_TEXTENCODING_UTF8
));
188 printf( "FcPreMatchSubstititution \"%s\" bipw=%d%d%d%d -> ",
189 aOrigName
.getStr(), rFontSelData
.GetWeight(), rFontSelData
.GetSlant(),
190 rFontSelData
.GetPitch(), rFontSelData
.GetWidthType() );
191 if( !bHaveSubstitute
)
192 printf( "no substitute available\n" );
194 printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName
.getStr(),
195 aOut
.GetWeight(), aOut
.GetSlant(), aOut
.GetPitch(), aOut
.GetWidthType() );
198 if( bHaveSubstitute
)
200 rCachedFontMap
.push_front(value_type(rFontSelData
, aOut
));
201 //fairly arbitrary limit in this case, but I recall measuring max 8
202 //fonts as the typical max amount of fonts in medium sized documents
203 if (rCachedFontMap
.size() > 8)
204 rCachedFontMap
.pop_back();
208 return bHaveSubstitute
;
211 bool FcGlyphFallbackSubstititution::FindFontSubstitute( FontSelectPattern
& rFontSelData
,
212 OUString
& rMissingCodes
) const
214 // We don't actually want to talk to Fontconfig at all for symbol fonts
215 if( rFontSelData
.IsSymbolFont() )
217 // StarSymbol is a unicode font, but it still deserves the symbol flag
218 if ( IsStarSymbol(rFontSelData
.maSearchName
) )
221 const FontSelectPattern aOut
= GetFcSubstitute( rFontSelData
, rMissingCodes
);
222 // TODO: cache the unicode + srcfont specific result
223 // FC doing it would be preferable because it knows the invariables
224 // e.g. FC knows the FC rule that all Arial gets replaced by LiberationSans
225 // whereas we would have to check for every size or attribute
226 if( aOut
.maSearchName
.isEmpty() )
229 const bool bHaveSubstitute
= !uselessmatch( rFontSelData
, aOut
);
232 const OString
aOrigName(OUStringToOString(rFontSelData
.maTargetName
,
233 RTL_TEXTENCODING_UTF8
));
234 const OString
aSubstName(OUStringToOString(aOut
.maSearchName
,
235 RTL_TEXTENCODING_UTF8
));
236 printf( "FcGFSubstititution \"%s\" bipw=%d%d%d%d ->",
237 aOrigName
.getStr(), rFontSelData
.GetWeight(), rFontSelData
.GetSlant(),
238 rFontSelData
.GetPitch(), rFontSelData
.GetWidthType() );
239 if( !bHaveSubstitute
)
240 printf( "no substitute available\n" );
242 printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName
.getStr(),
243 aOut
.GetWeight(), aOut
.GetSlant(), aOut
.GetPitch(), aOut
.GetWidthType() );
246 if( bHaveSubstitute
)
249 return bHaveSubstitute
;
252 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */