Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "generic/geninst.h"
30 : : #include "generic/genpspgraphics.h"
31 : : #include "generic/glyphcache.hxx"
32 : :
33 : : #include "vcl/sysdata.hxx"
34 : : #include "outfont.hxx"
35 : :
36 : : #include "generic/printergfx.hxx"
37 : : #include "salbmp.hxx"
38 : : #include "impfont.hxx"
39 : : #include "outfont.hxx"
40 : : #include "outdev.h"
41 : : #include "fontsubset.hxx"
42 : : #include "salprn.hxx"
43 : : #include "region.h"
44 : :
45 : : #include <list>
46 : :
47 : : // ===========================================================================
48 : : // platform specific font substitution hooks
49 : : // ===========================================================================
50 : :
51 : : struct FontSelectPatternAttributesHash
52 : : {
53 : : size_t operator()(const FontSelectPatternAttributes& rAttributes) const
54 : : { return rAttributes.hashCode(); }
55 : : };
56 : :
57 [ - + ][ + - ]: 472 : class FcPreMatchSubstititution
58 : : : public ImplPreMatchFontSubstitution
59 : : {
60 : : public:
61 : : bool FindFontSubstitute( FontSelectPattern& ) const;
62 : : typedef ::std::pair<FontSelectPatternAttributes, FontSelectPatternAttributes> value_type;
63 : : private:
64 : : typedef ::std::list<value_type> CachedFontMapType;
65 : : mutable CachedFontMapType maCachedFontMap;
66 : : };
67 : :
68 [ - + ]: 236 : class FcGlyphFallbackSubstititution
69 : : : public ImplGlyphFallbackFontSubstitution
70 : : {
71 : : // TODO: add a cache
72 : : public:
73 : : bool FindFontSubstitute( FontSelectPattern&, rtl::OUString& rMissingCodes ) const;
74 : : };
75 : :
76 : 233 : int SalGenericInstance::FetchFontSubstitutionFlags()
77 : : {
78 : : // init font substitution defaults
79 : 233 : int nDisableBits = 0;
80 : : #ifdef SOLARIS
81 : : nDisableBits = 1; // disable "font fallback" here on default
82 : : #endif
83 : : // apply the environment variable if any
84 : 233 : const char* pEnvStr = ::getenv( "SAL_DISABLE_FC_SUBST" );
85 [ - + ]: 233 : if( pEnvStr )
86 : : {
87 [ # # ][ # # ]: 0 : if( (*pEnvStr >= '0') && (*pEnvStr <= '9') )
88 : 0 : nDisableBits = (*pEnvStr - '0');
89 : : else
90 : 0 : nDisableBits = ~0U; // no specific bits set: disable all
91 : : }
92 : 233 : return nDisableBits;
93 : : }
94 : :
95 : 359 : void SalGenericInstance::RegisterFontSubstitutors( ImplDevFontList* pList )
96 : : {
97 : : // init font substitution defaults
98 : 359 : int nDisableBits = 0;
99 : : #ifdef SOLARIS
100 : : nDisableBits = 1; // disable "font fallback" here on default
101 : : #endif
102 : : // apply the environment variable if any
103 : 359 : const char* pEnvStr = ::getenv( "SAL_DISABLE_FC_SUBST" );
104 [ - + ]: 359 : if( pEnvStr )
105 : : {
106 [ # # ][ # # ]: 0 : if( (*pEnvStr >= '0') && (*pEnvStr <= '9') )
107 : 0 : nDisableBits = (*pEnvStr - '0');
108 : : else
109 : 0 : nDisableBits = ~0U; // no specific bits set: disable all
110 : : }
111 : :
112 : : // register font fallback substitutions (unless disabled by bit0)
113 [ + - ]: 359 : if( (nDisableBits & 1) == 0 )
114 : : {
115 [ + + ][ + - ]: 359 : static FcPreMatchSubstititution aSubstPreMatch;
[ + - ][ # # ]
116 : 359 : pList->SetPreMatchHook( &aSubstPreMatch );
117 : : }
118 : :
119 : : // register glyph fallback substitutions (unless disabled by bit1)
120 [ + - ]: 359 : if( (nDisableBits & 2) == 0 )
121 : : {
122 [ + + ][ + - ]: 359 : static FcGlyphFallbackSubstititution aSubstFallback;
123 : 359 : pList->SetFallbackHook( &aSubstFallback );
124 : : }
125 : 359 : }
126 : :
127 : : // -----------------------------------------------------------------------
128 : :
129 : 8749 : static FontSelectPattern GetFcSubstitute(const FontSelectPattern &rFontSelData, rtl::OUString& rMissingCodes )
130 : : {
131 : 8749 : FontSelectPattern aSubstituted(rFontSelData);
132 [ + - ]: 8749 : psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
133 [ + - ]: 8749 : rMgr.Substitute(aSubstituted, rMissingCodes);
134 : 8749 : return aSubstituted;
135 : : }
136 : :
137 : : namespace
138 : : {
139 : 8749 : bool uselessmatch(const FontSelectPattern &rOrig, const FontSelectPattern &rNew)
140 : : {
141 : : return
142 : : (
143 : 8749 : rOrig.maTargetName == rNew.maSearchName &&
144 : : rOrig.meWeight == rNew.meWeight &&
145 : : rOrig.meItalic == rNew.meItalic &&
146 : : rOrig.mePitch == rNew.mePitch &&
147 : : rOrig.meWidthType == rNew.meWidthType
148 [ # # ][ # # ]: 8749 : );
[ # # ][ # # ]
[ - + ]
149 : : }
150 : :
151 : : class equal
152 : : {
153 : : private:
154 : : const FontSelectPatternAttributes& mrAttributes;
155 : : public:
156 : 96351 : equal(const FontSelectPatternAttributes& rAttributes)
157 : 96351 : : mrAttributes(rAttributes)
158 : : {
159 : 96351 : }
160 : 188552 : bool operator()(const FcPreMatchSubstititution::value_type& rOther) const
161 : 188552 : { return rOther.first == mrAttributes; }
162 : : };
163 : : }
164 : :
165 : : //--------------------------------------------------------------------------
166 : :
167 : 133615 : bool FcPreMatchSubstititution::FindFontSubstitute( FontSelectPattern &rFontSelData ) const
168 : : {
169 : : // We dont' actually want to talk to Fontconfig at all for symbol fonts
170 [ + + ]: 133615 : if( rFontSelData.IsSymbolFont() )
171 : 48 : return false;
172 : : // StarSymbol is a unicode font, but it still deserves the symbol flag
173 [ + - ][ + + ]: 261070 : if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10)
[ + + ][ + + ]
174 [ + - ]: 127503 : || 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) )
175 : 37216 : return false;
176 : :
177 : : //see fdo#41556 and fdo#47636
178 : : //fontconfig can return e.g. an italic font for a non-italic input and/or
179 : : //different fonts depending on fontsize, bold, etc settings so don't cache
180 : : //just on the name, cache map all the input and all the output not just map
181 : : //from original selection to output fontname
182 : 96351 : FontSelectPatternAttributes& rPatternAttributes = rFontSelData;
183 : 96351 : CachedFontMapType &rCachedFontMap = const_cast<CachedFontMapType &>(maCachedFontMap);
184 [ + - ]: 96351 : CachedFontMapType::iterator itr = std::find_if(rCachedFontMap.begin(), rCachedFontMap.end(), equal(rPatternAttributes));
185 [ + + ]: 96351 : if (itr != rCachedFontMap.end())
186 : : {
187 : : // Cached substitution
188 [ + - ]: 91172 : rFontSelData.copyAttributes(itr->second);
189 [ + + ]: 91172 : if (itr != rCachedFontMap.begin())
190 : : {
191 : : // MRU, move it to the front
192 [ + - ]: 36244 : rCachedFontMap.splice(rCachedFontMap.begin(), rCachedFontMap, itr);
193 : : }
194 : 91172 : return true;
195 : : }
196 : :
197 : 5179 : rtl::OUString aDummy;
198 [ + - ]: 5179 : const FontSelectPattern aOut = GetFcSubstitute( rFontSelData, aDummy );
199 : :
200 [ - + ]: 5179 : if( !aOut.maSearchName.Len() )
201 : 0 : return false;
202 : :
203 [ + - ]: 5179 : const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut );
204 : :
205 : : #ifdef DEBUG
206 : : const rtl::OString aOrigName(rtl::OUStringToOString(rFontSelData.maTargetName,
207 : : RTL_TEXTENCODING_UTF8));
208 : : const rtl::OString aSubstName(rtl::OUStringToOString(aOut.maSearchName,
209 : : RTL_TEXTENCODING_UTF8));
210 : : printf( "FcPreMatchSubstititution \"%s\" bipw=%d%d%d%d -> ",
211 : : aOrigName.getStr(), rFontSelData.meWeight, rFontSelData.meItalic,
212 : : rFontSelData.mePitch, rFontSelData.meWidthType );
213 : : if( !bHaveSubstitute )
214 : : printf( "no substitute available\n" );
215 : : else
216 : : printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.getStr(),
217 : : aOut.meWeight, aOut.meItalic, aOut.mePitch, aOut.meWidthType );
218 : : #endif
219 : :
220 [ + - ]: 5179 : if( bHaveSubstitute )
221 : : {
222 [ + - ][ + - ]: 5179 : rCachedFontMap.push_front(value_type(rFontSelData, aOut));
[ + - ]
223 : : //fairly arbitrary limit in this case, but I recall measuring max 8
224 : : //fonts as the typical max amount of fonts in medium sized documents
225 [ + + ]: 5179 : if (rCachedFontMap.size() > 8)
226 [ + - ]: 4000 : rCachedFontMap.pop_back();
227 [ + - ]: 5179 : rFontSelData = aOut;
228 : : }
229 : :
230 [ + - ]: 133615 : return bHaveSubstitute;
231 : : }
232 : :
233 : : // -----------------------------------------------------------------------
234 : :
235 : 3570 : bool FcGlyphFallbackSubstititution::FindFontSubstitute( FontSelectPattern& rFontSelData,
236 : : rtl::OUString& rMissingCodes ) const
237 : : {
238 : : // We dont' actually want to talk to Fontconfig at all for symbol fonts
239 [ - + ]: 3570 : if( rFontSelData.IsSymbolFont() )
240 : 0 : return false;
241 : : // StarSymbol is a unicode font, but it still deserves the symbol flag
242 [ + - ][ + - ]: 7140 : if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10)
[ - + ][ - + ]
243 [ + - ]: 3570 : || 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) )
244 : 0 : return false;
245 : :
246 [ + - ]: 3570 : const FontSelectPattern aOut = GetFcSubstitute( rFontSelData, rMissingCodes );
247 : : // TODO: cache the unicode + srcfont specific result
248 : : // FC doing it would be preferable because it knows the invariables
249 : : // e.g. FC knows the FC rule that all Arial gets replaced by LiberationSans
250 : : // whereas we would have to check for every size or attribute
251 [ - + ]: 3570 : if( !aOut.maSearchName.Len() )
252 : 0 : return false;
253 : :
254 [ + - ]: 3570 : const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut );
255 : :
256 : : #ifdef DEBUG
257 : : const rtl::OString aOrigName(rtl::OUStringToOString(rFontSelData.maTargetName,
258 : : RTL_TEXTENCODING_UTF8));
259 : : const rtl::OString aSubstName(rtl::OUStringToOString(aOut.maSearchName,
260 : : RTL_TEXTENCODING_UTF8));
261 : : printf( "FcGFSubstititution \"%s\" bipw=%d%d%d%d ->",
262 : : aOrigName.getStr(), rFontSelData.meWeight, rFontSelData.meItalic,
263 : : rFontSelData.mePitch, rFontSelData.meWidthType );
264 : : if( !bHaveSubstitute )
265 : : printf( "no substitute available\n" );
266 : : else
267 : : printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.getStr(),
268 : : aOut.meWeight, aOut.meItalic, aOut.mePitch, aOut.meWidthType );
269 : : #endif
270 : :
271 [ + - ]: 3570 : if( bHaveSubstitute )
272 [ + - ]: 3570 : rFontSelData = aOut;
273 : :
274 [ + - ]: 3570 : return bHaveSubstitute;
275 : : }
276 : :
277 : : // ===========================================================================
278 : :
279 : :
280 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|