b311480e |
1 | // Created on: 2008-01-20 |
2 | // Created by: Alexander A. BORODIN |
973c2be1 |
3 | // Copyright (c) 2008-2014 OPEN CASCADE SAS |
b311480e |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
b311480e |
6 | // |
d5f74e42 |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
b311480e |
15 | |
42cf5bc1 |
16 | #include <Font_FontMgr.hxx> |
5b377041 |
17 | |
18 | #include <Font_NameOfFont.hxx> |
725ef85e |
19 | #include <Font_FTLibrary.hxx> |
42cf5bc1 |
20 | #include <Font_SystemFont.hxx> |
5b377041 |
21 | #include <Message.hxx> |
22 | #include <Message_Messenger.hxx> |
7fd59977 |
23 | #include <NCollection_List.hxx> |
aff395a3 |
24 | #include <NCollection_Map.hxx> |
42cf5bc1 |
25 | #include <OSD_Environment.hxx> |
7fd59977 |
26 | #include <Standard_Stream.hxx> |
42cf5bc1 |
27 | #include <Standard_Type.hxx> |
aff395a3 |
28 | #include <TCollection_HAsciiString.hxx> |
7fd59977 |
29 | |
aff395a3 |
30 | #include <ft2build.h> |
31 | #include FT_FREETYPE_H |
25e59720 |
32 | IMPLEMENT_STANDARD_RTTIEXT(Font_FontMgr,Standard_Transient) |
92efcf78 |
33 | |
65360da3 |
34 | #if defined(_WIN32) |
7fd59977 |
35 | |
aff395a3 |
36 | #include <windows.h> |
37 | #include <stdlib.h> |
38 | |
39 | #ifdef _MSC_VER |
40 | #pragma comment (lib, "freetype.lib") |
41 | #endif |
42 | |
43 | namespace |
7fd59977 |
44 | { |
7fd59977 |
45 | |
aff395a3 |
46 | // list of supported extensions |
47 | static Standard_CString Font_FontMgr_Extensions[] = |
48 | { |
49 | "ttf", |
50 | "otf", |
51 | "ttc", |
52 | NULL |
53 | }; |
54 | |
55 | }; |
56 | |
57 | #else |
7fd59977 |
58 | |
aff395a3 |
59 | #include <OSD_DirectoryIterator.hxx> |
65360da3 |
60 | #include <OSD_FileIterator.hxx> |
aff395a3 |
61 | #include <OSD_Path.hxx> |
62 | #include <OSD_File.hxx> |
63 | #include <OSD_OpenMode.hxx> |
64 | #include <OSD_Protection.hxx> |
7fd59977 |
65 | |
aff395a3 |
66 | namespace |
67 | { |
68 | |
69 | // list of supported extensions |
70 | static Standard_CString Font_FontMgr_Extensions[] = |
71 | { |
72 | "ttf", |
73 | "otf", |
74 | "ttc", |
75 | "pfa", |
76 | "pfb", |
264abd72 |
77 | #ifdef __APPLE__ |
78 | // Datafork TrueType (OS X), obsolete |
79 | //"dfont", |
80 | #endif |
aff395a3 |
81 | NULL |
82 | }; |
83 | |
264abd72 |
84 | #if !defined(__ANDROID__) && !defined(__APPLE__) |
aff395a3 |
85 | // X11 configuration file in plain text format (obsolete - doesn't exists in modern distributives) |
86 | static Standard_CString myFontServiceConf[] = {"/etc/X11/fs/config", |
87 | "/usr/X11R6/lib/X11/fs/config", |
88 | "/usr/X11/lib/X11/fs/config", |
89 | NULL |
90 | }; |
264abd72 |
91 | #endif |
aff395a3 |
92 | |
93 | #ifdef __APPLE__ |
94 | // default fonts paths in Mac OS X |
95 | static Standard_CString myDefaultFontsDirs[] = {"/System/Library/Fonts", |
96 | "/Library/Fonts", |
97 | NULL |
98 | }; |
99 | #else |
100 | // default fonts paths in most Unix systems (Linux and others) |
65360da3 |
101 | static Standard_CString myDefaultFontsDirs[] = {"/system/fonts", // Android |
102 | "/usr/share/fonts", |
aff395a3 |
103 | "/usr/local/share/fonts", |
104 | NULL |
105 | }; |
106 | #endif |
107 | |
108 | static void addDirsRecursively (const OSD_Path& thePath, |
109 | NCollection_Map<TCollection_AsciiString>& theDirsMap) |
7fd59977 |
110 | { |
aff395a3 |
111 | TCollection_AsciiString aDirName; |
112 | thePath.SystemName (aDirName); |
113 | if (!theDirsMap.Add (aDirName)) |
114 | { |
115 | return; |
7fd59977 |
116 | } |
7fd59977 |
117 | |
aff395a3 |
118 | for (OSD_DirectoryIterator aDirIterator (thePath, "*"); aDirIterator.More(); aDirIterator.Next()) |
7fd59977 |
119 | { |
aff395a3 |
120 | OSD_Path aChildDirPath; |
121 | aDirIterator.Values().Path (aChildDirPath); |
122 | |
123 | TCollection_AsciiString aChildDirName; |
124 | aChildDirPath.SystemName (aChildDirName); |
125 | if (!aChildDirName.IsEqual (".") && !aChildDirName.IsEqual ("..")) |
126 | { |
127 | aChildDirName = aDirName + "/" + aChildDirName; |
128 | OSD_Path aPath (aChildDirName); |
129 | addDirsRecursively (aPath, theDirsMap); |
130 | } |
7fd59977 |
131 | } |
7fd59977 |
132 | } |
aff395a3 |
133 | |
68858c7d |
134 | } // anonymous namespace |
aff395a3 |
135 | |
136 | #endif |
137 | |
138 | // ======================================================================= |
139 | // function : checkFont |
140 | // purpose : |
141 | // ======================================================================= |
725ef85e |
142 | static Handle(Font_SystemFont) checkFont (const Handle(Font_FTLibrary)& theFTLib, |
143 | const Standard_CString theFontPath) |
aff395a3 |
144 | { |
145 | FT_Face aFontFace; |
725ef85e |
146 | FT_Error aFaceError = FT_New_Face (theFTLib->Instance(), theFontPath, 0, &aFontFace); |
aff395a3 |
147 | if (aFaceError != FT_Err_Ok) |
148 | { |
149 | return NULL; |
7fd59977 |
150 | } |
7fd59977 |
151 | |
aff395a3 |
152 | Font_FontAspect anAspect = Font_FA_Regular; |
153 | if (aFontFace->style_flags == (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD)) |
154 | { |
155 | anAspect = Font_FA_BoldItalic; |
156 | } |
157 | else if (aFontFace->style_flags == FT_STYLE_FLAG_ITALIC) |
158 | { |
159 | anAspect = Font_FA_Italic; |
160 | } |
161 | else if (aFontFace->style_flags == FT_STYLE_FLAG_BOLD) |
162 | { |
163 | anAspect = Font_FA_Bold; |
164 | } |
165 | |
508643cf |
166 | Handle(Font_SystemFont) aResult; |
167 | if (aFontFace->family_name != NULL // skip broken fonts (error in FreeType?) |
168 | && FT_Select_Charmap (aFontFace, ft_encoding_unicode) == 0) // Font_FTFont supports only UNICODE fonts |
169 | { |
5b377041 |
170 | aResult = new Font_SystemFont (aFontFace->family_name); |
171 | aResult->SetFontPath (anAspect, theFontPath); |
e4f0cc46 |
172 | // automatically identify some known single-line fonts |
5b377041 |
173 | aResult->SetSingleStrokeFont (aResult->FontKey().StartsWith ("olf ")); |
508643cf |
174 | } |
7fd59977 |
175 | |
aff395a3 |
176 | FT_Done_Face (aFontFace); |
7fd59977 |
177 | |
aff395a3 |
178 | return aResult; |
179 | } |
7fd59977 |
180 | |
aff395a3 |
181 | // ======================================================================= |
182 | // function : GetInstance |
183 | // purpose : |
184 | // ======================================================================= |
185 | Handle(Font_FontMgr) Font_FontMgr::GetInstance() |
186 | { |
eeaaaefb |
187 | static Handle(Font_FontMgr) _mgr; |
aff395a3 |
188 | if (_mgr.IsNull()) |
189 | { |
eeaaaefb |
190 | _mgr = new Font_FontMgr(); |
aff395a3 |
191 | } |
7fd59977 |
192 | |
193 | return _mgr; |
7fd59977 |
194 | } |
195 | |
5b377041 |
196 | // ======================================================================= |
197 | // function : addFontAlias |
198 | // purpose : |
199 | // ======================================================================= |
200 | void Font_FontMgr::addFontAlias (const TCollection_AsciiString& theAliasName, |
201 | const Handle(Font_FontAliasSequence)& theAliases, |
202 | Font_FontAspect theAspect) |
203 | { |
204 | if (theAliases.IsNull() |
205 | || theAliases->IsEmpty()) |
206 | { |
207 | return; |
208 | } |
209 | |
210 | Handle(Font_FontAliasSequence) anAliases = theAliases; |
211 | if (theAspect != Font_FA_Undefined) |
212 | { |
213 | anAliases = new Font_FontAliasSequence(); |
214 | for (Font_FontAliasSequence::Iterator anAliasIter (*theAliases); anAliasIter.More(); anAliasIter.Next()) |
215 | { |
216 | const TCollection_AsciiString& aName = anAliasIter.Value().FontName; |
217 | anAliases->Append (Font_FontAlias (aName, theAspect)); |
218 | } |
219 | } |
220 | |
221 | TCollection_AsciiString anAliasName (theAliasName); |
222 | anAliasName.LowerCase(); |
223 | myFontAliases.Bind (anAliasName, anAliases); |
224 | } |
225 | |
aff395a3 |
226 | // ======================================================================= |
227 | // function : Font_FontMgr |
228 | // purpose : |
229 | // ======================================================================= |
230 | Font_FontMgr::Font_FontMgr() |
5b377041 |
231 | : myToTraceAliases (Standard_False) |
aff395a3 |
232 | { |
5b377041 |
233 | Handle(Font_FontAliasSequence) aMono = new Font_FontAliasSequence(); |
234 | Handle(Font_FontAliasSequence) aSerif = new Font_FontAliasSequence(); |
235 | Handle(Font_FontAliasSequence) aSans = new Font_FontAliasSequence(); |
236 | Handle(Font_FontAliasSequence) aSymbol = new Font_FontAliasSequence(); |
237 | Handle(Font_FontAliasSequence) aScript = new Font_FontAliasSequence(); |
238 | Handle(Font_FontAliasSequence) aWinDin = new Font_FontAliasSequence(); |
239 | Handle(Font_FontAliasSequence) anIris = new Font_FontAliasSequence(); |
240 | Handle(Font_FontAliasSequence) aCJK = new Font_FontAliasSequence(); |
241 | Handle(Font_FontAliasSequence) aKorean = new Font_FontAliasSequence(); |
242 | |
243 | // best matches - pre-installed on Windows, some of them are pre-installed on macOS, |
244 | // and sometimes them can be found installed on other systems (by user) |
245 | aMono ->Append (Font_FontAlias ("courier new")); |
246 | aSerif ->Append (Font_FontAlias ("times new roman")); |
247 | aSans ->Append (Font_FontAlias ("arial")); |
248 | aSymbol->Append (Font_FontAlias ("symbol")); |
249 | aScript->Append (Font_FontAlias ("script")); |
250 | aWinDin->Append (Font_FontAlias ("wingdings")); |
251 | anIris ->Append (Font_FontAlias ("lucida console")); |
252 | |
253 | #if defined(__ANDROID__) |
254 | // Noto font family is usually installed on Android 6+ devices |
255 | aMono ->Append (Font_FontAlias ("noto mono")); |
256 | aSerif ->Append (Font_FontAlias ("noto serif")); |
257 | // Droid font family is usually installed on Android 4+ devices |
258 | aMono ->Append (Font_FontAlias ("droid sans mono")); |
259 | aSerif ->Append (Font_FontAlias ("droid serif")); |
260 | aSans ->Append (Font_FontAlias ("roboto")); // actually DroidSans.ttf |
261 | #elif !defined(_WIN32) && !defined(__APPLE__) //X11 |
262 | aSerif ->Append (Font_FontAlias ("times")); |
263 | aSans ->Append (Font_FontAlias ("helvetica")); |
264 | // GNU FreeFonts family is usually installed on Linux |
265 | aMono ->Append (Font_FontAlias ("freemono")); |
266 | aSerif ->Append (Font_FontAlias ("freeserif")); |
267 | aSans ->Append (Font_FontAlias ("freesans")); |
268 | // DejaVu font family is usually installed on Linux |
269 | aMono ->Append (Font_FontAlias ("dejavu sans mono")); |
270 | aSerif ->Append (Font_FontAlias ("dejavu serif")); |
271 | aSans ->Append (Font_FontAlias ("dejavu sans")); |
272 | #endif |
273 | |
274 | // default CJK (Chinese/Japanese/Korean) fonts |
275 | aCJK ->Append (Font_FontAlias ("simsun")); // Windows |
276 | aCJK ->Append (Font_FontAlias ("droid sans fallback")); // Android, Linux |
277 | aCJK ->Append (Font_FontAlias ("noto sans sc")); // Android |
278 | |
279 | #if defined(_WIN32) |
280 | aKorean->Append (Font_FontAlias ("malgun gothic")); // introduced since Vista |
281 | aKorean->Append (Font_FontAlias ("gulim")); // used on older systems (Windows XP) |
282 | #elif defined(__APPLE__) |
283 | aKorean->Append (Font_FontAlias ("applegothic")); |
284 | aKorean->Append (Font_FontAlias ("stfangsong")); |
285 | #endif |
286 | aKorean->Append (Font_FontAlias ("nanumgothic")); // Android, Linux |
287 | aKorean->Append (Font_FontAlias ("noto sans kr")); // Android |
288 | aKorean->Append (Font_FontAlias ("nanummyeongjo")); // Linux |
289 | aKorean->Append (Font_FontAlias ("noto serif cjk jp")); // Linux |
290 | aKorean->Append (Font_FontAlias ("noto sans cjk jp")); // Linux |
291 | |
292 | addFontAlias ("mono", aMono); |
293 | addFontAlias ("courier", aMono); // Font_NOF_ASCII_MONO |
294 | addFontAlias ("monospace", aMono); // Font_NOF_MONOSPACE |
295 | addFontAlias ("rock", aSans); // Font_NOF_CARTOGRAPHIC_SIMPLEX |
296 | addFontAlias ("sansserif", aSans); // Font_NOF_SANS_SERIF |
297 | addFontAlias ("sans-serif", aSans); |
298 | addFontAlias ("sans", aSans); |
299 | addFontAlias ("arial", aSans); |
300 | addFontAlias ("times", aSerif); |
301 | addFontAlias ("serif", aSerif); // Font_NOF_SERIF |
302 | addFontAlias ("times-roman", aSerif); // Font_NOF_ASCII_SIMPLEX |
303 | addFontAlias ("times-bold", aSerif, Font_FA_Bold); // Font_NOF_ASCII_DUPLEX |
304 | addFontAlias ("times-italic", aSerif, Font_FA_Italic); // Font_NOF_ASCII_ITALIC_COMPLEX |
305 | addFontAlias ("times-bolditalic", aSerif, Font_FA_BoldItalic); // Font_NOF_ASCII_ITALIC_TRIPLEX |
306 | addFontAlias ("symbol", aSymbol); // Font_NOF_GREEK_MONO |
307 | addFontAlias ("iris", anIris); // Font_NOF_KANJI_MONO |
308 | addFontAlias ("korean", aKorean); // Font_NOF_KOREAN |
309 | addFontAlias ("cjk", aCJK); // Font_NOF_CJK |
310 | addFontAlias ("nsimsun", aCJK); |
311 | addFontAlias (Font_NOF_SYMBOL_MONO, aWinDin); |
312 | addFontAlias (Font_NOF_ASCII_SCRIPT_SIMPLEX, aScript); |
313 | |
314 | myFallbackAlias = aSans; |
315 | |
7fd59977 |
316 | InitFontDataBase(); |
7fd59977 |
317 | } |
318 | |
725ef85e |
319 | // ======================================================================= |
320 | // function : CheckFont |
321 | // purpose : |
322 | // ======================================================================= |
323 | Handle(Font_SystemFont) Font_FontMgr::CheckFont (Standard_CString theFontPath) const |
324 | { |
325 | Handle(Font_FTLibrary) aFtLibrary = new Font_FTLibrary(); |
326 | return checkFont (aFtLibrary, theFontPath); |
327 | } |
328 | |
329 | // ======================================================================= |
330 | // function : RegisterFont |
331 | // purpose : |
332 | // ======================================================================= |
333 | Standard_Boolean Font_FontMgr::RegisterFont (const Handle(Font_SystemFont)& theFont, |
334 | const Standard_Boolean theToOverride) |
335 | { |
336 | if (theFont.IsNull()) |
337 | { |
338 | return Standard_False; |
339 | } |
340 | |
5b377041 |
341 | const Standard_Integer anOldIndex = myFontMap.FindIndex (theFont); |
342 | if (anOldIndex == 0) |
343 | { |
344 | myFontMap.Add (theFont); |
345 | return Standard_True; |
346 | } |
347 | |
348 | Handle(Font_SystemFont) anOldFont = myFontMap.FindKey (anOldIndex); |
349 | for (int anAspectIter = 0; anAspectIter < Font_FontAspect_NB; ++anAspectIter) |
725ef85e |
350 | { |
5b377041 |
351 | if (anOldFont->FontPath ((Font_FontAspect )anAspectIter).IsEqual (theFont->FontPath ((Font_FontAspect )anAspectIter))) |
725ef85e |
352 | { |
353 | continue; |
354 | } |
5b377041 |
355 | else if (theToOverride |
356 | || !anOldFont->HasFontAspect ((Font_FontAspect )anAspectIter)) |
725ef85e |
357 | { |
5b377041 |
358 | anOldFont->SetFontPath ((Font_FontAspect )anAspectIter, theFont->FontPath ((Font_FontAspect )anAspectIter)); |
725ef85e |
359 | } |
5b377041 |
360 | else if (theFont->HasFontAspect ((Font_FontAspect )anAspectIter)) |
725ef85e |
361 | { |
5b377041 |
362 | return Standard_False; |
725ef85e |
363 | } |
364 | } |
725ef85e |
365 | return Standard_True; |
366 | } |
367 | |
aff395a3 |
368 | // ======================================================================= |
369 | // function : InitFontDataBase |
370 | // purpose : |
371 | // ======================================================================= |
372 | void Font_FontMgr::InitFontDataBase() |
373 | { |
5b377041 |
374 | myFontMap.Clear(); |
725ef85e |
375 | Handle(Font_FTLibrary) aFtLibrary; |
7fd59977 |
376 | |
1ce0716b |
377 | #if defined(OCCT_UWP) |
378 | // system font files are not accessible |
379 | (void )aFtLibrary; |
380 | #elif defined(_WIN32) |
7fd59977 |
381 | |
aff395a3 |
382 | // font directory is placed in "C:\Windows\Fonts\" |
383 | UINT aStrLength = GetSystemWindowsDirectoryA (NULL, 0); |
384 | if (aStrLength == 0) |
a6535b1d |
385 | { |
aff395a3 |
386 | return; |
a6535b1d |
387 | } |
aff395a3 |
388 | |
389 | char* aWinDir = new char[aStrLength]; |
390 | GetSystemWindowsDirectoryA (aWinDir, aStrLength); |
5b377041 |
391 | TCollection_AsciiString aFontsDir (aWinDir); |
392 | aFontsDir.AssignCat ("\\Fonts\\"); |
aff395a3 |
393 | delete[] aWinDir; |
394 | |
395 | // read fonts list from registry |
396 | HKEY aFontsKey; |
397 | if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts", |
398 | 0, KEY_READ, &aFontsKey) != ERROR_SUCCESS) |
7fd59977 |
399 | { |
400 | return; |
7fd59977 |
401 | } |
7fd59977 |
402 | |
aff395a3 |
403 | NCollection_Map<TCollection_AsciiString> aSupportedExtensions; |
404 | for (Standard_Integer anIter = 0; Font_FontMgr_Extensions[anIter] != NULL; ++anIter) |
7fd59977 |
405 | { |
aff395a3 |
406 | Standard_CString anExt = Font_FontMgr_Extensions[anIter]; |
407 | aSupportedExtensions.Add (TCollection_AsciiString (anExt)); |
7fd59977 |
408 | } |
409 | |
725ef85e |
410 | aFtLibrary = new Font_FTLibrary(); |
aff395a3 |
411 | static const DWORD aBufferSize = 256; |
412 | char aNameBuff[aBufferSize]; |
413 | char aPathBuff[aBufferSize]; |
414 | DWORD aNameSize = aBufferSize; |
415 | DWORD aPathSize = aBufferSize; |
416 | for (DWORD anIter = 0; |
417 | RegEnumValueA (aFontsKey, anIter, |
418 | aNameBuff, &aNameSize, NULL, NULL, |
419 | (LPBYTE )aPathBuff, &aPathSize) != ERROR_NO_MORE_ITEMS; |
420 | ++anIter, aNameSize = aBufferSize, aPathSize = aBufferSize) |
421 | { |
422 | aPathBuff[(aPathSize < aBufferSize) ? aPathSize : (aBufferSize - 1)] = '\0'; // ensure string is NULL-terminated |
7fd59977 |
423 | |
5b377041 |
424 | TCollection_AsciiString aFontName (aNameBuff), aFontPath (aPathBuff); |
425 | if (aFontPath.Search ("\\") == -1) |
aff395a3 |
426 | { |
5b377041 |
427 | aFontPath.Insert (1, aFontsDir); // make absolute path |
7fd59977 |
428 | } |
aff395a3 |
429 | |
430 | // check file extension is in list of supported |
5b377041 |
431 | const Standard_Integer anExtensionPosition = aFontPath.SearchFromEnd (".") + 1; |
432 | if (anExtensionPosition > 0 && anExtensionPosition < aFontPath.Length()) |
7fd59977 |
433 | { |
5b377041 |
434 | TCollection_AsciiString aFontExtension = aFontPath.SubString (anExtensionPosition, aFontPath.Length()); |
435 | aFontExtension.LowerCase(); |
436 | if (aSupportedExtensions.Contains (aFontExtension)) |
aff395a3 |
437 | { |
5b377041 |
438 | if (Handle(Font_SystemFont) aNewFont = checkFont (aFtLibrary, aFontPath.ToCString())) |
aff395a3 |
439 | { |
5b377041 |
440 | RegisterFont (aNewFont, false); |
aff395a3 |
441 | } |
442 | } |
7fd59977 |
443 | } |
444 | } |
7fd59977 |
445 | |
aff395a3 |
446 | // close registry key |
447 | RegCloseKey (aFontsKey); |
448 | |
449 | #else |
7fd59977 |
450 | |
aff395a3 |
451 | NCollection_Map<TCollection_AsciiString> aMapOfFontsDirs; |
264abd72 |
452 | #if !defined(__ANDROID__) && !defined(__APPLE__) |
aff395a3 |
453 | const OSD_Protection aProtectRead (OSD_R, OSD_R, OSD_R, OSD_R); |
7fd59977 |
454 | |
aff395a3 |
455 | // read fonts directories from font service config file (obsolete) |
456 | for (Standard_Integer anIter = 0; myFontServiceConf[anIter] != NULL; ++anIter) |
7fd59977 |
457 | { |
aff395a3 |
458 | const TCollection_AsciiString aFileOfFontsPath (myFontServiceConf[anIter]); |
459 | OSD_File aFile (aFileOfFontsPath); |
460 | if (!aFile.Exists()) |
461 | { |
462 | continue; |
463 | } |
7fd59977 |
464 | |
aff395a3 |
465 | aFile.Open (OSD_ReadOnly, aProtectRead); |
466 | if (!aFile.IsOpen()) |
467 | { |
468 | continue; |
469 | } |
470 | |
471 | Standard_Integer aNByte = 256; |
472 | Standard_Integer aNbyteRead; |
473 | TCollection_AsciiString aStr; // read string with information |
474 | while (!aFile.IsAtEnd()) |
7fd59977 |
475 | { |
aff395a3 |
476 | Standard_Integer aLocation = -1; |
477 | Standard_Integer aPathLocation = -1; |
478 | |
479 | aFile.ReadLine (aStr, aNByte, aNbyteRead); // reading 1 line (256 bytes) |
480 | aLocation = aStr.Search ("catalogue="); |
481 | if (aLocation < 0) |
482 | { |
483 | aLocation = aStr.Search ("catalogue ="); |
484 | } |
485 | |
486 | aPathLocation = aStr.Search ("/"); |
487 | if (aLocation > 0 && aPathLocation > 0) |
7fd59977 |
488 | { |
aff395a3 |
489 | aStr = aStr.Split (aPathLocation - 1); |
490 | TCollection_AsciiString aFontPath; |
491 | Standard_Integer aPathNumber = 1; |
492 | do |
7fd59977 |
493 | { |
aff395a3 |
494 | // Getting directory paths, which can be splitted by "," or ":" |
495 | aFontPath = aStr.Token (":,", aPathNumber); |
496 | aFontPath.RightAdjust(); |
497 | if (!aFontPath.IsEmpty()) |
7fd59977 |
498 | { |
aff395a3 |
499 | OSD_Path aPath(aFontPath); |
500 | addDirsRecursively (aPath, aMapOfFontsDirs); |
7fd59977 |
501 | } |
aff395a3 |
502 | aPathNumber++; |
503 | } |
504 | while (!aFontPath.IsEmpty()); |
7fd59977 |
505 | } |
7fd59977 |
506 | } |
aff395a3 |
507 | aFile.Close(); |
7fd59977 |
508 | } |
264abd72 |
509 | #endif |
7fd59977 |
510 | |
aff395a3 |
511 | // append default directories |
512 | for (Standard_Integer anIter = 0; myDefaultFontsDirs[anIter] != NULL; ++anIter) |
513 | { |
514 | Standard_CString anItem = myDefaultFontsDirs[anIter]; |
515 | TCollection_AsciiString aPathStr (anItem); |
516 | OSD_Path aPath (aPathStr); |
517 | addDirsRecursively (aPath, aMapOfFontsDirs); |
518 | } |
519 | |
520 | NCollection_Map<TCollection_AsciiString> aSupportedExtensions; |
521 | for (Standard_Integer anIter = 0; Font_FontMgr_Extensions[anIter] != NULL; ++anIter) |
522 | { |
523 | Standard_CString anExt = Font_FontMgr_Extensions[anIter]; |
524 | aSupportedExtensions.Add (TCollection_AsciiString (anExt)); |
525 | } |
526 | |
725ef85e |
527 | aFtLibrary = new Font_FTLibrary(); |
aff395a3 |
528 | for (NCollection_Map<TCollection_AsciiString>::Iterator anIter (aMapOfFontsDirs); |
529 | anIter.More(); anIter.Next()) |
530 | { |
5b377041 |
531 | #if !defined(__ANDROID__) && !defined(__APPLE__) |
532 | OSD_File aReadFile (anIter.Value() + "/fonts.dir"); |
533 | if (!aReadFile.Exists()) |
65360da3 |
534 | { |
5b377041 |
535 | #endif |
536 | OSD_Path aFolderPath (anIter.Value()); |
537 | for (OSD_FileIterator aFileIter (aFolderPath, "*"); aFileIter.More(); aFileIter.Next()) |
538 | { |
539 | OSD_Path aFontFilePath; |
540 | aFileIter.Values().Path (aFontFilePath); |
65360da3 |
541 | |
5b377041 |
542 | TCollection_AsciiString aFontFileName; |
543 | aFontFilePath.SystemName (aFontFileName); |
544 | aFontFileName = anIter.Value() + "/" + aFontFileName; |
65360da3 |
545 | |
5b377041 |
546 | if (Handle(Font_SystemFont) aNewFont = checkFont (aFtLibrary, aFontFileName.ToCString())) |
547 | { |
548 | RegisterFont (aNewFont, false); |
549 | } |
65360da3 |
550 | } |
5b377041 |
551 | |
552 | #if !defined(__ANDROID__) && !defined(__APPLE__) |
553 | continue; |
aff395a3 |
554 | } |
555 | |
556 | aReadFile.Open (OSD_ReadOnly, aProtectRead); |
557 | if (!aReadFile.IsOpen()) |
558 | { |
559 | continue; // invalid fonts directory |
560 | } |
561 | |
562 | Standard_Integer aNbyteRead, aNByte = 256; |
563 | TCollection_AsciiString aLine (aNByte); |
564 | Standard_Boolean isFirstLine = Standard_True; |
565 | const TCollection_AsciiString anEncoding ("iso8859-1\n"); |
566 | while (!aReadFile.IsAtEnd()) |
567 | { |
568 | aReadFile.ReadLine (aLine, aNByte, aNbyteRead); |
569 | if (isFirstLine) |
570 | { |
571 | // first line contains the number of fonts in this file |
572 | // just ignoring it... |
573 | isFirstLine = Standard_False; |
574 | continue; |
575 | } |
7fd59977 |
576 | |
aff395a3 |
577 | Standard_Integer anExtensionPosition = aLine.Search (".") + 1; |
578 | if (anExtensionPosition == 0) |
579 | { |
580 | continue; // can't find extension position in the font description |
581 | } |
7fd59977 |
582 | |
aff395a3 |
583 | Standard_Integer anEndOfFileName = aLine.Location (" ", anExtensionPosition, aLine.Length()) - 1; |
584 | if (anEndOfFileName < 0 || anEndOfFileName < anExtensionPosition) |
585 | { |
586 | continue; // font description have empty extension |
587 | } |
7fd59977 |
588 | |
aff395a3 |
589 | TCollection_AsciiString aFontExtension = aLine.SubString (anExtensionPosition, anEndOfFileName); |
590 | aFontExtension.LowerCase(); |
591 | if (aSupportedExtensions.Contains (aFontExtension) && (aLine.Search (anEncoding) > 0)) |
7fd59977 |
592 | { |
aff395a3 |
593 | // In current implementation use fonts with ISO-8859-1 coding page. |
594 | // OCCT not give to manage coding page by means of programm interface. |
595 | // TODO: make high level interface for choosing necessary coding page. |
5b377041 |
596 | TCollection_AsciiString aXLFD (aLine.SubString (anEndOfFileName + 2, aLine.Length())); |
597 | TCollection_AsciiString aFontPath (anIter.Value().ToCString()); |
598 | if (aFontPath.SearchFromEnd ("/") != aFontPath.Length()) |
aff395a3 |
599 | { |
5b377041 |
600 | aFontPath.AssignCat ("/"); |
aff395a3 |
601 | } |
5b377041 |
602 | TCollection_AsciiString aFontFileName (aLine.SubString (1, anEndOfFileName)); |
603 | aFontPath.AssignCat (aFontFileName); |
604 | if (Handle(Font_SystemFont) aNewFont = checkFont (aFtLibrary, aFontPath.ToCString())) |
aff395a3 |
605 | { |
5b377041 |
606 | RegisterFont (aNewFont, false); |
607 | if (!aXLFD.IsEmpty() |
608 | && aXLFD.Search ("-0-0-0-0-") != -1) // ignore non-resizable fonts |
609 | { |
610 | const TCollection_AsciiString anXName = aXLFD.Token ("-", 2); |
611 | Font_FontAspect anXAspect = Font_FA_Regular; |
612 | if (aXLFD.Token ("-", 3).IsEqual ("bold") |
613 | && (aXLFD.Token ("-", 4).IsEqual ("i") |
614 | || aXLFD.Token ("-", 4).IsEqual ("o"))) |
615 | { |
616 | anXAspect = Font_FA_BoldItalic; |
617 | } |
618 | else if (aXLFD.Token ("-", 3).IsEqual ("bold")) |
619 | { |
620 | anXAspect = Font_FA_Bold; |
621 | } |
622 | else if (aXLFD.Token ("-", 4).IsEqual ("i") |
623 | || aXLFD.Token ("-", 4).IsEqual ("o")) |
624 | { |
625 | anXAspect = Font_FA_Italic; |
626 | } |
627 | |
628 | Handle(Font_SystemFont) aNewFontFromXLFD = new Font_SystemFont (anXName); |
629 | aNewFontFromXLFD->SetFontPath (anXAspect, aFontPath); |
630 | if (!aNewFont->IsEqual (aNewFontFromXLFD)) |
631 | { |
632 | RegisterFont (aNewFontFromXLFD, false); |
633 | } |
634 | } |
aff395a3 |
635 | } |
aff395a3 |
636 | } |
7fd59977 |
637 | } |
aff395a3 |
638 | aReadFile.Close(); |
65360da3 |
639 | #endif |
7fd59977 |
640 | } |
641 | #endif |
aff395a3 |
642 | } |
643 | |
b514beda |
644 | // ======================================================================= |
645 | // function : GetAvailableFontsNames |
646 | // purpose : |
647 | // ======================================================================= |
aff395a3 |
648 | void Font_FontMgr::GetAvailableFontsNames (TColStd_SequenceOfHAsciiString& theFontsNames) const |
649 | { |
650 | theFontsNames.Clear(); |
5b377041 |
651 | for (NCollection_IndexedMap<Handle(Font_SystemFont), Font_SystemFont>::Iterator aFontIter (myFontMap); |
652 | aFontIter.More(); aFontIter.Next()) |
aff395a3 |
653 | { |
5b377041 |
654 | const Handle(Font_SystemFont)& aFont = aFontIter.Value(); |
655 | theFontsNames.Append (new TCollection_HAsciiString(aFont->FontName())); |
aff395a3 |
656 | } |
7fd59977 |
657 | } |
658 | |
b514beda |
659 | // ======================================================================= |
660 | // function : GetFont |
661 | // purpose : |
662 | // ======================================================================= |
aff395a3 |
663 | Handle(Font_SystemFont) Font_FontMgr::GetFont (const Handle(TCollection_HAsciiString)& theFontName, |
b514beda |
664 | const Font_FontAspect theFontAspect, |
aff395a3 |
665 | const Standard_Integer theFontSize) const |
7fd59977 |
666 | { |
5b377041 |
667 | if ((theFontSize < 2 && theFontSize != -1) || theFontName.IsNull()) |
aff395a3 |
668 | { |
5b377041 |
669 | return Handle(Font_SystemFont)(); |
aff395a3 |
670 | } |
671 | |
5b377041 |
672 | Handle(Font_SystemFont) aFont = myFontMap.Find (theFontName->String()); |
673 | return (aFont.IsNull() |
674 | || theFontAspect == Font_FontAspect_UNDEFINED |
675 | || aFont->HasFontAspect (theFontAspect)) |
676 | ? aFont |
677 | : Handle(Font_SystemFont)(); |
678 | } |
aff395a3 |
679 | |
5b377041 |
680 | // ======================================================================= |
681 | // function : GetFont |
682 | // purpose : |
683 | // ======================================================================= |
684 | Handle(Font_SystemFont) Font_FontMgr::GetFont (const TCollection_AsciiString& theFontName) const |
685 | { |
686 | return myFontMap.Find (theFontName); |
7fd59977 |
687 | } |
688 | |
b514beda |
689 | // ======================================================================= |
690 | // function : FindFont |
691 | // purpose : |
692 | // ======================================================================= |
5b377041 |
693 | Handle(Font_SystemFont) Font_FontMgr::FindFont (const TCollection_AsciiString& theFontName, |
1bbd7c79 |
694 | Font_StrictLevel theStrictLevel, |
5b377041 |
695 | Font_FontAspect& theFontAspect) const |
aff395a3 |
696 | { |
5b377041 |
697 | TCollection_AsciiString aFontName (theFontName); |
698 | aFontName.LowerCase(); |
699 | Handle(Font_SystemFont) aFont = myFontMap.Find (aFontName); |
1bbd7c79 |
700 | if (!aFont.IsNull() |
701 | || theStrictLevel == Font_StrictLevel_Strict) |
aff395a3 |
702 | { |
703 | return aFont; |
704 | } |
705 | |
706 | // Trying to use font names mapping |
976627e6 |
707 | for (int aPass = 0; aPass < 2; ++aPass) |
aff395a3 |
708 | { |
976627e6 |
709 | Handle(Font_FontAliasSequence) anAliases; |
710 | if (aPass == 0) |
711 | { |
712 | myFontAliases.Find (aFontName, anAliases); |
713 | } |
1bbd7c79 |
714 | else if (theStrictLevel == Font_StrictLevel_Any) |
976627e6 |
715 | { |
716 | anAliases = myFallbackAlias; |
717 | } |
aff395a3 |
718 | |
976627e6 |
719 | if (anAliases.IsNull() |
720 | || anAliases->IsEmpty()) |
721 | { |
722 | continue; |
723 | } |
724 | |
725 | bool isAliasUsed = false, isBestAlias = false; |
5b377041 |
726 | for (Font_FontAliasSequence::Iterator anAliasIter (*anAliases); anAliasIter.More(); anAliasIter.Next()) |
b514beda |
727 | { |
5b377041 |
728 | const Font_FontAlias& anAlias = anAliasIter.Value(); |
729 | if (Handle(Font_SystemFont) aFont2 = myFontMap.Find (anAlias.FontName)) |
730 | { |
731 | if (aFont.IsNull()) |
732 | { |
733 | aFont = aFont2; |
734 | isAliasUsed = true; |
735 | } |
736 | |
737 | if ((anAlias.FontAspect != Font_FontAspect_UNDEFINED |
738 | && aFont2->HasFontAspect (anAlias.FontAspect))) |
739 | { |
740 | // special case - alias refers to styled font (e.g. "times-bold") |
741 | isBestAlias = true; |
742 | theFontAspect = anAlias.FontAspect; |
743 | break; |
744 | } |
745 | else if (anAlias.FontAspect == Font_FontAspect_UNDEFINED |
746 | && (theFontAspect == Font_FontAspect_UNDEFINED |
976627e6 |
747 | || aFont2->HasFontAspect (theFontAspect))) |
5b377041 |
748 | { |
749 | isBestAlias = true; |
750 | break; |
751 | } |
752 | } |
753 | } |
976627e6 |
754 | |
755 | if (aPass == 0) |
5b377041 |
756 | { |
757 | if (isAliasUsed && myToTraceAliases) |
758 | { |
759 | Message::DefaultMessenger()->Send (TCollection_AsciiString("Font_FontMgr, using font alias '") + aFont->FontName() + "'" |
976627e6 |
760 | " instead of requested '" + theFontName +"'", Message_Trace); |
5b377041 |
761 | } |
762 | if (isBestAlias) |
763 | { |
764 | return aFont; |
765 | } |
976627e6 |
766 | else if (!aFont.IsNull()) |
767 | { |
768 | break; |
769 | } |
b514beda |
770 | } |
771 | } |
aff395a3 |
772 | |
5b377041 |
773 | if (aFont.IsNull()) |
aff395a3 |
774 | { |
5b377041 |
775 | // try finding ANY font in case if even default fallback alias myFallbackAlias cannot be found |
776 | aFont = myFontMap.Find (TCollection_AsciiString()); |
777 | } |
778 | if (aFont.IsNull()) |
779 | { |
780 | Message::DefaultMessenger()->Send (TCollection_AsciiString("Font_FontMgr, error: unable to find any font!", Message_Fail)); |
781 | return Handle(Font_SystemFont)(); |
aff395a3 |
782 | } |
783 | |
5b377041 |
784 | if ((theFontAspect != Font_FA_Undefined |
785 | && !aFont->HasFontAspect (theFontAspect)) |
786 | || (!aFontName.IsEmpty() |
787 | && !aFontName.IsEqual (aFont->FontKey()))) |
aff395a3 |
788 | { |
5b377041 |
789 | TCollection_AsciiString aDesc = TCollection_AsciiString() + "'" + theFontName + "'" |
790 | + TCollection_AsciiString() + " [" + Font_FontMgr::FontAspectToString (theFontAspect) + "]"; |
791 | Message::DefaultMessenger()->Send (TCollection_AsciiString("Font_FontMgr, warning: unable to find font ") |
792 | + aDesc + "; " + aFont->ToString() + " is used instead"); |
aff395a3 |
793 | } |
5b377041 |
794 | return aFont; |
795 | } |
aff395a3 |
796 | |
5b377041 |
797 | // ======================================================================= |
798 | // function : Font_FontMap::Find |
799 | // purpose : |
800 | // ======================================================================= |
801 | Handle(Font_SystemFont) Font_FontMgr::Font_FontMap::Find (const TCollection_AsciiString& theFontName) const |
802 | { |
803 | if (IsEmpty()) |
aff395a3 |
804 | { |
5b377041 |
805 | return Handle(Font_SystemFont)(); |
806 | } |
807 | else if (theFontName.IsEmpty()) |
808 | { |
809 | return FindKey (1); // return any font |
aff395a3 |
810 | } |
811 | |
5b377041 |
812 | TCollection_AsciiString aFontName (theFontName); |
813 | aFontName.LowerCase(); |
814 | for (IndexedMapNode* aNodeIter = (IndexedMapNode* )myData1[::HashCode (aFontName, NbBuckets())]; |
815 | aNodeIter != NULL; aNodeIter = (IndexedMapNode* )aNodeIter->Next()) |
816 | { |
817 | const Handle(Font_SystemFont)& aKey = aNodeIter->Key1(); |
818 | if (aKey->FontKey().IsEqual (aFontName)) |
819 | { |
820 | return aKey; |
821 | } |
822 | } |
823 | return Handle(Font_SystemFont)(); |
aff395a3 |
824 | } |