/src/libreoffice/vcl/unx/generic/fontmanager/fontmanager.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
20 | | #include <memory> |
21 | | #include <osl/thread.h> |
22 | | |
23 | | #include <unx/fontmanager.hxx> |
24 | | #include <impfontcharmap.hxx> |
25 | | #include <unotools/syslocaleoptions.hxx> |
26 | | #include <unx/gendata.hxx> |
27 | | #include <unx/helper.hxx> |
28 | | #include <vcl/fontcharmap.hxx> |
29 | | |
30 | | #include <tools/urlobj.hxx> |
31 | | #include <tools/UnixWrappers.h> |
32 | | |
33 | | #include <o3tl/string_view.hxx> |
34 | | #include <osl/file.hxx> |
35 | | |
36 | | #include <rtl/ustrbuf.hxx> |
37 | | #include <rtl/strbuf.hxx> |
38 | | |
39 | | #include <sal/macros.h> |
40 | | #include <sal/log.hxx> |
41 | | |
42 | | #include <i18nlangtag/applelangid.hxx> |
43 | | |
44 | | #include <sft.hxx> |
45 | | |
46 | | #if OSL_DEBUG_LEVEL > 1 |
47 | | #include <sys/times.h> |
48 | | #include <stdio.h> |
49 | | #endif |
50 | | |
51 | | #include <algorithm> |
52 | | #include <set> |
53 | | |
54 | | #ifdef CALLGRIND_COMPILE |
55 | | #include <valgrind/callgrind.h> |
56 | | #endif |
57 | | |
58 | | #include <com/sun/star/beans/XMaterialHolder.hpp> |
59 | | |
60 | | using namespace vcl; |
61 | | using namespace psp; |
62 | | using namespace com::sun::star::uno; |
63 | | using namespace com::sun::star::lang; |
64 | | |
65 | | /* |
66 | | * PrintFont implementations |
67 | | */ |
68 | | PrintFontManager::PrintFont::PrintFont() |
69 | 1.27k | : m_nDirectory(0) |
70 | 1.27k | , m_nCollectionEntry(0) |
71 | 1.27k | , m_nVariationEntry(0) |
72 | 1.27k | { |
73 | 1.27k | } |
74 | | |
75 | | /* |
76 | | * one instance only |
77 | | */ |
78 | | PrintFontManager& PrintFontManager::get() |
79 | 145 | { |
80 | 145 | GenericUnixSalData* const pSalData(GetGenericUnixSalData()); |
81 | 145 | assert(pSalData); |
82 | 145 | return *pSalData->GetPrintFontManager(); |
83 | 145 | } |
84 | | |
85 | | /* |
86 | | * the PrintFontManager |
87 | | */ |
88 | | |
89 | | PrintFontManager::PrintFontManager() |
90 | 106 | : m_nNextFontID( 1 ) |
91 | 106 | , m_nNextDirAtom( 1 ) |
92 | 106 | , m_aFontInstallerTimer("PrintFontManager m_aFontInstallerTimer") |
93 | 106 | { |
94 | 106 | m_aFontInstallerTimer.SetInvokeHandler(LINK(this, PrintFontManager, autoInstallFontLangSupport)); |
95 | 106 | m_aFontInstallerTimer.SetTimeout(5000); |
96 | | |
97 | | #ifdef CALLGRIND_COMPILE |
98 | | CALLGRIND_TOGGLE_COLLECT(); |
99 | | CALLGRIND_ZERO_STATS(); |
100 | | #endif |
101 | | |
102 | | #if OSL_DEBUG_LEVEL > 1 |
103 | | clock_t aStart; |
104 | | clock_t aStep1; |
105 | | clock_t aStep2; |
106 | | |
107 | | struct tms tms; |
108 | | |
109 | | aStart = times(&tms); |
110 | | #endif |
111 | | |
112 | | // first try fontconfig |
113 | 106 | initFontconfig(); |
114 | | |
115 | | // part one - look for downloadable fonts |
116 | 106 | rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); |
117 | 106 | const OUString& rSalPrivatePath = psp::getFontPath(); |
118 | | |
119 | | // search for the fonts in SAL_PRIVATE_FONTPATH first; those are |
120 | | // the fonts installed with the office |
121 | 106 | if (!rSalPrivatePath.isEmpty()) |
122 | 106 | { |
123 | 106 | OString aPath = OUStringToOString(rSalPrivatePath, aEncoding); |
124 | 106 | sal_Int32 nIndex = 0; |
125 | 106 | do |
126 | 318 | { |
127 | 318 | OString aToken = aPath.getToken(0, ';', nIndex); |
128 | 318 | normPath(aToken); |
129 | 318 | if (!aToken.isEmpty()) |
130 | 212 | addFontconfigDir(aToken); |
131 | 318 | } while (nIndex >= 0); |
132 | 106 | } |
133 | | |
134 | 106 | countFontconfigFonts(); |
135 | | |
136 | | #if OSL_DEBUG_LEVEL > 1 |
137 | | aStep1 = times(&tms); |
138 | | |
139 | | aStep2 = times(&tms); |
140 | | SAL_INFO("vcl.fonts", |
141 | | "PrintFontManager::PrintFontManager: collected " << m_aFonts.size() << " fonts."); |
142 | | double fTick = (double)sysconf(_SC_CLK_TCK); |
143 | | SAL_INFO("vcl.fonts", "Step 1 took " << ((double)(aStep1 - aStart) / fTick) << " seconds."); |
144 | | SAL_INFO("vcl.fonts", "Step 2 took " << ((double)(aStep2 - aStep1) / fTick) << " seconds."); |
145 | | #endif |
146 | | |
147 | | #ifdef CALLGRIND_COMPILE |
148 | | CALLGRIND_DUMP_STATS(); |
149 | | CALLGRIND_TOGGLE_COLLECT(); |
150 | | #endif |
151 | 106 | } |
152 | | |
153 | | PrintFontManager::~PrintFontManager() |
154 | 0 | { |
155 | 0 | m_aFontInstallerTimer.Stop(); |
156 | 0 | deinitFontconfig(); |
157 | 0 | } |
158 | | |
159 | | OString PrintFontManager::getDirectory( int nAtom ) const |
160 | 0 | { |
161 | 0 | std::unordered_map< int, OString >::const_iterator it( m_aAtomToDir.find( nAtom ) ); |
162 | 0 | return it != m_aAtomToDir.end() ? it->second : OString(); |
163 | 0 | } |
164 | | |
165 | | int PrintFontManager::getDirectoryAtom( const OString& rDirectory ) |
166 | 1.27k | { |
167 | 1.27k | int nAtom = 0; |
168 | 1.27k | std::unordered_map< OString, int >::const_iterator it |
169 | 1.27k | ( m_aDirToAtom.find( rDirectory ) ); |
170 | 1.27k | if( it != m_aDirToAtom.end() ) |
171 | 1.16k | nAtom = it->second; |
172 | 106 | else |
173 | 106 | { |
174 | 106 | nAtom = m_nNextDirAtom++; |
175 | 106 | m_aDirToAtom[ rDirectory ] = nAtom; |
176 | 106 | m_aAtomToDir[ nAtom ] = rDirectory; |
177 | 106 | } |
178 | 1.27k | return nAtom; |
179 | 1.27k | } |
180 | | |
181 | | std::vector<fontID> PrintFontManager::findFontFileIDs( std::u16string_view rFileUrl ) const |
182 | 0 | { |
183 | 0 | rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); |
184 | 0 | INetURLObject aPath( rFileUrl ); |
185 | 0 | OString aName(OUStringToOString(aPath.GetLastName(INetURLObject::DecodeMechanism::WithCharset, aEncoding), aEncoding)); |
186 | 0 | OString aDir( OUStringToOString( |
187 | 0 | INetURLObject::decode( aPath.GetPath(), INetURLObject::DecodeMechanism::WithCharset, aEncoding ), aEncoding ) ); |
188 | |
|
189 | 0 | auto dirIt = m_aDirToAtom.find(aDir); |
190 | 0 | if (dirIt == m_aDirToAtom.end()) |
191 | 0 | return {}; |
192 | | |
193 | 0 | return findFontFileIDs(dirIt->second, aName); |
194 | 0 | } |
195 | | |
196 | | std::vector<fontID> PrintFontManager::addFontFile( std::u16string_view rFileUrl ) |
197 | 0 | { |
198 | 0 | rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); |
199 | 0 | INetURLObject aPath( rFileUrl ); |
200 | 0 | OString aName(OUStringToOString(aPath.GetLastName(INetURLObject::DecodeMechanism::WithCharset, aEncoding), aEncoding)); |
201 | 0 | OString aDir( OUStringToOString( |
202 | 0 | INetURLObject::decode( aPath.GetPath(), INetURLObject::DecodeMechanism::WithCharset, aEncoding ), aEncoding ) ); |
203 | |
|
204 | 0 | int nDirID = getDirectoryAtom( aDir ); |
205 | 0 | std::vector<fontID> aFontIds = findFontFileIDs( nDirID, aName ); |
206 | 0 | if( aFontIds.empty() ) |
207 | 0 | { |
208 | 0 | addFontconfigFile(OUStringToOString(aPath.GetFull(), osl_getThreadTextEncoding())); |
209 | |
|
210 | 0 | std::vector<PrintFont> aNewFonts = analyzeFontFile(nDirID, aName); |
211 | 0 | for (auto & font : aNewFonts) |
212 | 0 | { |
213 | 0 | fontID nFontId = m_nNextFontID++; |
214 | 0 | m_aFonts[nFontId] = std::move(font); |
215 | 0 | m_aFontFileToFontID[ aName ].insert( nFontId ); |
216 | 0 | aFontIds.push_back(nFontId); |
217 | 0 | } |
218 | 0 | } |
219 | 0 | return aFontIds; |
220 | 0 | } |
221 | | |
222 | | void PrintFontManager::removeFontFile(std::u16string_view rFileUrl) |
223 | 0 | { |
224 | 0 | INetURLObject aPath(rFileUrl); |
225 | 0 | rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); |
226 | 0 | if (auto ids = findFontFileIDs(rFileUrl); !ids.empty()) |
227 | 0 | { |
228 | 0 | OString aName(OUStringToOString( |
229 | 0 | aPath.GetLastName(INetURLObject::DecodeMechanism::WithCharset, aEncoding), aEncoding)); |
230 | |
|
231 | 0 | for (auto nFontID : ids) |
232 | 0 | { |
233 | 0 | m_aFonts.erase(nFontID); |
234 | 0 | m_aFontFileToFontID[aName].erase(nFontID); |
235 | 0 | } |
236 | 0 | } |
237 | |
|
238 | 0 | removeFontconfigFile(OUStringToOString(aPath.GetFull(), aEncoding)); |
239 | 0 | } |
240 | | |
241 | | std::vector<PrintFontManager::PrintFont> PrintFontManager::analyzeFontFile( int nDirID, const OString& rFontFile) const |
242 | 0 | { |
243 | 0 | std::vector<PrintFontManager::PrintFont> aNewFonts; |
244 | |
|
245 | 0 | OString aDir( getDirectory( nDirID ) ); |
246 | |
|
247 | 0 | OString aFullPath = aDir + "/" + rFontFile; |
248 | |
|
249 | 0 | bool bSupported; |
250 | 0 | int nFD; |
251 | 0 | int n; |
252 | 0 | if (sscanf(aFullPath.getStr(), "/:FD:/%d%n", &nFD, &n) == 1 && aFullPath.getStr()[n] == '\0') |
253 | 0 | { |
254 | | // Hack, pathname that actually means we will use a pre-opened file descriptor |
255 | 0 | bSupported = true; |
256 | 0 | } |
257 | 0 | else |
258 | 0 | { |
259 | | // #i1872# reject unreadable files |
260 | 0 | if( wrap_access( aFullPath.getStr(), R_OK ) ) |
261 | 0 | return aNewFonts; |
262 | | |
263 | 0 | bSupported = false; |
264 | 0 | OString aExt( rFontFile.copy( rFontFile.lastIndexOf( '.' )+1 ) ); |
265 | 0 | if( aExt.equalsIgnoreAsciiCase("ttf") |
266 | 0 | || aExt.equalsIgnoreAsciiCase("ttc") |
267 | 0 | || aExt.equalsIgnoreAsciiCase("tte") // #i33947# for Gaiji support |
268 | 0 | || aExt.equalsIgnoreAsciiCase("otf") ) // check for TTF- and PS-OpenType too |
269 | 0 | bSupported = true; |
270 | 0 | } |
271 | | |
272 | 0 | if (bSupported) |
273 | 0 | { |
274 | | // get number of ttc entries |
275 | 0 | int nLength = CountTTCFonts( aFullPath.getStr() ); |
276 | 0 | if (nLength > 0) |
277 | 0 | { |
278 | 0 | SAL_INFO("vcl.fonts", "ttc: " << aFullPath << " contains " << nLength << " fonts"); |
279 | | |
280 | 0 | for( int i = 0; i < nLength; i++ ) |
281 | 0 | { |
282 | 0 | PrintFont aFont; |
283 | 0 | aFont.m_nDirectory = nDirID; |
284 | 0 | aFont.m_aFontFile = rFontFile; |
285 | 0 | aFont.m_nCollectionEntry = i; |
286 | 0 | if (analyzeSfntFile(aFont)) |
287 | 0 | aNewFonts.push_back(aFont); |
288 | 0 | } |
289 | 0 | } |
290 | 0 | else |
291 | 0 | { |
292 | 0 | PrintFont aFont; |
293 | 0 | aFont.m_nDirectory = nDirID; |
294 | 0 | aFont.m_aFontFile = rFontFile; |
295 | 0 | aFont.m_nCollectionEntry = 0; |
296 | | |
297 | | // need to read the font anyway to get aliases inside the font file |
298 | 0 | if (analyzeSfntFile(aFont)) |
299 | 0 | aNewFonts.push_back(aFont); |
300 | 0 | } |
301 | 0 | } |
302 | 0 | return aNewFonts; |
303 | 0 | } |
304 | | |
305 | | fontID PrintFontManager::findFontFileID(int nDirID, const OString& rFontFile, int nFaceIndex, int nVariationIndex) const |
306 | 0 | { |
307 | 0 | fontID nID = 0; |
308 | |
|
309 | 0 | auto set_it = m_aFontFileToFontID.find( rFontFile ); |
310 | 0 | if( set_it == m_aFontFileToFontID.end() ) |
311 | 0 | return nID; |
312 | | |
313 | 0 | for (fontID elem : set_it->second) |
314 | 0 | { |
315 | 0 | auto it = m_aFonts.find(elem); |
316 | 0 | if( it == m_aFonts.end() ) |
317 | 0 | continue; |
318 | 0 | const PrintFont& rFont = (*it).second; |
319 | 0 | if (rFont.m_nDirectory == nDirID && |
320 | 0 | rFont.m_aFontFile == rFontFile && |
321 | 0 | rFont.m_nCollectionEntry == nFaceIndex && |
322 | 0 | rFont.m_nVariationEntry == nVariationIndex) |
323 | 0 | { |
324 | 0 | nID = it->first; |
325 | 0 | if (nID) |
326 | 0 | break; |
327 | 0 | } |
328 | 0 | } |
329 | |
|
330 | 0 | return nID; |
331 | 0 | } |
332 | | |
333 | | std::vector<fontID> PrintFontManager::findFontFileIDs( int nDirID, const OString& rFontFile ) const |
334 | 0 | { |
335 | 0 | std::vector<fontID> aIds; |
336 | |
|
337 | 0 | auto set_it = m_aFontFileToFontID.find( rFontFile ); |
338 | 0 | if( set_it == m_aFontFileToFontID.end() ) |
339 | 0 | return aIds; |
340 | | |
341 | 0 | for (auto const& elem : set_it->second) |
342 | 0 | { |
343 | 0 | auto it = m_aFonts.find(elem); |
344 | 0 | if( it == m_aFonts.end() ) |
345 | 0 | continue; |
346 | 0 | const PrintFont& rFont = (*it).second; |
347 | 0 | if (rFont.m_nDirectory == nDirID && |
348 | 0 | rFont.m_aFontFile == rFontFile) |
349 | 0 | aIds.push_back(it->first); |
350 | 0 | } |
351 | |
|
352 | 0 | return aIds; |
353 | 0 | } |
354 | | |
355 | | namespace { |
356 | | |
357 | | OUString analyzeSfntFamilyName(void const * pTTFont) |
358 | 0 | { |
359 | 0 | return analyzeSfntName(static_cast<TrueTypeFont const *>(pTTFont), 1, SvtSysLocaleOptions().GetRealUILanguageTag()); |
360 | 0 | } |
361 | | |
362 | | } |
363 | | |
364 | | bool PrintFontManager::analyzeSfntFile( PrintFont& rFont ) const |
365 | 0 | { |
366 | 0 | bool bSuccess = false; |
367 | 0 | rtl_TextEncoding aEncoding = osl_getThreadTextEncoding(); |
368 | 0 | OString aFile = getFontFile( rFont ); |
369 | 0 | TrueTypeFont* pTTFont = nullptr; |
370 | |
|
371 | 0 | auto& rDFA = rFont.m_aFontAttributes; |
372 | 0 | rDFA.SetQuality(512); |
373 | |
|
374 | 0 | auto const e = OpenTTFontFile( aFile.getStr(), rFont.m_nCollectionEntry, &pTTFont ); |
375 | 0 | if( e == SFErrCodes::Ok ) |
376 | 0 | { |
377 | 0 | TTGlobalFontInfo aInfo; |
378 | 0 | GetTTGlobalFontInfo( pTTFont, & aInfo ); |
379 | |
|
380 | 0 | if (rDFA.GetFamilyName().isEmpty()) |
381 | 0 | { |
382 | 0 | OUString aFamily = analyzeSfntFamilyName(pTTFont); |
383 | 0 | if (aFamily.isEmpty()) |
384 | 0 | { |
385 | | // poor font does not have a family name |
386 | | // name it to file name minus the extension |
387 | 0 | sal_Int32 dotIndex = rFont.m_aFontFile.lastIndexOf('.'); |
388 | 0 | if ( dotIndex == -1 ) |
389 | 0 | dotIndex = rFont.m_aFontFile.getLength(); |
390 | 0 | aFamily = OStringToOUString(rFont.m_aFontFile.subView(0, dotIndex), aEncoding); |
391 | 0 | } |
392 | |
|
393 | 0 | rDFA.SetFamilyName(aFamily); |
394 | 0 | } |
395 | |
|
396 | 0 | if( !aInfo.usubfamily.isEmpty() ) |
397 | 0 | rDFA.SetStyleName(aInfo.usubfamily); |
398 | |
|
399 | 0 | rDFA.SetFamilyType(matchFamilyName(rDFA.GetFamilyName())); |
400 | |
|
401 | 0 | rDFA.SetWeight(AnalyzeTTFWeight(pTTFont)); |
402 | |
|
403 | 0 | switch( aInfo.width ) |
404 | 0 | { |
405 | 0 | case FWIDTH_ULTRA_CONDENSED: rDFA.SetWidthType(WIDTH_ULTRA_CONDENSED); break; |
406 | 0 | case FWIDTH_EXTRA_CONDENSED: rDFA.SetWidthType(WIDTH_EXTRA_CONDENSED); break; |
407 | 0 | case FWIDTH_CONDENSED: rDFA.SetWidthType(WIDTH_CONDENSED); break; |
408 | 0 | case FWIDTH_SEMI_CONDENSED: rDFA.SetWidthType(WIDTH_SEMI_CONDENSED); break; |
409 | 0 | case FWIDTH_SEMI_EXPANDED: rDFA.SetWidthType(WIDTH_SEMI_EXPANDED); break; |
410 | 0 | case FWIDTH_EXPANDED: rDFA.SetWidthType(WIDTH_EXPANDED); break; |
411 | 0 | case FWIDTH_EXTRA_EXPANDED: rDFA.SetWidthType(WIDTH_EXTRA_EXPANDED); break; |
412 | 0 | case FWIDTH_ULTRA_EXPANDED: rDFA.SetWidthType(WIDTH_ULTRA_EXPANDED); break; |
413 | | |
414 | 0 | case FWIDTH_NORMAL: |
415 | 0 | default: rDFA.SetWidthType(WIDTH_NORMAL); break; |
416 | 0 | } |
417 | | |
418 | 0 | rDFA.SetPitch(aInfo.pitch ? PITCH_FIXED : PITCH_VARIABLE); |
419 | 0 | rDFA.SetItalic(aInfo.italicAngle == 0 ? ITALIC_NONE : (aInfo.italicAngle < 0 ? ITALIC_NORMAL : ITALIC_OBLIQUE)); |
420 | | // #104264# there are fonts that set italic angle 0 although they are |
421 | | // italic; use macstyle bit here |
422 | 0 | if( aInfo.italicAngle == 0 && (aInfo.macStyle & 2) ) |
423 | 0 | rDFA.SetItalic(ITALIC_NORMAL); |
424 | |
|
425 | 0 | rDFA.SetMicrosoftSymbolEncoded(aInfo.microsoftSymbolEncoded); |
426 | |
|
427 | 0 | CloseTTFont( pTTFont ); |
428 | 0 | bSuccess = true; |
429 | 0 | } |
430 | 0 | else |
431 | 0 | SAL_WARN("vcl.fonts", "Could not OpenTTFont \"" << aFile << "\": " << int(e)); |
432 | | |
433 | 0 | return bSuccess; |
434 | 0 | } |
435 | | |
436 | | std::vector<fontID> PrintFontManager::getFontList() |
437 | 39 | { |
438 | 39 | std::vector<fontID> aFontIDs; |
439 | 39 | for (auto const& font : m_aFonts) |
440 | 468 | aFontIDs.push_back(font.first); |
441 | | |
442 | 39 | return aFontIDs; |
443 | 39 | } |
444 | | |
445 | | int PrintFontManager::getFontFaceNumber( fontID nFontID ) const |
446 | 468 | { |
447 | 468 | int nRet = 0; |
448 | 468 | const PrintFont* pFont = getFont( nFontID ); |
449 | 468 | if (pFont) |
450 | 468 | { |
451 | 468 | nRet = pFont->m_nCollectionEntry; |
452 | 468 | if (nRet < 0) |
453 | 0 | nRet = 0; |
454 | 468 | } |
455 | 468 | return nRet; |
456 | 468 | } |
457 | | |
458 | | int PrintFontManager::getFontFaceVariation( fontID nFontID ) const |
459 | 468 | { |
460 | 468 | int nRet = 0; |
461 | 468 | const PrintFont* pFont = getFont( nFontID ); |
462 | 468 | if (pFont) |
463 | 468 | { |
464 | 468 | nRet = pFont->m_nVariationEntry; |
465 | 468 | if (nRet < 0) |
466 | 0 | nRet = 0; |
467 | 468 | } |
468 | 468 | return nRet; |
469 | 468 | } |
470 | | |
471 | | FontFamily PrintFontManager::matchFamilyName( std::u16string_view rFamily ) |
472 | 0 | { |
473 | 0 | struct family_t { |
474 | 0 | const char* mpName; |
475 | 0 | sal_uInt16 mnLength; |
476 | 0 | FontFamily meType; |
477 | 0 | }; |
478 | |
|
479 | 0 | #define InitializeClass( p, a ) p, sizeof(p) - 1, a |
480 | 0 | static const family_t pFamilyMatch[] = { |
481 | 0 | { InitializeClass( "arial", FAMILY_SWISS ) }, |
482 | 0 | { InitializeClass( "arioso", FAMILY_SCRIPT ) }, |
483 | 0 | { InitializeClass( "avant garde", FAMILY_SWISS ) }, |
484 | 0 | { InitializeClass( "avantgarde", FAMILY_SWISS ) }, |
485 | 0 | { InitializeClass( "bembo", FAMILY_ROMAN ) }, |
486 | 0 | { InitializeClass( "bookman", FAMILY_ROMAN ) }, |
487 | 0 | { InitializeClass( "conga", FAMILY_ROMAN ) }, |
488 | 0 | { InitializeClass( "courier", FAMILY_MODERN ) }, |
489 | 0 | { InitializeClass( "curl", FAMILY_SCRIPT ) }, |
490 | 0 | { InitializeClass( "fixed", FAMILY_MODERN ) }, |
491 | 0 | { InitializeClass( "gill", FAMILY_SWISS ) }, |
492 | 0 | { InitializeClass( "helmet", FAMILY_MODERN ) }, |
493 | 0 | { InitializeClass( "helvetica", FAMILY_SWISS ) }, |
494 | 0 | { InitializeClass( "international", FAMILY_MODERN ) }, |
495 | 0 | { InitializeClass( "lucida", FAMILY_SWISS ) }, |
496 | 0 | { InitializeClass( "new century schoolbook", FAMILY_ROMAN ) }, |
497 | 0 | { InitializeClass( "palatino", FAMILY_ROMAN ) }, |
498 | 0 | { InitializeClass( "roman", FAMILY_ROMAN ) }, |
499 | 0 | { InitializeClass( "sans serif", FAMILY_SWISS ) }, |
500 | 0 | { InitializeClass( "sansserif", FAMILY_SWISS ) }, |
501 | 0 | { InitializeClass( "serf", FAMILY_ROMAN ) }, |
502 | 0 | { InitializeClass( "serif", FAMILY_ROMAN ) }, |
503 | 0 | { InitializeClass( "times", FAMILY_ROMAN ) }, |
504 | 0 | { InitializeClass( "utopia", FAMILY_ROMAN ) }, |
505 | 0 | { InitializeClass( "zapf chancery", FAMILY_SCRIPT ) }, |
506 | 0 | { InitializeClass( "zapfchancery", FAMILY_SCRIPT ) } |
507 | 0 | }; |
508 | |
|
509 | 0 | OString aFamily = OUStringToOString( rFamily, RTL_TEXTENCODING_ASCII_US ); |
510 | 0 | sal_uInt32 nLower = 0; |
511 | 0 | sal_uInt32 nUpper = SAL_N_ELEMENTS(pFamilyMatch); |
512 | |
|
513 | 0 | while( nLower < nUpper ) |
514 | 0 | { |
515 | 0 | sal_uInt32 nCurrent = (nLower + nUpper) / 2; |
516 | 0 | const family_t* pHaystack = pFamilyMatch + nCurrent; |
517 | 0 | sal_Int32 nComparison = |
518 | 0 | rtl_str_compareIgnoreAsciiCase_WithLength |
519 | 0 | ( |
520 | 0 | aFamily.getStr(), aFamily.getLength(), |
521 | 0 | pHaystack->mpName, pHaystack->mnLength |
522 | 0 | ); |
523 | |
|
524 | 0 | if( nComparison < 0 ) |
525 | 0 | nUpper = nCurrent; |
526 | 0 | else |
527 | 0 | if( nComparison > 0 ) |
528 | 0 | nLower = nCurrent + 1; |
529 | 0 | else |
530 | 0 | return pHaystack->meType; |
531 | 0 | } |
532 | | |
533 | 0 | return FAMILY_DONTKNOW; |
534 | 0 | } |
535 | | |
536 | | OString PrintFontManager::getFontFile(const PrintFont& rFont) const |
537 | 468 | { |
538 | 468 | std::unordered_map< int, OString >::const_iterator it = m_aAtomToDir.find(rFont.m_nDirectory); |
539 | | assert(it != m_aAtomToDir.end()); |
540 | 468 | OString aPath = it->second + "/" + rFont.m_aFontFile; |
541 | 468 | return aPath; |
542 | 468 | } |
543 | | |
544 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |