2 * Copyright 2001-2016, Haiku.
3 * Distributed under the terms of the MIT License.
6 * DarkWyrm <bpmagic@columbus.rr.com>
7 * Axel Dörfler, axeld@pinc-software.de
11 /*! Manages font families and styles */
14 #include "FontManager.h"
19 #include <Directory.h>
22 #include <FindDirectory.h>
24 #include <NodeMonitor.h>
28 #include "FontFamily.h"
29 #include "ServerConfig.h"
30 #include "ServerFont.h"
33 //#define TRACE_FONT_MANAGER
34 #ifdef TRACE_FONT_MANAGER
35 # define FTRACE(x) printf x
41 // TODO: needs some more work for multi-user support
43 FT_Library gFreeTypeLibrary
;
44 FontManager
*gFontManager
= NULL
;
46 struct FontManager::font_directory
{
51 BObjectList
<FontStyle
> styles
;
53 bool AlreadyScanned() const { return revision
!= 0; }
54 FontStyle
* FindStyle(const node_ref
& nodeRef
) const;
57 struct FontManager::font_mapping
{
65 FontManager::font_directory::FindStyle(const node_ref
& nodeRef
) const
67 for (int32 i
= styles
.CountItems(); i
-- > 0;) {
68 FontStyle
* style
= styles
.ItemAt(i
);
70 if (nodeRef
== style
->NodeRef())
79 set_entry(node_ref
& nodeRef
, const char* name
, BEntry
& entry
)
82 ref
.device
= nodeRef
.device
;
83 ref
.directory
= nodeRef
.node
;
85 status_t status
= ref
.set_name(name
);
89 return entry
.SetTo(&ref
);
94 compare_font_families(const FontFamily
* a
, const FontFamily
* b
)
96 return strcmp(a
->Name(), b
->Name());
103 //! Does basic set up so that directories can be scanned
104 FontManager::FontManager()
105 : BLooper("Font Manager"),
106 fDirectories(10, true),
110 fDefaultPlainFont(NULL
),
111 fDefaultBoldFont(NULL
),
112 fDefaultFixedFont(NULL
),
117 fInitStatus
= FT_Init_FreeType(&gFreeTypeLibrary
) == 0 ? B_OK
: B_ERROR
;
119 if (fInitStatus
== B_OK
) {
121 _LoadRecentFontMappings();
123 fInitStatus
= _SetDefaultFonts();
125 if (fInitStatus
== B_OK
) {
126 // Precache the plain and bold fonts
127 _PrecacheFontFile(fDefaultPlainFont
);
128 _PrecacheFontFile(fDefaultBoldFont
);
134 //! Frees items allocated in the constructor and shuts down FreeType
135 FontManager::~FontManager()
137 delete fDefaultPlainFont
;
138 delete fDefaultBoldFont
;
139 delete fDefaultFixedFont
;
141 // free families before we're done with FreeType
143 for (int32 i
= fFamilies
.CountItems(); i
-- > 0;) {
144 delete fFamilies
.ItemAt(i
);
147 FT_Done_FreeType(gFreeTypeLibrary
);
152 FontManager::MessageReceived(BMessage
* message
)
154 switch (message
->what
) {
157 // TODO: support removing fonts!
160 if (message
->FindInt32("opcode", &opcode
) != B_OK
)
164 case B_ENTRY_CREATED
:
168 if (message
->FindInt32("device", &nodeRef
.device
) != B_OK
169 || message
->FindInt64("directory", &nodeRef
.node
) != B_OK
170 || message
->FindString("name", &name
) != B_OK
)
173 // TODO: make this better (possible under Haiku)
175 // let the font be written completely before trying to open it
178 if (set_entry(nodeRef
, name
, entry
) != B_OK
)
181 if (entry
.IsDirectory()) {
182 // a new directory to watch for us
186 font_directory
* directory
= _FindDirectory(nodeRef
);
187 if (directory
== NULL
) {
188 // unknown directory? how come?
192 _AddFont(*directory
, entry
);
199 // has the entry been moved into a monitored directory or has
200 // it been removed from one?
205 if (message
->FindInt32("device", &nodeRef
.device
) != B_OK
206 || message
->FindInt64("to directory", &nodeRef
.node
) != B_OK
207 || message
->FindInt64("from directory", (int64
*)&fromNode
) != B_OK
208 || message
->FindInt64("node", (int64
*)&node
) != B_OK
209 || message
->FindString("name", &name
) != B_OK
)
212 font_directory
* directory
= _FindDirectory(nodeRef
);
215 if (set_entry(nodeRef
, name
, entry
) != B_OK
)
218 if (directory
!= NULL
) {
219 // something has been added to our watched font directories
221 // test, if the source directory is one of ours as well
222 nodeRef
.node
= fromNode
;
223 font_directory
* fromDirectory
= _FindDirectory(nodeRef
);
225 if (entry
.IsDirectory()) {
226 if (fromDirectory
== NULL
) {
227 // there is a new directory to watch for us
229 FTRACE(("new directory moved in"));
231 // A directory from our watched directories has
232 // been renamed or moved within the watched
233 // directories - we only need to update the
234 // path names of the styles in that directory
236 directory
= _FindDirectory(nodeRef
);
237 if (directory
!= NULL
) {
238 for (int32 i
= 0; i
< directory
->styles
.CountItems(); i
++) {
239 FontStyle
* style
= directory
->styles
.ItemAt(i
);
240 style
->UpdatePath(directory
->directory
);
243 FTRACE(("directory renamed"));
246 if (fromDirectory
!= NULL
) {
247 // find style in source and move it to the target
249 FontStyle
* style
= fromDirectory
->FindStyle(nodeRef
);
251 fromDirectory
->styles
.RemoveItem(style
, false);
252 directory
->styles
.AddItem(style
);
253 style
->UpdatePath(directory
->directory
);
255 FTRACE(("font moved"));
257 FTRACE(("font added: %s\n", name
));
258 _AddFont(*directory
, entry
);
262 // and entry has been removed from our font directories
263 if (entry
.IsDirectory()) {
264 if (entry
.GetNodeRef(&nodeRef
) == B_OK
265 && (directory
= _FindDirectory(nodeRef
)) != NULL
)
266 _RemoveDirectory(directory
);
268 // remove font style from directory
269 _RemoveStyle(nodeRef
.device
, fromNode
, node
);
275 case B_ENTRY_REMOVED
:
278 uint64 directoryNode
;
279 if (message
->FindInt32("device", &nodeRef
.device
) != B_OK
280 || message
->FindInt64("directory", (int64
*)&directoryNode
) != B_OK
281 || message
->FindInt64("node", &nodeRef
.node
) != B_OK
)
284 font_directory
* directory
= _FindDirectory(nodeRef
);
285 if (directory
!= NULL
) {
286 // the directory has been removed, so we remove it as well
287 _RemoveDirectory(directory
);
289 // remove font style from directory
290 _RemoveStyle(nodeRef
.device
, directoryNode
, nodeRef
.node
);
302 FontManager::SaveRecentFontMappings()
308 FontManager::_AddDefaultMapping(const char* family
, const char* style
,
311 font_mapping
* mapping
= new (std::nothrow
) font_mapping
;
315 mapping
->family
= family
;
316 mapping
->style
= style
;
319 if (entry
.GetRef(&mapping
->ref
) != B_OK
321 || !fMappings
.AddItem(mapping
))
327 FontManager::_LoadRecentFontMappings()
329 // default known mappings
330 // TODO: load them for real, and use these as a fallback
333 if (find_directory(B_BEOS_FONTS_DIRECTORY
, &ttfontsPath
) == B_OK
) {
334 ttfontsPath
.Append("ttfonts");
336 BPath veraFontPath
= ttfontsPath
;
337 veraFontPath
.Append("NotoSans-Regular.ttf");
338 _AddDefaultMapping("Noto Sans", "Book", veraFontPath
.Path());
340 veraFontPath
.SetTo(ttfontsPath
.Path());
341 veraFontPath
.Append("NotoSans-Bold.ttf");
342 _AddDefaultMapping("Noto Sans", "Bold", veraFontPath
.Path());
344 veraFontPath
.SetTo(ttfontsPath
.Path());
345 veraFontPath
.Append("NotoMono-Regular.ttf");
346 _AddDefaultMapping("Noto Mono", "Regular", veraFontPath
.Path());
356 FontManager::_AddMappedFont(const char* familyName
, const char* styleName
)
358 FTRACE(("_AddMappedFont(family = \"%s\", style = \"%s\")\n",
359 familyName
, styleName
));
361 for (int32 i
= 0; i
< fMappings
.CountItems(); i
++) {
362 font_mapping
* mapping
= fMappings
.ItemAt(i
);
364 if (mapping
->family
== familyName
) {
365 if (styleName
!= NULL
&& mapping
->style
!= styleName
)
368 BEntry
entry(&mapping
->ref
);
369 if (entry
.InitCheck() != B_OK
)
372 // find parent directory
375 nodeRef
.device
= mapping
->ref
.device
;
376 nodeRef
.node
= mapping
->ref
.directory
;
377 font_directory
* directory
= _FindDirectory(nodeRef
);
378 if (directory
== NULL
) {
379 // unknown directory, maybe this is a user font - try
380 // to create the missing directory
382 if (path
.GetParent(&path
) != B_OK
383 || _CreateDirectories(path
.Path()) != B_OK
384 || (directory
= _FindDirectory(nodeRef
)) == NULL
)
388 return _AddFont(*directory
, entry
);
392 return B_ENTRY_NOT_FOUND
;
396 /*! \brief Removes the style from the font directory.
398 It doesn't necessary delete the font style, if it's still
402 FontManager::_RemoveStyle(font_directory
& directory
, FontStyle
* style
)
404 FTRACE(("font removed: %s\n", style
->Name()));
406 directory
.styles
.RemoveItem(style
);
407 directory
.revision
++;
409 fStyleHashTable
.RemoveItem(*style
);
416 FontManager::_RemoveStyle(dev_t device
, uint64 directoryNode
, uint64 node
)
418 // remove font style from directory
420 nodeRef
.device
= device
;
421 nodeRef
.node
= directoryNode
;
423 font_directory
* directory
= _FindDirectory(nodeRef
);
424 if (directory
!= NULL
) {
425 // find style in directory and remove it
427 FontStyle
* style
= directory
->FindStyle(nodeRef
);
429 _RemoveStyle(*directory
, style
);
435 FontManager::_GetDefaultStyle(const char *familyName
, const char *styleName
,
436 const char *fallbackFamily
, const char *fallbackStyle
,
439 // try to find a matching font
441 FontStyle
* style
= GetStyle(familyName
, styleName
);
443 style
= GetStyle(fallbackFamily
, fallbackStyle
);
445 style
= FindStyleMatchingFace(fallbackFace
);
446 if (style
== NULL
&& FamilyAt(0) != NULL
)
447 style
= FamilyAt(0)->StyleAt(0);
455 /*! \brief Sets the fonts that will be used when you create an empty
456 ServerFont without specifying a style, as well as the default
457 Desktop fonts if there are no settings available.
460 FontManager::_SetDefaultFonts()
463 FontStyle
* style
= _GetDefaultStyle(DEFAULT_PLAIN_FONT_FAMILY
,
464 DEFAULT_PLAIN_FONT_STYLE
, FALLBACK_PLAIN_FONT_FAMILY
,
465 DEFAULT_PLAIN_FONT_STYLE
,
470 fDefaultPlainFont
= new (std::nothrow
) ServerFont(*style
,
471 DEFAULT_PLAIN_FONT_SIZE
);
472 if (fDefaultPlainFont
== NULL
)
476 style
= _GetDefaultStyle(DEFAULT_BOLD_FONT_FAMILY
, DEFAULT_BOLD_FONT_STYLE
,
477 FALLBACK_BOLD_FONT_FAMILY
, DEFAULT_BOLD_FONT_STYLE
, B_BOLD_FACE
);
479 fDefaultBoldFont
= new (std::nothrow
) ServerFont(*style
,
480 DEFAULT_BOLD_FONT_SIZE
);
481 if (fDefaultBoldFont
== NULL
)
485 style
= _GetDefaultStyle(DEFAULT_FIXED_FONT_FAMILY
, DEFAULT_FIXED_FONT_STYLE
,
486 FALLBACK_FIXED_FONT_FAMILY
, DEFAULT_FIXED_FONT_STYLE
, B_REGULAR_FACE
);
488 fDefaultFixedFont
= new (std::nothrow
) ServerFont(*style
,
489 DEFAULT_FIXED_FONT_SIZE
);
490 if (fDefaultFixedFont
== NULL
)
493 fDefaultFixedFont
->SetSpacing(B_FIXED_SPACING
);
500 FontManager::_PrecacheFontFile(const ServerFont
* font
)
505 size_t bufferSize
= 32768;
506 uint8
* buffer
= new (std::nothrow
) uint8
[bufferSize
];
507 if (buffer
== NULL
) {
508 // We don't care. Pre-caching doesn't make sense anyways when there
509 // is not enough RAM...
513 BFile
file(font
->Path(), B_READ_ONLY
);
514 if (file
.InitCheck() != B_OK
) {
520 // We just want the file in the kernel file cache...
521 ssize_t read
= file
.Read(buffer
, bufferSize
);
522 if (read
< (ssize_t
)bufferSize
)
531 FontManager::_AddSystemPaths()
534 if (find_directory(B_SYSTEM_FONTS_DIRECTORY
, &path
, true) == B_OK
)
535 _AddPath(path
.Path());
537 // We don't scan these in test mode to help shave off some startup time
539 if (find_directory(B_SYSTEM_NONPACKAGED_FONTS_DIRECTORY
, &path
, true) == B_OK
)
540 _AddPath(path
.Path());
546 FontManager::_ScanFontsIfNecessary()
553 //! Scans all currently known font directories
555 FontManager::_ScanFonts()
560 for (int32 i
= fDirectories
.CountItems(); i
-- > 0;) {
561 font_directory
* directory
= fDirectories
.ItemAt(i
);
563 if (directory
->AlreadyScanned())
566 _ScanFontDirectory(*directory
);
573 /*! \brief Adds the FontFamily/FontStyle that is represented by this path.
576 FontManager::_AddFont(font_directory
& directory
, BEntry
& entry
)
579 status_t status
= entry
.GetNodeRef(&nodeRef
);
584 status
= entry
.GetPath(&path
);
589 FT_Error error
= FT_New_Face(gFreeTypeLibrary
, path
.Path(), 0, &face
);
593 FontFamily
*family
= _FindFamily(face
->family_name
);
594 if (family
!= NULL
&& family
->HasStyle(face
->style_name
)) {
595 // prevent adding the same style twice
596 // (this indicates a problem with the installed fonts maybe?)
601 if (family
== NULL
) {
602 family
= new (std::nothrow
) FontFamily(face
->family_name
, fNextID
++);
604 || !fFamilies
.BinaryInsert(family
, compare_font_families
)) {
611 FTRACE(("\tadd style: %s, %s\n", face
->family_name
, face
->style_name
));
613 // the FontStyle takes over ownership of the FT_Face object
614 FontStyle
*style
= new (std::nothrow
) FontStyle(nodeRef
, path
.Path(), face
);
615 if (style
== NULL
|| !family
->AddStyle(style
)) {
621 directory
.styles
.AddItem(style
);
622 fStyleHashTable
.AddItem(style
);
624 if (directory
.AlreadyScanned())
625 directory
.revision
++;
631 FontManager::font_directory
*
632 FontManager::_FindDirectory(node_ref
& nodeRef
)
634 for (int32 i
= fDirectories
.CountItems(); i
-- > 0;) {
635 font_directory
* directory
= fDirectories
.ItemAt(i
);
637 if (directory
->directory
== nodeRef
)
646 FontManager::_RemoveDirectory(font_directory
* directory
)
648 FTRACE(("FontManager: Remove directory (%" B_PRIdINO
")!\n",
649 directory
->directory
.node
));
651 fDirectories
.RemoveItem(directory
, false);
653 // TODO: remove styles from this directory!
655 watch_node(&directory
->directory
, B_STOP_WATCHING
, this);
661 FontManager::_AddPath(const char* path
)
664 status_t status
= entry
.SetTo(path
);
668 return _AddPath(entry
);
673 FontManager::_AddPath(BEntry
& entry
, font_directory
** _newDirectory
)
676 status_t status
= entry
.GetNodeRef(&nodeRef
);
680 // check if we are already know this directory
682 font_directory
* directory
= _FindDirectory(nodeRef
);
683 if (directory
!= NULL
) {
685 *_newDirectory
= directory
;
689 // it's a new one, so let's add it
691 directory
= new (std::nothrow
) font_directory
;
692 if (directory
== NULL
)
696 status
= entry
.GetStat(&stat
);
697 if (status
!= B_OK
) {
702 directory
->directory
= nodeRef
;
703 directory
->user
= stat
.st_uid
;
704 directory
->group
= stat
.st_gid
;
705 directory
->revision
= 0;
707 status
= watch_node(&nodeRef
, B_WATCH_DIRECTORY
, this);
708 if (status
!= B_OK
) {
709 // we cannot watch this directory - while this is unfortunate,
710 // it's not a critical error
711 printf("could not watch directory %" B_PRIdDEV
":%" B_PRIdINO
"\n",
712 nodeRef
.device
, nodeRef
.node
);
713 // TODO: should go into syslog()
716 FTRACE(("FontManager: now watching: %s\n", path
.Path()));
719 fDirectories
.AddItem(directory
);
722 *_newDirectory
= directory
;
729 /*! \brief Creates all unknown font_directories of the specified path - but
730 only if one of its parent directories is already known.
732 This method is used to create the font_directories for font_mappings.
733 It recursively walks upwards in the directory hierarchy until it finds
734 a known font_directory (or hits the root directory, in which case it
738 FontManager::_CreateDirectories(const char* path
)
740 FTRACE(("_CreateDirectories(path = %s)\n", path
));
742 if (!strcmp(path
, "/")) {
743 // we walked our way up to the root
744 return B_ENTRY_NOT_FOUND
;
748 status_t status
= entry
.SetTo(path
);
753 status
= entry
.GetNodeRef(&nodeRef
);
757 // check if we are already know this directory
759 font_directory
* directory
= _FindDirectory(nodeRef
);
760 if (directory
!= NULL
)
763 // We don't know this one yet - keep walking the path upwards
764 // and try to find a match.
767 status
= parent
.GetParent(&parent
);
771 status
= _CreateDirectories(parent
.Path());
775 // We have our match, create sub directory
777 return _AddPath(path
);
781 /*! \brief Scan a folder for all valid fonts
782 \param directoryPath Path of the folder to scan.
785 FontManager::_ScanFontDirectory(font_directory
& fontDirectory
)
787 // This bad boy does all the real work. It loads each entry in the
788 // directory. If a valid font file, it adds both the family and the style.
790 BDirectory directory
;
791 status_t status
= directory
.SetTo(&fontDirectory
.directory
);
796 while (directory
.GetNextEntry(&entry
) == B_OK
) {
797 if (entry
.IsDirectory()) {
798 // scan this directory recursively
799 font_directory
* newDirectory
;
800 if (_AddPath(entry
, &newDirectory
) == B_OK
&& newDirectory
!= NULL
)
801 _ScanFontDirectory(*newDirectory
);
806 // TODO: Commenting this out makes my "Unicode glyph lookup"
807 // work with our default fonts. The real fix is to select the
808 // Unicode char map (if supported), and/or adjust the
809 // utf8 -> glyph-index mapping everywhere to handle other
810 // char maps. We could also ignore fonts that don't support
811 // the Unicode lookup as a temporary "solution".
813 FT_CharMap charmap
= _GetSupportedCharmap(face
);
819 face
->charmap
= charmap
;
822 _AddFont(fontDirectory
, entry
);
823 // takes over ownership of the FT_Face object
826 fontDirectory
.revision
= 1;
831 /*! \brief Finds and returns the first valid charmap in a font
833 \param face Font handle obtained from FT_Load_Face()
834 \return An FT_CharMap or NULL if unsuccessful
837 FontManager::_GetSupportedCharmap(const FT_Face
& face
)
839 for (int32 i
= 0; i
< face
->num_charmaps
; i
++) {
840 FT_CharMap charmap
= face
->charmaps
[i
];
842 switch (charmap
->platform_id
) {
844 // if Windows Symbol or Windows Unicode
845 if (charmap
->encoding_id
== 0 || charmap
->encoding_id
== 1)
851 if (charmap
->encoding_id
== 0)
857 if (charmap
->encoding_id
== 0)
871 FontManager::CheckRevision(uid_t user
)
873 BAutolock
locker(this);
876 _ScanFontsIfNecessary();
878 for (int32 i
= 0; i
< fDirectories
.CountItems(); i
++) {
879 font_directory
* directory
= fDirectories
.ItemAt(i
);
881 // TODO: for now, add all directories
882 revision
+= directory
->revision
;
889 /*! \brief Counts the number of font families available
890 \return The number of unique font families currently available
893 FontManager::CountFamilies()
895 _ScanFontsIfNecessary();
897 return fFamilies
.CountItems();
901 /*! \brief Counts the number of styles available in a font family
902 \param family Name of the font family to scan
903 \return The number of font styles currently available for the font family
906 FontManager::CountStyles(const char *familyName
)
908 _ScanFontsIfNecessary();
910 FontFamily
*family
= GetFamily(familyName
);
912 return family
->CountStyles();
918 /*! \brief Counts the number of styles available in a font family
919 \param family Name of the font family to scan
920 \return The number of font styles currently available for the font family
923 FontManager::CountStyles(uint16 familyID
)
925 _ScanFontsIfNecessary();
927 FontFamily
*family
= GetFamily(familyID
);
929 return family
->CountStyles();
936 FontManager::FamilyAt(int32 index
) const
938 return fFamilies
.ItemAt(index
);
943 FontManager::_FindFamily(const char* name
) const
948 FontFamily
family(name
, 0);
949 return const_cast<FontFamily
*>(fFamilies
.BinarySearch(family
,
950 compare_font_families
));
954 /*! \brief Locates a FontFamily object by name
955 \param name The family to find
956 \return Pointer to the specified family or NULL if not found.
959 FontManager::GetFamily(const char* name
)
964 FontFamily
* family
= _FindFamily(name
);
971 // try font mappings before failing
972 if (_AddMappedFont(name
) == B_OK
)
973 return _FindFamily(name
);
976 return _FindFamily(name
);
981 FontManager::GetFamily(uint16 familyID
) const
983 FontKey
key(familyID
, 0);
984 FontStyle
* style
= (FontStyle
*)fStyleHashTable
.GetValue(key
);
986 return style
->Family();
993 FontManager::GetStyleByIndex(const char* familyName
, int32 index
)
995 FontFamily
* family
= GetFamily(familyName
);
997 return family
->StyleAt(index
);
1004 FontManager::GetStyleByIndex(uint16 familyID
, int32 index
)
1006 FontFamily
* family
= GetFamily(familyID
);
1008 return family
->StyleAt(index
);
1014 /*! \brief Retrieves the FontStyle object that comes closest to the one
1017 \param family The font's family or NULL in which case \a familyID is used
1018 \param style The font's style or NULL in which case \a styleID is used
1019 \param familyID will only be used if \a family is NULL (or empty)
1020 \param styleID will only be used if \a style is NULL (or empty)
1021 \param face is used to specify the style if both \a style is NULL or empty
1022 and styleID is 0xffff.
1024 \return The FontStyle having those attributes or NULL if not available
1027 FontManager::GetStyle(const char* familyName
, const char* styleName
,
1028 uint16 familyID
, uint16 styleID
, uint16 face
)
1034 if (familyName
!= NULL
&& familyName
[0])
1035 family
= GetFamily(familyName
);
1037 family
= GetFamily(familyID
);
1044 if (styleName
!= NULL
&& styleName
[0]) {
1045 FontStyle
* fontStyle
= family
->GetStyle(styleName
);
1046 if (fontStyle
!= NULL
)
1049 // before we fail, we try the mappings for a match
1050 if (_AddMappedFont(family
->Name(), styleName
) == B_OK
) {
1051 fontStyle
= family
->GetStyle(styleName
);
1052 if (fontStyle
!= NULL
)
1057 return family
->GetStyle(styleName
);
1060 if (styleID
!= 0xffff)
1061 return family
->GetStyleByID(styleID
);
1063 // try to get from face
1064 return family
->GetStyleMatchingFace(face
);
1068 /*! \brief Retrieves the FontStyle object
1069 \param family ID for the font's family
1070 \param style ID of the font's style
1071 \return The FontStyle having those attributes or NULL if not available
1074 FontManager::GetStyle(uint16 familyID
, uint16 styleID
) const
1076 FontKey
key(familyID
, styleID
);
1077 return (FontStyle
*)fStyleHashTable
.GetValue(key
);
1081 /*! \brief If you don't find your preferred font style, but are anxious
1082 to have one fitting your needs, you may want to use this method.
1085 FontManager::FindStyleMatchingFace(uint16 face
) const
1087 int32 count
= fFamilies
.CountItems();
1089 for (int32 i
= 0; i
< count
; i
++) {
1090 FontFamily
* family
= fFamilies
.ItemAt(i
);
1091 FontStyle
* style
= family
->GetStyleMatchingFace(face
);
1100 /*! \brief This call is used by the FontStyle class - and the FontStyle class
1101 only - to remove itself from the font manager.
1102 At this point, the style is already no longer available to the user.
1105 FontManager::RemoveStyle(FontStyle
* style
)
1107 FontFamily
* family
= style
->Family();
1109 debugger("family is NULL!");
1111 FontStyle
* check
= GetStyle(family
->ID(), style
->ID());
1113 debugger("style removed but still available!");
1115 if (family
->RemoveStyle(style
)
1116 && family
->CountStyles() == 0)
1117 fFamilies
.RemoveItem(family
);
1122 FontManager::DefaultPlainFont() const
1124 return fDefaultPlainFont
;
1129 FontManager::DefaultBoldFont() const
1131 return fDefaultBoldFont
;
1136 FontManager::DefaultFixedFont() const
1138 return fDefaultFixedFont
;
1143 FontManager::AttachUser(uid_t userID
)
1145 BAutolock
locker(this);
1148 // TODO: actually, find_directory() cannot know which user ID we want here
1149 // TODO: avoids user fonts in safe mode
1151 if (find_directory(B_USER_FONTS_DIRECTORY
, &path
, true) == B_OK
)
1152 _AddPath(path
.Path());
1153 if (find_directory(B_USER_NONPACKAGED_FONTS_DIRECTORY
, &path
, true)
1155 _AddPath(path
.Path());
1162 FontManager::DetachUser(uid_t userID
)
1164 BAutolock
locker(this);