2 * Copyright 2001-2009, Haiku.
3 * Distributed under the terms of the MIT License.
6 * DarkWyrm <bpmagic@columbus.rr.com>
7 * Axel Dörfler, axeld@pinc-software.de
10 /*! Manages font families and styles */
13 #include "FontFamily.h"
14 #include "FontManager.h"
15 #include "ServerConfig.h"
16 #include "ServerFont.h"
19 #include <Directory.h>
22 #include <FindDirectory.h>
24 #include <NodeMonitor.h>
30 //#define TRACE_FONT_MANAGER
31 #ifdef TRACE_FONT_MANAGER
32 # define FTRACE(x) printf x
38 // TODO: needs some more work for multi-user support
40 FT_Library gFreeTypeLibrary
;
41 FontManager
*gFontManager
= NULL
;
43 struct FontManager::font_directory
{
48 BObjectList
<FontStyle
> styles
;
50 bool AlreadyScanned() const { return revision
!= 0; }
51 FontStyle
* FindStyle(const node_ref
& nodeRef
) const;
54 struct FontManager::font_mapping
{
62 FontManager::font_directory::FindStyle(const node_ref
& nodeRef
) const
64 for (int32 i
= styles
.CountItems(); i
-- > 0;) {
65 FontStyle
* style
= styles
.ItemAt(i
);
67 if (nodeRef
== style
->NodeRef())
76 set_entry(node_ref
& nodeRef
, const char* name
, BEntry
& entry
)
79 ref
.device
= nodeRef
.device
;
80 ref
.directory
= nodeRef
.node
;
82 status_t status
= ref
.set_name(name
);
86 return entry
.SetTo(&ref
);
91 compare_font_families(const FontFamily
* a
, const FontFamily
* b
)
93 return strcmp(a
->Name(), b
->Name());
100 //! Does basic set up so that directories can be scanned
101 FontManager::FontManager()
102 : BLooper("Font Manager"),
103 fDirectories(10, true),
107 fDefaultPlainFont(NULL
),
108 fDefaultBoldFont(NULL
),
109 fDefaultFixedFont(NULL
),
114 fInitStatus
= FT_Init_FreeType(&gFreeTypeLibrary
) == 0 ? B_OK
: B_ERROR
;
116 if (fInitStatus
== B_OK
) {
118 _LoadRecentFontMappings();
120 fInitStatus
= _SetDefaultFonts();
122 if (fInitStatus
== B_OK
) {
123 // Precache the plain and bold fonts
124 _PrecacheFontFile(fDefaultPlainFont
);
125 _PrecacheFontFile(fDefaultBoldFont
);
131 //! Frees items allocated in the constructor and shuts down FreeType
132 FontManager::~FontManager()
134 delete fDefaultPlainFont
;
135 delete fDefaultBoldFont
;
136 delete fDefaultFixedFont
;
138 // free families before we're done with FreeType
140 for (int32 i
= fFamilies
.CountItems(); i
-- > 0;) {
141 delete fFamilies
.ItemAt(i
);
144 FT_Done_FreeType(gFreeTypeLibrary
);
149 FontManager::MessageReceived(BMessage
* message
)
151 switch (message
->what
) {
154 // TODO: support removing fonts!
157 if (message
->FindInt32("opcode", &opcode
) != B_OK
)
161 case B_ENTRY_CREATED
:
165 if (message
->FindInt32("device", &nodeRef
.device
) != B_OK
166 || message
->FindInt64("directory", &nodeRef
.node
) != B_OK
167 || message
->FindString("name", &name
) != B_OK
)
170 // TODO: make this better (possible under Haiku)
172 // let the font be written completely before trying to open it
175 if (set_entry(nodeRef
, name
, entry
) != B_OK
)
178 if (entry
.IsDirectory()) {
179 // a new directory to watch for us
183 font_directory
* directory
= _FindDirectory(nodeRef
);
184 if (directory
== NULL
) {
185 // unknown directory? how come?
189 _AddFont(*directory
, entry
);
196 // has the entry been moved into a monitored directory or has
197 // it been removed from one?
202 if (message
->FindInt32("device", &nodeRef
.device
) != B_OK
203 || message
->FindInt64("to directory", &nodeRef
.node
) != B_OK
204 || message
->FindInt64("from directory", (int64
*)&fromNode
) != B_OK
205 || message
->FindInt64("node", (int64
*)&node
) != B_OK
206 || message
->FindString("name", &name
) != B_OK
)
209 font_directory
* directory
= _FindDirectory(nodeRef
);
212 if (set_entry(nodeRef
, name
, entry
) != B_OK
)
215 if (directory
!= NULL
) {
216 // something has been added to our watched font directories
218 // test, if the source directory is one of ours as well
219 nodeRef
.node
= fromNode
;
220 font_directory
* fromDirectory
= _FindDirectory(nodeRef
);
222 if (entry
.IsDirectory()) {
223 if (fromDirectory
== NULL
) {
224 // there is a new directory to watch for us
226 FTRACE(("new directory moved in"));
228 // A directory from our watched directories has
229 // been renamed or moved within the watched
230 // directories - we only need to update the
231 // path names of the styles in that directory
233 directory
= _FindDirectory(nodeRef
);
234 if (directory
!= NULL
) {
235 for (int32 i
= 0; i
< directory
->styles
.CountItems(); i
++) {
236 FontStyle
* style
= directory
->styles
.ItemAt(i
);
237 style
->UpdatePath(directory
->directory
);
240 FTRACE(("directory renamed"));
243 if (fromDirectory
!= NULL
) {
244 // find style in source and move it to the target
246 FontStyle
* style
= fromDirectory
->FindStyle(nodeRef
);
248 fromDirectory
->styles
.RemoveItem(style
, false);
249 directory
->styles
.AddItem(style
);
250 style
->UpdatePath(directory
->directory
);
252 FTRACE(("font moved"));
254 FTRACE(("font added: %s\n", name
));
255 _AddFont(*directory
, entry
);
259 // and entry has been removed from our font directories
260 if (entry
.IsDirectory()) {
261 if (entry
.GetNodeRef(&nodeRef
) == B_OK
262 && (directory
= _FindDirectory(nodeRef
)) != NULL
)
263 _RemoveDirectory(directory
);
265 // remove font style from directory
266 _RemoveStyle(nodeRef
.device
, fromNode
, node
);
272 case B_ENTRY_REMOVED
:
275 uint64 directoryNode
;
276 if (message
->FindInt32("device", &nodeRef
.device
) != B_OK
277 || message
->FindInt64("directory", (int64
*)&directoryNode
) != B_OK
278 || message
->FindInt64("node", &nodeRef
.node
) != B_OK
)
281 font_directory
* directory
= _FindDirectory(nodeRef
);
282 if (directory
!= NULL
) {
283 // the directory has been removed, so we remove it as well
284 _RemoveDirectory(directory
);
286 // remove font style from directory
287 _RemoveStyle(nodeRef
.device
, directoryNode
, nodeRef
.node
);
299 FontManager::SaveRecentFontMappings()
305 FontManager::_AddDefaultMapping(const char* family
, const char* style
,
308 font_mapping
* mapping
= new (std::nothrow
) font_mapping
;
312 mapping
->family
= family
;
313 mapping
->style
= style
;
316 if (entry
.GetRef(&mapping
->ref
) != B_OK
318 || !fMappings
.AddItem(mapping
))
324 FontManager::_LoadRecentFontMappings()
326 // default known mappings
327 // TODO: load them for real, and use these as a fallback
330 if (find_directory(B_BEOS_FONTS_DIRECTORY
, &ttfontsPath
) == B_OK
) {
331 ttfontsPath
.Append("ttfonts");
333 BPath veraFontPath
= ttfontsPath
;
334 veraFontPath
.Append("DejaVuSans.ttf");
335 _AddDefaultMapping("DejaVu Sans", "Book", veraFontPath
.Path());
337 veraFontPath
.SetTo(ttfontsPath
.Path());
338 veraFontPath
.Append("DejaVuSans-Bold.ttf");
339 _AddDefaultMapping("DejaVu Sans", "Bold", veraFontPath
.Path());
341 veraFontPath
.SetTo(ttfontsPath
.Path());
342 veraFontPath
.Append("DejaVuSansMono.ttf");
343 _AddDefaultMapping("DejaVu Sans Mono", "Book", veraFontPath
.Path());
353 FontManager::_AddMappedFont(const char* familyName
, const char* styleName
)
355 FTRACE(("_AddMappedFont(family = \"%s\", style = \"%s\")\n",
356 familyName
, styleName
));
358 for (int32 i
= 0; i
< fMappings
.CountItems(); i
++) {
359 font_mapping
* mapping
= fMappings
.ItemAt(i
);
361 if (mapping
->family
== familyName
) {
362 if (styleName
!= NULL
&& mapping
->style
!= styleName
)
365 BEntry
entry(&mapping
->ref
);
366 if (entry
.InitCheck() != B_OK
)
369 // find parent directory
372 nodeRef
.device
= mapping
->ref
.device
;
373 nodeRef
.node
= mapping
->ref
.directory
;
374 font_directory
* directory
= _FindDirectory(nodeRef
);
375 if (directory
== NULL
) {
376 // unknown directory, maybe this is a user font - try
377 // to create the missing directory
379 if (path
.GetParent(&path
) != B_OK
380 || _CreateDirectories(path
.Path()) != B_OK
381 || (directory
= _FindDirectory(nodeRef
)) == NULL
)
385 return _AddFont(*directory
, entry
);
389 return B_ENTRY_NOT_FOUND
;
393 /*! \brief Removes the style from the font directory.
395 It doesn't necessary delete the font style, if it's still
399 FontManager::_RemoveStyle(font_directory
& directory
, FontStyle
* style
)
401 FTRACE(("font removed: %s\n", style
->Name()));
403 directory
.styles
.RemoveItem(style
);
404 directory
.revision
++;
406 fStyleHashTable
.RemoveItem(*style
);
413 FontManager::_RemoveStyle(dev_t device
, uint64 directoryNode
, uint64 node
)
415 // remove font style from directory
417 nodeRef
.device
= device
;
418 nodeRef
.node
= directoryNode
;
420 font_directory
* directory
= _FindDirectory(nodeRef
);
421 if (directory
!= NULL
) {
422 // find style in directory and remove it
424 FontStyle
* style
= directory
->FindStyle(nodeRef
);
426 _RemoveStyle(*directory
, style
);
432 FontManager::_GetDefaultStyle(const char *familyName
, const char *styleName
,
433 const char *fallbackFamily
, const char *fallbackStyle
,
436 // try to find a matching font
438 FontStyle
* style
= GetStyle(familyName
, styleName
);
440 style
= GetStyle(fallbackFamily
, fallbackStyle
);
442 style
= FindStyleMatchingFace(fallbackFace
);
443 if (style
== NULL
&& FamilyAt(0) != NULL
)
444 style
= FamilyAt(0)->StyleAt(0);
452 /*! \brief Sets the fonts that will be used when you create an empty
453 ServerFont without specifying a style, as well as the default
454 Desktop fonts if there are no settings available.
457 FontManager::_SetDefaultFonts()
460 FontStyle
* style
= _GetDefaultStyle(DEFAULT_PLAIN_FONT_FAMILY
,
461 DEFAULT_PLAIN_FONT_STYLE
, FALLBACK_PLAIN_FONT_FAMILY
,
462 DEFAULT_PLAIN_FONT_STYLE
,
467 fDefaultPlainFont
= new (std::nothrow
) ServerFont(*style
,
468 DEFAULT_PLAIN_FONT_SIZE
);
469 if (fDefaultPlainFont
== NULL
)
473 style
= _GetDefaultStyle(DEFAULT_BOLD_FONT_FAMILY
, DEFAULT_BOLD_FONT_STYLE
,
474 FALLBACK_BOLD_FONT_FAMILY
, DEFAULT_BOLD_FONT_STYLE
, B_BOLD_FACE
);
476 fDefaultBoldFont
= new (std::nothrow
) ServerFont(*style
,
477 DEFAULT_BOLD_FONT_SIZE
);
478 if (fDefaultBoldFont
== NULL
)
482 style
= _GetDefaultStyle(DEFAULT_FIXED_FONT_FAMILY
, DEFAULT_FIXED_FONT_STYLE
,
483 FALLBACK_FIXED_FONT_FAMILY
, DEFAULT_FIXED_FONT_STYLE
, B_REGULAR_FACE
);
485 fDefaultFixedFont
= new (std::nothrow
) ServerFont(*style
,
486 DEFAULT_FIXED_FONT_SIZE
);
487 if (fDefaultFixedFont
== NULL
)
490 fDefaultFixedFont
->SetSpacing(B_FIXED_SPACING
);
497 FontManager::_PrecacheFontFile(const ServerFont
* font
)
502 size_t bufferSize
= 32768;
503 uint8
* buffer
= new (std::nothrow
) uint8
[bufferSize
];
504 if (buffer
== NULL
) {
505 // We don't care. Pre-caching doesn't make sense anyways when there
506 // is not enough RAM...
510 BFile
file(font
->Path(), B_READ_ONLY
);
511 if (file
.InitCheck() != B_OK
) {
517 // We just want the file in the kernel file cache...
518 ssize_t read
= file
.Read(buffer
, bufferSize
);
519 if (read
< (ssize_t
)bufferSize
)
528 FontManager::_AddSystemPaths()
531 if (find_directory(B_SYSTEM_FONTS_DIRECTORY
, &path
, true) == B_OK
)
532 _AddPath(path
.Path());
534 // We don't scan these in test mode to help shave off some startup time
536 if (find_directory(B_SYSTEM_NONPACKAGED_FONTS_DIRECTORY
, &path
, true) == B_OK
)
537 _AddPath(path
.Path());
543 FontManager::_ScanFontsIfNecessary()
550 //! Scans all currently known font directories
552 FontManager::_ScanFonts()
557 for (int32 i
= fDirectories
.CountItems(); i
-- > 0;) {
558 font_directory
* directory
= fDirectories
.ItemAt(i
);
560 if (directory
->AlreadyScanned())
563 _ScanFontDirectory(*directory
);
570 /*! \brief Adds the FontFamily/FontStyle that is represented by this path.
573 FontManager::_AddFont(font_directory
& directory
, BEntry
& entry
)
576 status_t status
= entry
.GetNodeRef(&nodeRef
);
581 status
= entry
.GetPath(&path
);
586 FT_Error error
= FT_New_Face(gFreeTypeLibrary
, path
.Path(), 0, &face
);
590 FontFamily
*family
= _FindFamily(face
->family_name
);
591 if (family
!= NULL
&& family
->HasStyle(face
->style_name
)) {
592 // prevent adding the same style twice
593 // (this indicates a problem with the installed fonts maybe?)
598 if (family
== NULL
) {
599 family
= new (std::nothrow
) FontFamily(face
->family_name
, fNextID
++);
601 || !fFamilies
.BinaryInsert(family
, compare_font_families
)) {
608 FTRACE(("\tadd style: %s, %s\n", face
->family_name
, face
->style_name
));
610 // the FontStyle takes over ownership of the FT_Face object
611 FontStyle
*style
= new FontStyle(nodeRef
, path
.Path(), face
);
612 if (!family
->AddStyle(style
)) {
618 directory
.styles
.AddItem(style
);
619 fStyleHashTable
.AddItem(style
);
621 if (directory
.AlreadyScanned())
622 directory
.revision
++;
628 FontManager::font_directory
*
629 FontManager::_FindDirectory(node_ref
& nodeRef
)
631 for (int32 i
= fDirectories
.CountItems(); i
-- > 0;) {
632 font_directory
* directory
= fDirectories
.ItemAt(i
);
634 if (directory
->directory
== nodeRef
)
643 FontManager::_RemoveDirectory(font_directory
* directory
)
645 FTRACE(("FontManager: Remove directory (%" B_PRIdINO
")!\n",
646 directory
->directory
.node
));
648 fDirectories
.RemoveItem(directory
, false);
650 // TODO: remove styles from this directory!
652 watch_node(&directory
->directory
, B_STOP_WATCHING
, this);
658 FontManager::_AddPath(const char* path
)
661 status_t status
= entry
.SetTo(path
);
665 return _AddPath(entry
);
670 FontManager::_AddPath(BEntry
& entry
, font_directory
** _newDirectory
)
673 status_t status
= entry
.GetNodeRef(&nodeRef
);
677 // check if we are already know this directory
679 font_directory
* directory
= _FindDirectory(nodeRef
);
680 if (directory
!= NULL
) {
682 *_newDirectory
= directory
;
686 // it's a new one, so let's add it
688 directory
= new (std::nothrow
) font_directory
;
689 if (directory
== NULL
)
693 status
= entry
.GetStat(&stat
);
694 if (status
!= B_OK
) {
699 directory
->directory
= nodeRef
;
700 directory
->user
= stat
.st_uid
;
701 directory
->group
= stat
.st_gid
;
702 directory
->revision
= 0;
704 status
= watch_node(&nodeRef
, B_WATCH_DIRECTORY
, this);
705 if (status
!= B_OK
) {
706 // we cannot watch this directory - while this is unfortunate,
707 // it's not a critical error
708 printf("could not watch directory %" B_PRIdDEV
":%" B_PRIdINO
"\n",
709 nodeRef
.device
, nodeRef
.node
);
710 // TODO: should go into syslog()
713 FTRACE(("FontManager: now watching: %s\n", path
.Path()));
716 fDirectories
.AddItem(directory
);
719 *_newDirectory
= directory
;
726 /*! \brief Creates all unknown font_directories of the specified path - but
727 only if one of its parent directories is already known.
729 This method is used to create the font_directories for font_mappings.
730 It recursively walks upwards in the directory hierarchy until it finds
731 a known font_directory (or hits the root directory, in which case it
735 FontManager::_CreateDirectories(const char* path
)
737 FTRACE(("_CreateDirectories(path = %s)\n", path
));
739 if (!strcmp(path
, "/")) {
740 // we walked our way up to the root
741 return B_ENTRY_NOT_FOUND
;
745 status_t status
= entry
.SetTo(path
);
750 status
= entry
.GetNodeRef(&nodeRef
);
754 // check if we are already know this directory
756 font_directory
* directory
= _FindDirectory(nodeRef
);
757 if (directory
!= NULL
)
760 // We don't know this one yet - keep walking the path upwards
761 // and try to find a match.
764 status
= parent
.GetParent(&parent
);
768 status
= _CreateDirectories(parent
.Path());
772 // We have our match, create sub directory
774 return _AddPath(path
);
778 /*! \brief Scan a folder for all valid fonts
779 \param directoryPath Path of the folder to scan.
782 FontManager::_ScanFontDirectory(font_directory
& fontDirectory
)
784 // This bad boy does all the real work. It loads each entry in the
785 // directory. If a valid font file, it adds both the family and the style.
787 BDirectory directory
;
788 status_t status
= directory
.SetTo(&fontDirectory
.directory
);
793 while (directory
.GetNextEntry(&entry
) == B_OK
) {
794 if (entry
.IsDirectory()) {
795 // scan this directory recursively
796 font_directory
* newDirectory
;
797 if (_AddPath(entry
, &newDirectory
) == B_OK
&& newDirectory
!= NULL
)
798 _ScanFontDirectory(*newDirectory
);
803 // TODO: Commenting this out makes my "Unicode glyph lookup"
804 // work with our default fonts. The real fix is to select the
805 // Unicode char map (if supported), and/or adjust the
806 // utf8 -> glyph-index mapping everywhere to handle other
807 // char maps. We could also ignore fonts that don't support
808 // the Unicode lookup as a temporary "solution".
810 FT_CharMap charmap
= _GetSupportedCharmap(face
);
816 face
->charmap
= charmap
;
819 _AddFont(fontDirectory
, entry
);
820 // takes over ownership of the FT_Face object
823 fontDirectory
.revision
= 1;
828 /*! \brief Finds and returns the first valid charmap in a font
830 \param face Font handle obtained from FT_Load_Face()
831 \return An FT_CharMap or NULL if unsuccessful
834 FontManager::_GetSupportedCharmap(const FT_Face
& face
)
836 for (int32 i
= 0; i
< face
->num_charmaps
; i
++) {
837 FT_CharMap charmap
= face
->charmaps
[i
];
839 switch (charmap
->platform_id
) {
841 // if Windows Symbol or Windows Unicode
842 if (charmap
->encoding_id
== 0 || charmap
->encoding_id
== 1)
848 if (charmap
->encoding_id
== 0)
854 if (charmap
->encoding_id
== 0)
868 FontManager::CheckRevision(uid_t user
)
870 BAutolock
locker(this);
873 _ScanFontsIfNecessary();
875 for (int32 i
= 0; i
< fDirectories
.CountItems(); i
++) {
876 font_directory
* directory
= fDirectories
.ItemAt(i
);
878 // TODO: for now, add all directories
879 revision
+= directory
->revision
;
886 /*! \brief Counts the number of font families available
887 \return The number of unique font families currently available
890 FontManager::CountFamilies()
892 _ScanFontsIfNecessary();
894 return fFamilies
.CountItems();
898 /*! \brief Counts the number of styles available in a font family
899 \param family Name of the font family to scan
900 \return The number of font styles currently available for the font family
903 FontManager::CountStyles(const char *familyName
)
905 _ScanFontsIfNecessary();
907 FontFamily
*family
= GetFamily(familyName
);
909 return family
->CountStyles();
915 /*! \brief Counts the number of styles available in a font family
916 \param family Name of the font family to scan
917 \return The number of font styles currently available for the font family
920 FontManager::CountStyles(uint16 familyID
)
922 _ScanFontsIfNecessary();
924 FontFamily
*family
= GetFamily(familyID
);
926 return family
->CountStyles();
933 FontManager::FamilyAt(int32 index
) const
935 return fFamilies
.ItemAt(index
);
940 FontManager::_FindFamily(const char* name
) const
945 FontFamily
family(name
, 0);
946 return const_cast<FontFamily
*>(fFamilies
.BinarySearch(family
,
947 compare_font_families
));
951 /*! \brief Locates a FontFamily object by name
952 \param name The family to find
953 \return Pointer to the specified family or NULL if not found.
956 FontManager::GetFamily(const char* name
)
961 FontFamily
* family
= _FindFamily(name
);
968 // try font mappings before failing
969 if (_AddMappedFont(name
) == B_OK
)
970 return _FindFamily(name
);
973 return _FindFamily(name
);
978 FontManager::GetFamily(uint16 familyID
) const
980 FontKey
key(familyID
, 0);
981 FontStyle
* style
= (FontStyle
*)fStyleHashTable
.GetValue(key
);
983 return style
->Family();
990 FontManager::GetStyleByIndex(const char* familyName
, int32 index
)
992 FontFamily
* family
= GetFamily(familyName
);
994 return family
->StyleAt(index
);
1001 FontManager::GetStyleByIndex(uint16 familyID
, int32 index
)
1003 FontFamily
* family
= GetFamily(familyID
);
1005 return family
->StyleAt(index
);
1011 /*! \brief Retrieves the FontStyle object that comes closest to the one
1014 \param family The font's family or NULL in which case \a familyID is used
1015 \param style The font's style or NULL in which case \a styleID is used
1016 \param familyID will only be used if \a family is NULL (or empty)
1017 \param styleID will only be used if \a style is NULL (or empty)
1018 \param face is used to specify the style if both \a style is NULL or empty
1019 and styleID is 0xffff.
1021 \return The FontStyle having those attributes or NULL if not available
1024 FontManager::GetStyle(const char* familyName
, const char* styleName
,
1025 uint16 familyID
, uint16 styleID
, uint16 face
)
1031 if (familyName
!= NULL
&& familyName
[0])
1032 family
= GetFamily(familyName
);
1034 family
= GetFamily(familyID
);
1041 if (styleName
!= NULL
&& styleName
[0]) {
1042 FontStyle
* fontStyle
= family
->GetStyle(styleName
);
1043 if (fontStyle
!= NULL
)
1046 // before we fail, we try the mappings for a match
1047 if (_AddMappedFont(family
->Name(), styleName
) == B_OK
) {
1048 fontStyle
= family
->GetStyle(styleName
);
1049 if (fontStyle
!= NULL
)
1054 return family
->GetStyle(styleName
);
1057 if (styleID
!= 0xffff)
1058 return family
->GetStyleByID(styleID
);
1060 // try to get from face
1061 return family
->GetStyleMatchingFace(face
);
1065 /*! \brief Retrieves the FontStyle object
1066 \param family ID for the font's family
1067 \param style ID of the font's style
1068 \return The FontStyle having those attributes or NULL if not available
1071 FontManager::GetStyle(uint16 familyID
, uint16 styleID
) const
1073 FontKey
key(familyID
, styleID
);
1074 return (FontStyle
*)fStyleHashTable
.GetValue(key
);
1078 /*! \brief If you don't find your preferred font style, but are anxious
1079 to have one fitting your needs, you may want to use this method.
1082 FontManager::FindStyleMatchingFace(uint16 face
) const
1084 int32 count
= fFamilies
.CountItems();
1086 for (int32 i
= 0; i
< count
; i
++) {
1087 FontFamily
* family
= fFamilies
.ItemAt(i
);
1088 FontStyle
* style
= family
->GetStyleMatchingFace(face
);
1097 /*! \brief This call is used by the FontStyle class - and the FontStyle class
1098 only - to remove itself from the font manager.
1099 At this point, the style is already no longer available to the user.
1102 FontManager::RemoveStyle(FontStyle
* style
)
1104 FontFamily
* family
= style
->Family();
1106 debugger("family is NULL!");
1108 FontStyle
* check
= GetStyle(family
->ID(), style
->ID());
1110 debugger("style removed but still available!");
1112 if (family
->RemoveStyle(style
)
1113 && family
->CountStyles() == 0)
1114 fFamilies
.RemoveItem(family
);
1119 FontManager::DefaultPlainFont() const
1121 return fDefaultPlainFont
;
1126 FontManager::DefaultBoldFont() const
1128 return fDefaultBoldFont
;
1133 FontManager::DefaultFixedFont() const
1135 return fDefaultFixedFont
;
1140 FontManager::AttachUser(uid_t userID
)
1142 BAutolock
locker(this);
1145 // TODO: actually, find_directory() cannot know which user ID we want here
1146 // TODO: avoids user fonts in safe mode
1148 if (find_directory(B_USER_FONTS_DIRECTORY
, &path
, true) == B_OK
)
1149 _AddPath(path
.Path());
1150 if (find_directory(B_USER_NONPACKAGED_FONTS_DIRECTORY
, &path
, true)
1152 _AddPath(path
.Path());
1159 FontManager::DetachUser(uid_t userID
)
1161 BAutolock
locker(this);