0030537: Visualization - wrapping text in font text formatter
[occt.git] / src / Font / Font_FontMgr.cxx
CommitLineData
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>
21095f2d 23#include <NCollection_Buffer.hxx>
7fd59977 24#include <NCollection_List.hxx>
aff395a3 25#include <NCollection_Map.hxx>
42cf5bc1 26#include <OSD_Environment.hxx>
7fd59977 27#include <Standard_Stream.hxx>
42cf5bc1 28#include <Standard_Type.hxx>
aff395a3 29#include <TCollection_HAsciiString.hxx>
7fd59977 30
21095f2d 31#include "Font_DejavuSans_Latin_woff.pxx"
32
aff395a3 33#include <ft2build.h>
34#include FT_FREETYPE_H
25e59720 35IMPLEMENT_STANDARD_RTTIEXT(Font_FontMgr,Standard_Transient)
92efcf78 36
65360da3 37#if defined(_WIN32)
7fd59977 38
aff395a3 39 #include <windows.h>
40 #include <stdlib.h>
41
42 #ifdef _MSC_VER
43 #pragma comment (lib, "freetype.lib")
44 #endif
45
46 namespace
7fd59977 47 {
aff395a3 48 // list of supported extensions
49 static Standard_CString Font_FontMgr_Extensions[] =
50 {
51 "ttf",
52 "otf",
53 "ttc",
54 NULL
55 };
8c2d3314 56 }
aff395a3 57
58#else
7fd59977 59
aff395a3 60 #include <OSD_DirectoryIterator.hxx>
65360da3 61 #include <OSD_FileIterator.hxx>
aff395a3 62 #include <OSD_Path.hxx>
63 #include <OSD_File.hxx>
64 #include <OSD_OpenMode.hxx>
65 #include <OSD_Protection.hxx>
7fd59977 66
aff395a3 67 namespace
68 {
69
70 // list of supported extensions
71 static Standard_CString Font_FontMgr_Extensions[] =
72 {
73 "ttf",
74 "otf",
75 "ttc",
76 "pfa",
77 "pfb",
264abd72 78 #ifdef __APPLE__
79 // Datafork TrueType (OS X), obsolete
80 //"dfont",
81 #endif
aff395a3 82 NULL
83 };
84
565baee6 85 #if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
aff395a3 86 // X11 configuration file in plain text format (obsolete - doesn't exists in modern distributives)
87 static Standard_CString myFontServiceConf[] = {"/etc/X11/fs/config",
88 "/usr/X11R6/lib/X11/fs/config",
89 "/usr/X11/lib/X11/fs/config",
90 NULL
91 };
c9983ee8 92
93 // Although fontconfig library can be built for various platforms,
94 // practically it is useful only on desktop Linux distributions, where it is always packaged.
95 #include <fontconfig/fontconfig.h>
264abd72 96 #endif
aff395a3 97
98 #ifdef __APPLE__
99 // default fonts paths in Mac OS X
100 static Standard_CString myDefaultFontsDirs[] = {"/System/Library/Fonts",
101 "/Library/Fonts",
102 NULL
103 };
104 #else
105 // default fonts paths in most Unix systems (Linux and others)
65360da3 106 static Standard_CString myDefaultFontsDirs[] = {"/system/fonts", // Android
107 "/usr/share/fonts",
aff395a3 108 "/usr/local/share/fonts",
109 NULL
110 };
111 #endif
112
113 static void addDirsRecursively (const OSD_Path& thePath,
114 NCollection_Map<TCollection_AsciiString>& theDirsMap)
7fd59977 115 {
aff395a3 116 TCollection_AsciiString aDirName;
117 thePath.SystemName (aDirName);
118 if (!theDirsMap.Add (aDirName))
119 {
120 return;
7fd59977 121 }
7fd59977 122
aff395a3 123 for (OSD_DirectoryIterator aDirIterator (thePath, "*"); aDirIterator.More(); aDirIterator.Next())
7fd59977 124 {
aff395a3 125 OSD_Path aChildDirPath;
126 aDirIterator.Values().Path (aChildDirPath);
127
128 TCollection_AsciiString aChildDirName;
129 aChildDirPath.SystemName (aChildDirName);
130 if (!aChildDirName.IsEqual (".") && !aChildDirName.IsEqual (".."))
131 {
132 aChildDirName = aDirName + "/" + aChildDirName;
133 OSD_Path aPath (aChildDirName);
134 addDirsRecursively (aPath, theDirsMap);
135 }
7fd59977 136 }
7fd59977 137 }
aff395a3 138
68858c7d 139 } // anonymous namespace
aff395a3 140
141#endif
142
9a90a452 143//! Retrieve font information.
144//! @param theFonts [out] list of validated fonts
145//! @param theFTLib [in] font library
146//! @param theFontPath [in] path to the file
147//! @param theFaceId [in] face id, or -1 to load all faces within the file
148//! @return TRUE if at least one font face has been detected
149static bool checkFont (NCollection_Sequence<Handle(Font_SystemFont)>& theFonts,
150 const Handle(Font_FTLibrary)& theFTLib,
151 const TCollection_AsciiString& theFontPath,
152 FT_Long theFaceId = -1)
aff395a3 153{
9a90a452 154 const FT_Long aFaceId = theFaceId != -1 ? theFaceId : 0;
aff395a3 155 FT_Face aFontFace;
9a90a452 156 FT_Error aFaceError = FT_New_Face (theFTLib->Instance(), theFontPath.ToCString(), aFaceId, &aFontFace);
aff395a3 157 if (aFaceError != FT_Err_Ok)
158 {
9a90a452 159 return false;
15e4e6a2 160 }
161 if (aFontFace->family_name == NULL // skip broken fonts (error in FreeType?)
162 || FT_Select_Charmap (aFontFace, ft_encoding_unicode) != 0) // Font_FTFont supports only UNICODE fonts
163 {
164 FT_Done_Face (aFontFace);
9a90a452 165 return false;
7fd59977 166 }
7fd59977 167
15e4e6a2 168 // FreeType decomposes font definition into Family Name and Style Name,
169 // so that fonts within the same Family and different Styles can be identified.
170 // OCCT Font Manager natively handles 4 basic styles: Regular, Bold, Italic and Bold+Italic.
171 // To include other non-standard Styles, their names can be appended to Family Name; for this, names of normal Styles should be removed.
172 TCollection_AsciiString aFamily (aFontFace->family_name);
173 TCollection_AsciiString aStyle (aFontFace->style_name != NULL ? aFontFace->style_name : "");
aff395a3 174 Font_FontAspect anAspect = Font_FA_Regular;
175 if (aFontFace->style_flags == (FT_STYLE_FLAG_ITALIC | FT_STYLE_FLAG_BOLD))
176 {
177 anAspect = Font_FA_BoldItalic;
15e4e6a2 178 const Standard_Integer aRemoveItalic = aStyle.Search ("Italic");
179 if (aRemoveItalic != -1)
180 {
181 aStyle.Remove (aRemoveItalic, 6);
182 }
183 else
184 {
185 // synonym
186 const Standard_Integer aRemoveOblique = aStyle.Search ("Oblique");
187 if (aRemoveOblique != -1)
188 {
189 aStyle.Remove (aRemoveOblique, 7);
190 }
191 }
192
193 const Standard_Integer aRemoveBold = aStyle.Search ("Bold");
194 if (aRemoveBold != -1)
195 {
196 aStyle.Remove (aRemoveBold, 4);
197 }
aff395a3 198 }
199 else if (aFontFace->style_flags == FT_STYLE_FLAG_ITALIC)
200 {
201 anAspect = Font_FA_Italic;
15e4e6a2 202 const Standard_Integer aRemoveItalic = aStyle.Search ("Italic");
203 if (aRemoveItalic != -1)
204 {
205 aStyle.Remove (aRemoveItalic, 6);
206 }
207 else
208 {
209 // synonym
210 const Standard_Integer aRemoveOblique = aStyle.Search ("Oblique");
211 if (aRemoveOblique != -1)
212 {
213 aStyle.Remove (aRemoveOblique, 7);
214 }
215 }
aff395a3 216 }
217 else if (aFontFace->style_flags == FT_STYLE_FLAG_BOLD)
218 {
219 anAspect = Font_FA_Bold;
15e4e6a2 220 const Standard_Integer aRemoveBold = aStyle.Search ("Bold");
221 if (aRemoveBold != -1)
222 {
223 aStyle.Remove (aRemoveBold, 4);
224 }
aff395a3 225 }
226
15e4e6a2 227 const Standard_Integer aRemoveReg = aStyle.Search ("Regular");
228 if (aRemoveReg != -1)
508643cf 229 {
15e4e6a2 230 aStyle.Remove (aRemoveReg, 7);
231 }
232 else
233 {
234 // synonym
235 const Standard_Integer aRemoveBook = aStyle.Search ("Book");
236 if (aRemoveBook != -1)
237 {
238 aStyle.Remove (aRemoveBook, 4);
239 }
508643cf 240 }
7fd59977 241
15e4e6a2 242 aStyle.LeftAdjust();
243 aStyle.RightAdjust();
244 for (;;)
245 {
246 // remove double spaces after removal of several keywords in-between, like "Condensed Bold Italic Oblique"
247 const Standard_Integer aRemoveSpace = aStyle.Search (" ");
248 if (aRemoveSpace == -1)
249 {
250 break;
251 }
252
253 aStyle.Remove (aRemoveSpace, 1);
254 }
255
256 if (!aStyle.IsEmpty())
257 {
258 aFamily = aFamily + " " + aStyle;
259 }
7fd59977 260
15e4e6a2 261 Handle(Font_SystemFont) aResult = new Font_SystemFont (aFamily);
9a90a452 262 aResult->SetFontPath (anAspect, theFontPath, (Standard_Integer )aFaceId);
15e4e6a2 263 // automatically identify some known single-line fonts
264 aResult->SetSingleStrokeFont (aResult->FontKey().StartsWith ("olf "));
9a90a452 265 theFonts.Append (aResult);
266
267 if (theFaceId < aFontFace->num_faces)
268 {
269 const FT_Long aNbInstances = aFontFace->style_flags >> 16;
270 for (FT_Long anInstIter = 1; anInstIter < aNbInstances; ++anInstIter)
271 {
272 const FT_Long aSubFaceId = aFaceId + (anInstIter << 16);
273 checkFont (theFonts, theFTLib, theFontPath, aSubFaceId);
274 }
275 }
276 if (theFaceId == -1)
277 {
278 for (FT_Long aFaceIter = 1; aFaceIter < aFontFace->num_faces; ++aFaceIter)
279 {
280 checkFont (theFonts, theFTLib, theFontPath, aFaceIter);
281 }
282 }
15e4e6a2 283
284 FT_Done_Face (aFontFace);
9a90a452 285 return true;
aff395a3 286}
7fd59977 287
aff395a3 288// =======================================================================
289// function : GetInstance
290// purpose :
291// =======================================================================
292Handle(Font_FontMgr) Font_FontMgr::GetInstance()
293{
eeaaaefb 294 static Handle(Font_FontMgr) _mgr;
aff395a3 295 if (_mgr.IsNull())
296 {
eeaaaefb 297 _mgr = new Font_FontMgr();
aff395a3 298 }
7fd59977 299
300 return _mgr;
7fd59977 301}
302
912761ea 303// =======================================================================
304// function : ToUseUnicodeSubsetFallback
305// purpose :
306// =======================================================================
307Standard_Boolean& Font_FontMgr::ToUseUnicodeSubsetFallback()
308{
309 static Standard_Boolean TheToUseUnicodeSubsetFallback = true;
310 return TheToUseUnicodeSubsetFallback;
311}
312
5b377041 313// =======================================================================
f5e758d2 314// function : AddFontAlias
315// purpose :
316// =======================================================================
317bool Font_FontMgr::AddFontAlias (const TCollection_AsciiString& theAliasName,
318 const TCollection_AsciiString& theFontName)
319{
320 TCollection_AsciiString anAliasName (theAliasName);
321 anAliasName.LowerCase();
322 Handle(Font_FontAliasSequence) anAliases;
323 if (!myFontAliases.Find (anAliasName, anAliases))
324 {
325 anAliases = new Font_FontAliasSequence();
326 myFontAliases.Bind (anAliasName, anAliases);
327 }
328
329 for (Font_FontAliasSequence::Iterator anAliasIter (*anAliases); anAliasIter.More(); anAliasIter.Next())
330 {
331 if (anAliasIter.Value().FontName.IsEqual (anAliasName))
332 {
333 return false;
334 }
335 }
336
337 anAliases->Append (Font_FontAlias (theFontName));
338 return true;
339}
340
341// =======================================================================
342// function : RemoveFontAlias
343// purpose :
344// =======================================================================
345bool Font_FontMgr::RemoveFontAlias (const TCollection_AsciiString& theAliasName,
346 const TCollection_AsciiString& theFontName)
347{
348 if (theAliasName.IsEmpty())
349 {
350 if (myFontAliases.IsEmpty())
351 {
352 return false;
353 }
354 myFontAliases.Clear();
355 return true;
356 }
357
358 TCollection_AsciiString anAliasName (theAliasName);
359 anAliasName.LowerCase();
360 Handle(Font_FontAliasSequence) anAliases;
361 if (!myFontAliases.Find (anAliasName, anAliases))
362 {
363 return false;
364 }
365
366 if (theFontName.IsEmpty())
367 {
368 myFontAliases.UnBind (anAliasName);
369 return true;
370 }
371
372 for (Font_FontAliasSequence::Iterator aFontIter (*anAliases); aFontIter.More(); aFontIter.Next())
373 {
374 if (aFontIter.Value().FontName.IsEqual (theFontName))
375 {
376 anAliases->Remove (aFontIter);
377 if (anAliases->IsEmpty())
378 {
379 myFontAliases.UnBind (anAliasName);
380 }
381 return true;
382 }
383 }
384 return false;
385}
386
387// =======================================================================
388// function : GetAllAliases
389// purpose :
390// =======================================================================
391void Font_FontMgr::GetAllAliases (TColStd_SequenceOfHAsciiString& theAliases) const
392{
393 for (NCollection_DataMap<TCollection_AsciiString, Handle(Font_FontAliasSequence)>::Iterator anAliasIter (myFontAliases);
394 anAliasIter.More(); anAliasIter.Next())
395 {
396 theAliases.Append (new TCollection_HAsciiString (anAliasIter.Key()));
397 }
398}
399
400// =======================================================================
401// function : GetFontAliases
402// purpose :
403// =======================================================================
404void Font_FontMgr::GetFontAliases (TColStd_SequenceOfHAsciiString& theFontNames,
405 const TCollection_AsciiString& theAliasName) const
406{
407 TCollection_AsciiString anAliasName (theAliasName);
408 anAliasName.LowerCase();
409 Handle(Font_FontAliasSequence) anAliases;
410 if (!myFontAliases.Find (anAliasName, anAliases))
411 {
412 return;
413 }
414
415 for (Font_FontAliasSequence::Iterator aFontIter (*anAliases); aFontIter.More(); aFontIter.Next())
416 {
417 theFontNames.Append (new TCollection_HAsciiString (aFontIter.Value().FontName));
418 }
419}
420
421// =======================================================================
5b377041 422// function : addFontAlias
423// purpose :
424// =======================================================================
425void Font_FontMgr::addFontAlias (const TCollection_AsciiString& theAliasName,
426 const Handle(Font_FontAliasSequence)& theAliases,
427 Font_FontAspect theAspect)
428{
429 if (theAliases.IsNull()
430 || theAliases->IsEmpty())
431 {
432 return;
433 }
434
435 Handle(Font_FontAliasSequence) anAliases = theAliases;
436 if (theAspect != Font_FA_Undefined)
437 {
438 anAliases = new Font_FontAliasSequence();
439 for (Font_FontAliasSequence::Iterator anAliasIter (*theAliases); anAliasIter.More(); anAliasIter.Next())
440 {
441 const TCollection_AsciiString& aName = anAliasIter.Value().FontName;
442 anAliases->Append (Font_FontAlias (aName, theAspect));
443 }
444 }
445
446 TCollection_AsciiString anAliasName (theAliasName);
447 anAliasName.LowerCase();
448 myFontAliases.Bind (anAliasName, anAliases);
449}
450
aff395a3 451// =======================================================================
452// function : Font_FontMgr
453// purpose :
454// =======================================================================
455Font_FontMgr::Font_FontMgr()
5b377041 456: myToTraceAliases (Standard_False)
aff395a3 457{
5b377041 458 Handle(Font_FontAliasSequence) aMono = new Font_FontAliasSequence();
459 Handle(Font_FontAliasSequence) aSerif = new Font_FontAliasSequence();
460 Handle(Font_FontAliasSequence) aSans = new Font_FontAliasSequence();
461 Handle(Font_FontAliasSequence) aSymbol = new Font_FontAliasSequence();
462 Handle(Font_FontAliasSequence) aScript = new Font_FontAliasSequence();
463 Handle(Font_FontAliasSequence) aWinDin = new Font_FontAliasSequence();
464 Handle(Font_FontAliasSequence) anIris = new Font_FontAliasSequence();
465 Handle(Font_FontAliasSequence) aCJK = new Font_FontAliasSequence();
466 Handle(Font_FontAliasSequence) aKorean = new Font_FontAliasSequence();
912761ea 467 Handle(Font_FontAliasSequence) anArab = new Font_FontAliasSequence();
5b377041 468
469 // best matches - pre-installed on Windows, some of them are pre-installed on macOS,
470 // and sometimes them can be found installed on other systems (by user)
471 aMono ->Append (Font_FontAlias ("courier new"));
472 aSerif ->Append (Font_FontAlias ("times new roman"));
473 aSans ->Append (Font_FontAlias ("arial"));
474 aSymbol->Append (Font_FontAlias ("symbol"));
475 aScript->Append (Font_FontAlias ("script"));
476 aWinDin->Append (Font_FontAlias ("wingdings"));
477 anIris ->Append (Font_FontAlias ("lucida console"));
478
479#if defined(__ANDROID__)
480 // Noto font family is usually installed on Android 6+ devices
481 aMono ->Append (Font_FontAlias ("noto mono"));
482 aSerif ->Append (Font_FontAlias ("noto serif"));
483 // Droid font family is usually installed on Android 4+ devices
484 aMono ->Append (Font_FontAlias ("droid sans mono"));
485 aSerif ->Append (Font_FontAlias ("droid serif"));
486 aSans ->Append (Font_FontAlias ("roboto")); // actually DroidSans.ttf
487#elif !defined(_WIN32) && !defined(__APPLE__) //X11
488 aSerif ->Append (Font_FontAlias ("times"));
489 aSans ->Append (Font_FontAlias ("helvetica"));
490 // GNU FreeFonts family is usually installed on Linux
491 aMono ->Append (Font_FontAlias ("freemono"));
492 aSerif ->Append (Font_FontAlias ("freeserif"));
493 aSans ->Append (Font_FontAlias ("freesans"));
494 // DejaVu font family is usually installed on Linux
495 aMono ->Append (Font_FontAlias ("dejavu sans mono"));
496 aSerif ->Append (Font_FontAlias ("dejavu serif"));
497 aSans ->Append (Font_FontAlias ("dejavu sans"));
498#endif
499
500 // default CJK (Chinese/Japanese/Korean) fonts
501 aCJK ->Append (Font_FontAlias ("simsun")); // Windows
502 aCJK ->Append (Font_FontAlias ("droid sans fallback")); // Android, Linux
503 aCJK ->Append (Font_FontAlias ("noto sans sc")); // Android
1d99a2ba 504 aCJK ->Append (Font_FontAlias ("noto sans cjk jp"));
5b377041 505
506#if defined(_WIN32)
507 aKorean->Append (Font_FontAlias ("malgun gothic")); // introduced since Vista
508 aKorean->Append (Font_FontAlias ("gulim")); // used on older systems (Windows XP)
509#elif defined(__APPLE__)
510 aKorean->Append (Font_FontAlias ("applegothic"));
511 aKorean->Append (Font_FontAlias ("stfangsong"));
512#endif
513 aKorean->Append (Font_FontAlias ("nanumgothic")); // Android, Linux
514 aKorean->Append (Font_FontAlias ("noto sans kr")); // Android
515 aKorean->Append (Font_FontAlias ("nanummyeongjo")); // Linux
516 aKorean->Append (Font_FontAlias ("noto serif cjk jp")); // Linux
517 aKorean->Append (Font_FontAlias ("noto sans cjk jp")); // Linux
36e28f96 518 aKorean->Append (Font_FontAlias ("droid sans fallback")); // Linux
5b377041 519
912761ea 520#if defined(_WIN32)
521 anArab->Append (Font_FontAlias ("times new roman"));
522#elif defined(__APPLE__)
523 anArab->Append (Font_FontAlias ("decotype naskh"));
524#elif defined(__ANDROID__)
525 anArab->Append (Font_FontAlias ("droid arabic naskh"));
526 anArab->Append (Font_FontAlias ("noto naskh arabic"));
527#endif
528
5b377041 529 addFontAlias ("mono", aMono);
530 addFontAlias ("courier", aMono); // Font_NOF_ASCII_MONO
531 addFontAlias ("monospace", aMono); // Font_NOF_MONOSPACE
532 addFontAlias ("rock", aSans); // Font_NOF_CARTOGRAPHIC_SIMPLEX
533 addFontAlias ("sansserif", aSans); // Font_NOF_SANS_SERIF
534 addFontAlias ("sans-serif", aSans);
535 addFontAlias ("sans", aSans);
536 addFontAlias ("arial", aSans);
537 addFontAlias ("times", aSerif);
538 addFontAlias ("serif", aSerif); // Font_NOF_SERIF
539 addFontAlias ("times-roman", aSerif); // Font_NOF_ASCII_SIMPLEX
540 addFontAlias ("times-bold", aSerif, Font_FA_Bold); // Font_NOF_ASCII_DUPLEX
541 addFontAlias ("times-italic", aSerif, Font_FA_Italic); // Font_NOF_ASCII_ITALIC_COMPLEX
542 addFontAlias ("times-bolditalic", aSerif, Font_FA_BoldItalic); // Font_NOF_ASCII_ITALIC_TRIPLEX
543 addFontAlias ("symbol", aSymbol); // Font_NOF_GREEK_MONO
544 addFontAlias ("iris", anIris); // Font_NOF_KANJI_MONO
545 addFontAlias ("korean", aKorean); // Font_NOF_KOREAN
546 addFontAlias ("cjk", aCJK); // Font_NOF_CJK
547 addFontAlias ("nsimsun", aCJK);
912761ea 548 addFontAlias ("arabic", anArab); // Font_NOF_ARABIC
5b377041 549 addFontAlias (Font_NOF_SYMBOL_MONO, aWinDin);
550 addFontAlias (Font_NOF_ASCII_SCRIPT_SIMPLEX, aScript);
551
552 myFallbackAlias = aSans;
553
7fd59977 554 InitFontDataBase();
7fd59977 555}
556
9a90a452 557// =======================================================================
558// function : CheckFont
559// purpose :
560// =======================================================================
561Standard_Boolean Font_FontMgr::CheckFont (NCollection_Sequence<Handle(Font_SystemFont)>& theFonts,
562 const TCollection_AsciiString& theFontPath) const
563{
564 Handle(Font_FTLibrary) aFtLibrary = new Font_FTLibrary();
565 return checkFont (theFonts, aFtLibrary, theFontPath, 0);
566}
567
725ef85e 568// =======================================================================
569// function : CheckFont
570// purpose :
571// =======================================================================
572Handle(Font_SystemFont) Font_FontMgr::CheckFont (Standard_CString theFontPath) const
573{
574 Handle(Font_FTLibrary) aFtLibrary = new Font_FTLibrary();
9a90a452 575 NCollection_Sequence<Handle(Font_SystemFont)> aFonts;
576 return checkFont (aFonts, aFtLibrary, theFontPath, 0)
577 ? aFonts.First()
578 : Handle(Font_SystemFont)();
725ef85e 579}
580
581// =======================================================================
582// function : RegisterFont
583// purpose :
584// =======================================================================
585Standard_Boolean Font_FontMgr::RegisterFont (const Handle(Font_SystemFont)& theFont,
586 const Standard_Boolean theToOverride)
587{
588 if (theFont.IsNull())
589 {
590 return Standard_False;
591 }
592
5b377041 593 const Standard_Integer anOldIndex = myFontMap.FindIndex (theFont);
594 if (anOldIndex == 0)
595 {
596 myFontMap.Add (theFont);
597 return Standard_True;
598 }
599
600 Handle(Font_SystemFont) anOldFont = myFontMap.FindKey (anOldIndex);
601 for (int anAspectIter = 0; anAspectIter < Font_FontAspect_NB; ++anAspectIter)
725ef85e 602 {
9a90a452 603 if (anOldFont->FontPath ((Font_FontAspect )anAspectIter).IsEqual (theFont->FontPath ((Font_FontAspect )anAspectIter))
604 && anOldFont->FontFaceId ((Font_FontAspect )anAspectIter) == theFont->FontFaceId ((Font_FontAspect )anAspectIter))
725ef85e 605 {
606 continue;
607 }
5b377041 608 else if (theToOverride
609 || !anOldFont->HasFontAspect ((Font_FontAspect )anAspectIter))
725ef85e 610 {
9a90a452 611 anOldFont->SetFontPath ((Font_FontAspect )anAspectIter,
612 theFont->FontPath ((Font_FontAspect )anAspectIter),
613 theFont->FontFaceId ((Font_FontAspect )anAspectIter));
725ef85e 614 }
5b377041 615 else if (theFont->HasFontAspect ((Font_FontAspect )anAspectIter))
725ef85e 616 {
5b377041 617 return Standard_False;
725ef85e 618 }
619 }
725ef85e 620 return Standard_True;
621}
622
36e28f96 623// =======================================================================
624// function : ClearFontDataBase()
625// purpose :
626// =======================================================================
627void Font_FontMgr::ClearFontDataBase()
628{
629 myFontMap.Clear();
630}
631
aff395a3 632// =======================================================================
633// function : InitFontDataBase
634// purpose :
635// =======================================================================
636void Font_FontMgr::InitFontDataBase()
637{
5b377041 638 myFontMap.Clear();
c9983ee8 639 Handle(Font_FTLibrary) aFtLibrary = new Font_FTLibrary();
9a90a452 640 NCollection_Sequence<Handle(Font_SystemFont)> aFonts;
7fd59977 641
1ce0716b 642#if defined(OCCT_UWP)
643 // system font files are not accessible
644 (void )aFtLibrary;
645#elif defined(_WIN32)
7fd59977 646
aff395a3 647 // font directory is placed in "C:\Windows\Fonts\"
648 UINT aStrLength = GetSystemWindowsDirectoryA (NULL, 0);
649 if (aStrLength == 0)
a6535b1d 650 {
aff395a3 651 return;
a6535b1d 652 }
aff395a3 653
654 char* aWinDir = new char[aStrLength];
655 GetSystemWindowsDirectoryA (aWinDir, aStrLength);
5b377041 656 TCollection_AsciiString aFontsDir (aWinDir);
657 aFontsDir.AssignCat ("\\Fonts\\");
aff395a3 658 delete[] aWinDir;
659
660 // read fonts list from registry
661 HKEY aFontsKey;
662 if (RegOpenKeyExA (HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Fonts",
663 0, KEY_READ, &aFontsKey) != ERROR_SUCCESS)
7fd59977 664 {
665 return;
7fd59977 666 }
7fd59977 667
aff395a3 668 NCollection_Map<TCollection_AsciiString> aSupportedExtensions;
669 for (Standard_Integer anIter = 0; Font_FontMgr_Extensions[anIter] != NULL; ++anIter)
7fd59977 670 {
aff395a3 671 Standard_CString anExt = Font_FontMgr_Extensions[anIter];
672 aSupportedExtensions.Add (TCollection_AsciiString (anExt));
7fd59977 673 }
674
aff395a3 675 static const DWORD aBufferSize = 256;
676 char aNameBuff[aBufferSize];
677 char aPathBuff[aBufferSize];
678 DWORD aNameSize = aBufferSize;
679 DWORD aPathSize = aBufferSize;
680 for (DWORD anIter = 0;
681 RegEnumValueA (aFontsKey, anIter,
682 aNameBuff, &aNameSize, NULL, NULL,
683 (LPBYTE )aPathBuff, &aPathSize) != ERROR_NO_MORE_ITEMS;
684 ++anIter, aNameSize = aBufferSize, aPathSize = aBufferSize)
685 {
686 aPathBuff[(aPathSize < aBufferSize) ? aPathSize : (aBufferSize - 1)] = '\0'; // ensure string is NULL-terminated
7fd59977 687
5b377041 688 TCollection_AsciiString aFontName (aNameBuff), aFontPath (aPathBuff);
689 if (aFontPath.Search ("\\") == -1)
aff395a3 690 {
5b377041 691 aFontPath.Insert (1, aFontsDir); // make absolute path
7fd59977 692 }
aff395a3 693
694 // check file extension is in list of supported
5b377041 695 const Standard_Integer anExtensionPosition = aFontPath.SearchFromEnd (".") + 1;
696 if (anExtensionPosition > 0 && anExtensionPosition < aFontPath.Length())
7fd59977 697 {
5b377041 698 TCollection_AsciiString aFontExtension = aFontPath.SubString (anExtensionPosition, aFontPath.Length());
699 aFontExtension.LowerCase();
700 if (aSupportedExtensions.Contains (aFontExtension))
aff395a3 701 {
9a90a452 702 aFonts.Clear();
703 checkFont (aFonts, aFtLibrary, aFontPath.ToCString());
704 RegisterFonts (aFonts, false);
aff395a3 705 }
7fd59977 706 }
707 }
7fd59977 708
aff395a3 709 // close registry key
710 RegCloseKey (aFontsKey);
711
712#else
7fd59977 713
aff395a3 714 NCollection_Map<TCollection_AsciiString> aMapOfFontsDirs;
565baee6 715#if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
c9983ee8 716 if (FcConfig* aFcCfg = FcInitLoadConfig())
7fd59977 717 {
c9983ee8 718 if (FcStrList* aFcFontDir = FcConfigGetFontDirs (aFcCfg))
aff395a3 719 {
c9983ee8 720 for (;;)
721 {
722 FcChar8* aFcFolder = FcStrListNext (aFcFontDir);
723 if (aFcFolder == NULL)
724 {
725 break;
726 }
7fd59977 727
c9983ee8 728 TCollection_AsciiString aPathStr ((const char* )aFcFolder);
729 OSD_Path aPath (aPathStr);
730 addDirsRecursively (aPath, aMapOfFontsDirs);
731 }
732 FcStrListDone (aFcFontDir);
aff395a3 733 }
c9983ee8 734 FcConfigDestroy (aFcCfg);
735 }
736
737 const OSD_Protection aProtectRead (OSD_R, OSD_R, OSD_R, OSD_R);
738 if (aMapOfFontsDirs.IsEmpty())
739 {
a87b1b37 740 Message::SendAlarm ("Font_FontMgr, fontconfig library returns an empty folder list");
aff395a3 741
c9983ee8 742 // read fonts directories from font service config file (obsolete)
743 for (Standard_Integer anIter = 0; myFontServiceConf[anIter] != NULL; ++anIter)
7fd59977 744 {
c9983ee8 745 const TCollection_AsciiString aFileOfFontsPath (myFontServiceConf[anIter]);
746 OSD_File aFile (aFileOfFontsPath);
747 if (!aFile.Exists())
748 {
749 continue;
750 }
aff395a3 751
c9983ee8 752 aFile.Open (OSD_ReadOnly, aProtectRead);
753 if (!aFile.IsOpen())
aff395a3 754 {
c9983ee8 755 continue;
aff395a3 756 }
757
c9983ee8 758 Standard_Integer aNByte = 256;
759 Standard_Integer aNbyteRead;
760 TCollection_AsciiString aStr; // read string with information
761 while (!aFile.IsAtEnd())
7fd59977 762 {
c9983ee8 763 Standard_Integer aLocation = -1;
764 Standard_Integer aPathLocation = -1;
765
766 aFile.ReadLine (aStr, aNByte, aNbyteRead); // reading 1 line (256 bytes)
767 aLocation = aStr.Search ("catalogue=");
768 if (aLocation < 0)
769 {
770 aLocation = aStr.Search ("catalogue =");
771 }
772
773 aPathLocation = aStr.Search ("/");
774 if (aLocation > 0 && aPathLocation > 0)
7fd59977 775 {
c9983ee8 776 aStr = aStr.Split (aPathLocation - 1);
777 TCollection_AsciiString aFontPath;
778 Standard_Integer aPathNumber = 1;
779 do
7fd59977 780 {
c9983ee8 781 // Getting directory paths, which can be splitted by "," or ":"
782 aFontPath = aStr.Token (":,", aPathNumber);
783 aFontPath.RightAdjust();
784 if (!aFontPath.IsEmpty())
785 {
786 OSD_Path aPath(aFontPath);
787 addDirsRecursively (aPath, aMapOfFontsDirs);
788 }
789 aPathNumber++;
7fd59977 790 }
c9983ee8 791 while (!aFontPath.IsEmpty());
aff395a3 792 }
7fd59977 793 }
c9983ee8 794 aFile.Close();
7fd59977 795 }
796 }
264abd72 797#endif
7fd59977 798
aff395a3 799 // append default directories
800 for (Standard_Integer anIter = 0; myDefaultFontsDirs[anIter] != NULL; ++anIter)
801 {
802 Standard_CString anItem = myDefaultFontsDirs[anIter];
803 TCollection_AsciiString aPathStr (anItem);
804 OSD_Path aPath (aPathStr);
805 addDirsRecursively (aPath, aMapOfFontsDirs);
806 }
807
808 NCollection_Map<TCollection_AsciiString> aSupportedExtensions;
809 for (Standard_Integer anIter = 0; Font_FontMgr_Extensions[anIter] != NULL; ++anIter)
810 {
811 Standard_CString anExt = Font_FontMgr_Extensions[anIter];
812 aSupportedExtensions.Add (TCollection_AsciiString (anExt));
813 }
814
aff395a3 815 for (NCollection_Map<TCollection_AsciiString>::Iterator anIter (aMapOfFontsDirs);
816 anIter.More(); anIter.Next())
817 {
565baee6 818 #if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
5b377041 819 OSD_File aReadFile (anIter.Value() + "/fonts.dir");
820 if (!aReadFile.Exists())
65360da3 821 {
5b377041 822 #endif
823 OSD_Path aFolderPath (anIter.Value());
824 for (OSD_FileIterator aFileIter (aFolderPath, "*"); aFileIter.More(); aFileIter.Next())
825 {
826 OSD_Path aFontFilePath;
827 aFileIter.Values().Path (aFontFilePath);
65360da3 828
5b377041 829 TCollection_AsciiString aFontFileName;
830 aFontFilePath.SystemName (aFontFileName);
831 aFontFileName = anIter.Value() + "/" + aFontFileName;
65360da3 832
9a90a452 833 aFonts.Clear();
834 checkFont (aFonts, aFtLibrary, aFontFileName);
835 RegisterFonts (aFonts, false);
65360da3 836 }
5b377041 837
565baee6 838 #if !defined(__ANDROID__) && !defined(__APPLE__) && !defined(__EMSCRIPTEN__)
5b377041 839 continue;
aff395a3 840 }
841
842 aReadFile.Open (OSD_ReadOnly, aProtectRead);
843 if (!aReadFile.IsOpen())
844 {
845 continue; // invalid fonts directory
846 }
847
848 Standard_Integer aNbyteRead, aNByte = 256;
849 TCollection_AsciiString aLine (aNByte);
850 Standard_Boolean isFirstLine = Standard_True;
851 const TCollection_AsciiString anEncoding ("iso8859-1\n");
852 while (!aReadFile.IsAtEnd())
853 {
854 aReadFile.ReadLine (aLine, aNByte, aNbyteRead);
855 if (isFirstLine)
856 {
857 // first line contains the number of fonts in this file
858 // just ignoring it...
859 isFirstLine = Standard_False;
860 continue;
861 }
7fd59977 862
aff395a3 863 Standard_Integer anExtensionPosition = aLine.Search (".") + 1;
864 if (anExtensionPosition == 0)
865 {
866 continue; // can't find extension position in the font description
867 }
7fd59977 868
aff395a3 869 Standard_Integer anEndOfFileName = aLine.Location (" ", anExtensionPosition, aLine.Length()) - 1;
870 if (anEndOfFileName < 0 || anEndOfFileName < anExtensionPosition)
871 {
872 continue; // font description have empty extension
873 }
7fd59977 874
aff395a3 875 TCollection_AsciiString aFontExtension = aLine.SubString (anExtensionPosition, anEndOfFileName);
876 aFontExtension.LowerCase();
877 if (aSupportedExtensions.Contains (aFontExtension) && (aLine.Search (anEncoding) > 0))
7fd59977 878 {
aff395a3 879 // In current implementation use fonts with ISO-8859-1 coding page.
880 // OCCT not give to manage coding page by means of programm interface.
881 // TODO: make high level interface for choosing necessary coding page.
5b377041 882 TCollection_AsciiString aXLFD (aLine.SubString (anEndOfFileName + 2, aLine.Length()));
883 TCollection_AsciiString aFontPath (anIter.Value().ToCString());
884 if (aFontPath.SearchFromEnd ("/") != aFontPath.Length())
aff395a3 885 {
5b377041 886 aFontPath.AssignCat ("/");
aff395a3 887 }
5b377041 888 TCollection_AsciiString aFontFileName (aLine.SubString (1, anEndOfFileName));
889 aFontPath.AssignCat (aFontFileName);
9a90a452 890
891 aFonts.Clear();
892 if (checkFont (aFonts, aFtLibrary, aFontPath))
aff395a3 893 {
9a90a452 894 RegisterFonts (aFonts, false);
895 const Handle(Font_SystemFont)& aNewFont = aFonts.First();
5b377041 896 if (!aXLFD.IsEmpty()
897 && aXLFD.Search ("-0-0-0-0-") != -1) // ignore non-resizable fonts
898 {
899 const TCollection_AsciiString anXName = aXLFD.Token ("-", 2);
900 Font_FontAspect anXAspect = Font_FA_Regular;
901 if (aXLFD.Token ("-", 3).IsEqual ("bold")
902 && (aXLFD.Token ("-", 4).IsEqual ("i")
903 || aXLFD.Token ("-", 4).IsEqual ("o")))
904 {
905 anXAspect = Font_FA_BoldItalic;
906 }
907 else if (aXLFD.Token ("-", 3).IsEqual ("bold"))
908 {
909 anXAspect = Font_FA_Bold;
910 }
911 else if (aXLFD.Token ("-", 4).IsEqual ("i")
912 || aXLFD.Token ("-", 4).IsEqual ("o"))
913 {
914 anXAspect = Font_FA_Italic;
915 }
916
917 Handle(Font_SystemFont) aNewFontFromXLFD = new Font_SystemFont (anXName);
9a90a452 918 aNewFontFromXLFD->SetFontPath (anXAspect, aFontPath, 0);
5b377041 919 if (!aNewFont->IsEqual (aNewFontFromXLFD))
920 {
921 RegisterFont (aNewFontFromXLFD, false);
922 }
923 }
aff395a3 924 }
aff395a3 925 }
7fd59977 926 }
aff395a3 927 aReadFile.Close();
65360da3 928 #endif
7fd59977 929 }
930#endif
aff395a3 931}
932
b514beda 933// =======================================================================
934// function : GetAvailableFontsNames
935// purpose :
936// =======================================================================
aff395a3 937void Font_FontMgr::GetAvailableFontsNames (TColStd_SequenceOfHAsciiString& theFontsNames) const
938{
939 theFontsNames.Clear();
5b377041 940 for (NCollection_IndexedMap<Handle(Font_SystemFont), Font_SystemFont>::Iterator aFontIter (myFontMap);
941 aFontIter.More(); aFontIter.Next())
aff395a3 942 {
5b377041 943 const Handle(Font_SystemFont)& aFont = aFontIter.Value();
944 theFontsNames.Append (new TCollection_HAsciiString(aFont->FontName()));
aff395a3 945 }
7fd59977 946}
947
b514beda 948// =======================================================================
949// function : GetFont
950// purpose :
951// =======================================================================
aff395a3 952Handle(Font_SystemFont) Font_FontMgr::GetFont (const Handle(TCollection_HAsciiString)& theFontName,
b514beda 953 const Font_FontAspect theFontAspect,
aff395a3 954 const Standard_Integer theFontSize) const
7fd59977 955{
5b377041 956 if ((theFontSize < 2 && theFontSize != -1) || theFontName.IsNull())
aff395a3 957 {
5b377041 958 return Handle(Font_SystemFont)();
aff395a3 959 }
960
5b377041 961 Handle(Font_SystemFont) aFont = myFontMap.Find (theFontName->String());
962 return (aFont.IsNull()
963 || theFontAspect == Font_FontAspect_UNDEFINED
964 || aFont->HasFontAspect (theFontAspect))
965 ? aFont
966 : Handle(Font_SystemFont)();
967}
aff395a3 968
5b377041 969// =======================================================================
970// function : GetFont
971// purpose :
972// =======================================================================
973Handle(Font_SystemFont) Font_FontMgr::GetFont (const TCollection_AsciiString& theFontName) const
974{
975 return myFontMap.Find (theFontName);
7fd59977 976}
977
912761ea 978// =======================================================================
979// function : FindFallbackFont
980// purpose :
981// =======================================================================
982Handle(Font_SystemFont) Font_FontMgr::FindFallbackFont (Font_UnicodeSubset theSubset,
983 Font_FontAspect theFontAspect) const
984{
985 Font_FontAspect aFontAspect = theFontAspect;
36e28f96 986 Handle(Font_SystemFont) aFont;
912761ea 987 switch (theSubset)
988 {
36e28f96 989 case Font_UnicodeSubset_Western: aFont = FindFont (Font_NOF_SANS_SERIF, Font_StrictLevel_Aliases, aFontAspect, false); break;
990 case Font_UnicodeSubset_Korean: aFont = FindFont (Font_NOF_KOREAN, Font_StrictLevel_Aliases, aFontAspect, false); break;
991 case Font_UnicodeSubset_CJK: aFont = FindFont (Font_NOF_CJK, Font_StrictLevel_Aliases, aFontAspect, false); break;
992 case Font_UnicodeSubset_Arabic: aFont = FindFont (Font_NOF_ARABIC, Font_StrictLevel_Aliases, aFontAspect, false); break;
912761ea 993 }
36e28f96 994 if (aFont.IsNull())
995 {
996 const char* aRange = "";
997 switch (theSubset)
998 {
999 case Font_UnicodeSubset_Western: aRange = "Western"; break;
1000 case Font_UnicodeSubset_Korean: aRange = "Korean"; break;
1001 case Font_UnicodeSubset_CJK: aRange = "CJK"; break;
1002 case Font_UnicodeSubset_Arabic: aRange = "Arabic"; break;
1003 }
a87b1b37 1004 Message::SendFail (TCollection_AsciiString("Font_FontMgr, error: unable to find ") + aRange + " fallback font!");
36e28f96 1005 }
1006 return aFont;
912761ea 1007}
1008
b514beda 1009// =======================================================================
1010// function : FindFont
1011// purpose :
1012// =======================================================================
5b377041 1013Handle(Font_SystemFont) Font_FontMgr::FindFont (const TCollection_AsciiString& theFontName,
1bbd7c79 1014 Font_StrictLevel theStrictLevel,
36e28f96 1015 Font_FontAspect& theFontAspect,
1016 Standard_Boolean theDoFailMsg) const
aff395a3 1017{
5b377041 1018 TCollection_AsciiString aFontName (theFontName);
1019 aFontName.LowerCase();
1020 Handle(Font_SystemFont) aFont = myFontMap.Find (aFontName);
1bbd7c79 1021 if (!aFont.IsNull()
1022 || theStrictLevel == Font_StrictLevel_Strict)
aff395a3 1023 {
1024 return aFont;
1025 }
1026
1027 // Trying to use font names mapping
976627e6 1028 for (int aPass = 0; aPass < 2; ++aPass)
aff395a3 1029 {
976627e6 1030 Handle(Font_FontAliasSequence) anAliases;
1031 if (aPass == 0)
1032 {
1033 myFontAliases.Find (aFontName, anAliases);
1034 }
1bbd7c79 1035 else if (theStrictLevel == Font_StrictLevel_Any)
976627e6 1036 {
1037 anAliases = myFallbackAlias;
1038 }
aff395a3 1039
976627e6 1040 if (anAliases.IsNull()
1041 || anAliases->IsEmpty())
1042 {
1043 continue;
1044 }
1045
1046 bool isAliasUsed = false, isBestAlias = false;
5b377041 1047 for (Font_FontAliasSequence::Iterator anAliasIter (*anAliases); anAliasIter.More(); anAliasIter.Next())
b514beda 1048 {
5b377041 1049 const Font_FontAlias& anAlias = anAliasIter.Value();
1050 if (Handle(Font_SystemFont) aFont2 = myFontMap.Find (anAlias.FontName))
1051 {
1052 if (aFont.IsNull())
1053 {
1054 aFont = aFont2;
1055 isAliasUsed = true;
1056 }
1057
1058 if ((anAlias.FontAspect != Font_FontAspect_UNDEFINED
1059 && aFont2->HasFontAspect (anAlias.FontAspect)))
1060 {
1061 // special case - alias refers to styled font (e.g. "times-bold")
1062 isBestAlias = true;
1063 theFontAspect = anAlias.FontAspect;
1064 break;
1065 }
1066 else if (anAlias.FontAspect == Font_FontAspect_UNDEFINED
1067 && (theFontAspect == Font_FontAspect_UNDEFINED
976627e6 1068 || aFont2->HasFontAspect (theFontAspect)))
5b377041 1069 {
1070 isBestAlias = true;
1071 break;
1072 }
1073 }
1074 }
976627e6 1075
1076 if (aPass == 0)
5b377041 1077 {
1078 if (isAliasUsed && myToTraceAliases)
1079 {
a87b1b37 1080 Message::SendTrace (TCollection_AsciiString("Font_FontMgr, using font alias '") + aFont->FontName() + "'"
1081 " instead of requested '" + theFontName + "'");
5b377041 1082 }
1083 if (isBestAlias)
1084 {
1085 return aFont;
1086 }
976627e6 1087 else if (!aFont.IsNull())
1088 {
1089 break;
1090 }
b514beda 1091 }
1092 }
aff395a3 1093
912761ea 1094 if (aFont.IsNull()
1095 && theStrictLevel == Font_StrictLevel_Any)
aff395a3 1096 {
5b377041 1097 // try finding ANY font in case if even default fallback alias myFallbackAlias cannot be found
1098 aFont = myFontMap.Find (TCollection_AsciiString());
1099 }
1100 if (aFont.IsNull())
1101 {
36e28f96 1102 if (theDoFailMsg)
1103 {
a87b1b37 1104 Message::SendFail ("Font_FontMgr, error: unable to find any font!");
36e28f96 1105 }
5b377041 1106 return Handle(Font_SystemFont)();
aff395a3 1107 }
1108
5b377041 1109 if ((theFontAspect != Font_FA_Undefined
1110 && !aFont->HasFontAspect (theFontAspect))
1111 || (!aFontName.IsEmpty()
1112 && !aFontName.IsEqual (aFont->FontKey())))
aff395a3 1113 {
5b377041 1114 TCollection_AsciiString aDesc = TCollection_AsciiString() + "'" + theFontName + "'"
1115 + TCollection_AsciiString() + " [" + Font_FontMgr::FontAspectToString (theFontAspect) + "]";
a87b1b37 1116 Message::SendWarning (TCollection_AsciiString("Font_FontMgr, warning: unable to find font ")
1117 + aDesc + "; " + aFont->ToString() + " is used instead");
aff395a3 1118 }
5b377041 1119 return aFont;
1120}
aff395a3 1121
5b377041 1122// =======================================================================
1123// function : Font_FontMap::Find
1124// purpose :
1125// =======================================================================
1126Handle(Font_SystemFont) Font_FontMgr::Font_FontMap::Find (const TCollection_AsciiString& theFontName) const
1127{
1128 if (IsEmpty())
aff395a3 1129 {
5b377041 1130 return Handle(Font_SystemFont)();
1131 }
1132 else if (theFontName.IsEmpty())
1133 {
1134 return FindKey (1); // return any font
aff395a3 1135 }
1136
5b377041 1137 TCollection_AsciiString aFontName (theFontName);
1138 aFontName.LowerCase();
1139 for (IndexedMapNode* aNodeIter = (IndexedMapNode* )myData1[::HashCode (aFontName, NbBuckets())];
1140 aNodeIter != NULL; aNodeIter = (IndexedMapNode* )aNodeIter->Next())
1141 {
1142 const Handle(Font_SystemFont)& aKey = aNodeIter->Key1();
1143 if (aKey->FontKey().IsEqual (aFontName))
1144 {
1145 return aKey;
1146 }
1147 }
1148 return Handle(Font_SystemFont)();
aff395a3 1149}
21095f2d 1150
1151// =======================================================================
1152// function : EmbedFallbackFont
1153// purpose :
1154// =======================================================================
1155Handle(NCollection_Buffer) Font_FontMgr::EmbedFallbackFont()
1156{
1157 return new NCollection_Buffer (Handle(NCollection_BaseAllocator)(),
1158 Font_DejavuSans_Latin_woff_size,
1159 const_cast<Standard_Byte*>(Font_DejavuSans_Latin_woff));
1160}