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 |
35 | IMPLEMENT_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 |
149 | static 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 | // ======================================================================= |
292 | Handle(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 | // ======================================================================= |
307 | Standard_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 | // ======================================================================= |
317 | bool 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 | // ======================================================================= |
345 | bool 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 | // ======================================================================= |
391 | void 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 | // ======================================================================= |
404 | void 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 | // ======================================================================= |
425 | void 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 | // ======================================================================= |
455 | Font_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 | // ======================================================================= |
561 | Standard_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 | // ======================================================================= |
572 | Handle(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 | // ======================================================================= |
585 | Standard_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 | // ======================================================================= |
627 | void Font_FontMgr::ClearFontDataBase() |
628 | { |
629 | myFontMap.Clear(); |
630 | } |
631 | |
aff395a3 |
632 | // ======================================================================= |
633 | // function : InitFontDataBase |
634 | // purpose : |
635 | // ======================================================================= |
636 | void 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 |
937 | void 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 |
952 | Handle(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 | // ======================================================================= |
973 | Handle(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 | // ======================================================================= |
982 | Handle(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 |
1013 | Handle(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 | // ======================================================================= |
1126 | Handle(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 | // ======================================================================= |
1155 | Handle(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 | } |