app_server: make FontFamily referenceable

FontStyle will be keeping the references, so the family will exist as
long as there's a style pointing to it.

Change-Id: I639f7914be924a84d5db5882c638a4dac665aa23
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7634
Reviewed-by: Fredrik Holmqvist <fredrik.holmqvist@gmail.com>
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
This commit is contained in:
Máximo Castañeda 2024-04-18 20:36:54 +02:00 committed by waddlesplash
parent 0b8508801b
commit 7866929cf9
6 changed files with 29 additions and 57 deletions

View File

@ -62,24 +62,6 @@ FontFamily::FontFamily(const char *name, uint16 id)
} }
/*!
\brief Destructor
Deletes all attached styles. Note that a FontFamily must only be deleted
by the font manager.
*/
FontFamily::~FontFamily()
{
for (int32 i = fStyles.CountItems(); i-- > 0;) {
FontStyle* style = fStyles.RemoveItemAt(i);
// we remove us before deleting the style, so that the font manager
// is not contacted to remove the style from us
style->_SetFontFamily(NULL, -1);
}
}
/*! /*!
\brief Returns the name of the family \brief Returns the name of the family
\return The family's name \return The family's name

View File

@ -11,6 +11,7 @@
#include <ObjectList.h> #include <ObjectList.h>
#include <Referenceable.h>
#include <String.h> #include <String.h>
#include "FontStyle.h" #include "FontStyle.h"
@ -23,10 +24,9 @@
FontFamily objects bring together many styles of the same face, such as FontFamily objects bring together many styles of the same face, such as
Arial Roman, Arial Italic, Arial Bold, etc. Arial Roman, Arial Italic, Arial Bold, etc.
*/ */
class FontFamily { class FontFamily : public BReferenceable {
public: public:
FontFamily(const char* name, uint16 id); FontFamily(const char* name, uint16 id);
virtual ~FontFamily();
const char* Name() const; const char* Name() const;

View File

@ -289,15 +289,8 @@ FontManager::RemoveStyle(FontStyle* style)
if (family == NULL) if (family == NULL)
debugger("family is NULL!"); debugger("family is NULL!");
family->RemoveStyle(style);
fDelistedStyleHashTable.Remove(FontKey(family->ID(), style->ID())); fDelistedStyleHashTable.Remove(FontKey(family->ID(), style->ID()));
int count = fDelistedFamilies.Get(family) - 1;
if (count == 0)
fDelistedFamilies.Remove(family);
else if (count > 0)
fDelistedFamilies.Put(family, count);
if (family->CountStyles() == 0 && !fDelistedFamilies.ContainsKey(family))
delete family;
} }
@ -307,22 +300,20 @@ FontManager::_AddFont(FT_Face face, node_ref nodeRef, const char* path,
{ {
ASSERT(IsLocked()); ASSERT(IsLocked());
FontFamily* family = _FindFamily(face->family_name); BReference<FontFamily> family(_FindFamily(face->family_name));
bool isNewFontFamily = family == NULL; bool isNewFontFamily = !family.IsSet();
if (family != NULL && family->HasStyle(face->style_name)) { if (family.IsSet() && family->HasStyle(face->style_name)) {
// prevent adding the same style twice // prevent adding the same style twice
// (this indicates a problem with the installed fonts maybe?) // (this indicates a problem with the installed fonts maybe?)
FT_Done_Face(face); FT_Done_Face(face);
return B_NAME_IN_USE; return B_NAME_IN_USE;
} }
if (family == NULL) { if (!family.IsSet()) {
family = new (std::nothrow) FontFamily(face->family_name, _NextID()); family.SetTo(new (std::nothrow) FontFamily(face->family_name, _NextID()), true);
if (family == NULL if (!family.IsSet() || !fFamilies.BinaryInsert(family, compare_font_families)) {
|| !fFamilies.BinaryInsert(family, compare_font_families)) {
delete family;
FT_Done_Face(face); FT_Done_Face(face);
return B_NO_MEMORY; return B_NO_MEMORY;
} }
@ -335,10 +326,8 @@ FontManager::_AddFont(FT_Face face, node_ref nodeRef, const char* path,
if (style == NULL || !family->AddStyle(style)) { if (style == NULL || !family->AddStyle(style)) {
delete style; delete style;
if (isNewFontFamily) { if (isNewFontFamily)
fFamilies.RemoveItem(family); fFamilies.RemoveItem(family);
delete family;
}
return B_NO_MEMORY; return B_NO_MEMORY;
} }
@ -362,7 +351,6 @@ FontManager::_RemoveFont(uint16 familyID, uint16 styleID)
if (style != NULL) { if (style != NULL) {
fDelistedStyleHashTable.Put(key, style); fDelistedStyleHashTable.Put(key, style);
FontFamily* family = style->Family(); FontFamily* family = style->Family();
fDelistedFamilies.Put(family, fDelistedFamilies.Get(family) + 1);
if (family->RemoveStyle(style) && family->CountStyles() == 0) if (family->RemoveStyle(style) && family->CountStyles() == 0)
fFamilies.RemoveItem(family); fFamilies.RemoveItem(family);
fStyleHashTable.Remove(key); fStyleHashTable.Remove(key);
@ -374,20 +362,19 @@ FontManager::_RemoveFont(uint16 familyID, uint16 styleID)
void void
FontManager::_RemoveAllFonts() FontManager::_RemoveAllFonts()
{ {
for (int32 i = fFamilies.CountItems(); i-- > 0;) { fFamilies.MakeEmpty();
FontFamily* family = fFamilies.RemoveItemAt(i);
fDelistedFamilies.Remove(family);
delete family;
}
HashMap<FontKey, FontStyle*>::Iterator it = fDelistedStyleHashTable.GetIterator(); // Disconnect the styles from their families before removing them; once we
while (it.HasNext()) { // get to this point, we are in the dtor and don't want them to call back.
FontFamily* family = it.Next().value->Family();
fDelistedFamilies.Remove(family);
delete family;
}
fDelistedFamilies.Clear(); HashMap<FontKey, FontStyle*>::Iterator delisted = fDelistedStyleHashTable.GetIterator();
while (delisted.HasNext())
delisted.Next().value->_SetFontFamily(NULL, -1);
fDelistedStyleHashTable.Clear();
HashMap<FontKey, BReference<FontStyle> >::Iterator referenced = fStyleHashTable.GetIterator();
while (referenced.HasNext())
referenced.Next().value->_SetFontFamily(NULL, -1);
fStyleHashTable.Clear(); fStyleHashTable.Clear();
} }

View File

@ -102,8 +102,6 @@ private:
private: private:
typedef BObjectList<FontFamily> FamilyList; typedef BObjectList<FontFamily> FamilyList;
FamilyList fFamilies; FamilyList fFamilies;
HashMap<HashKeyPointer<FontFamily*>, int>
fDelistedFamilies;
HashMap<FontKey, BReference<FontStyle> > fStyleHashTable; HashMap<FontKey, BReference<FontStyle> > fStyleHashTable;
HashMap<FontKey, FontStyle*> fDelistedStyleHashTable; HashMap<FontKey, FontStyle*> fDelistedStyleHashTable;

View File

@ -96,7 +96,7 @@ FontStyle::FontStyle(node_ref& nodeRef, const char* path, FT_Face face,
FontStyle::~FontStyle() FontStyle::~FontStyle()
{ {
// make sure the font server is ours // make sure the font server is ours
if (fFamily != NULL && fFontManager->Lock()) { if (fFamily.IsSet() && fFontManager->Lock()) {
fFontManager->RemoveStyle(this); fFontManager->RemoveStyle(this);
fFontManager->Unlock(); fFontManager->Unlock();
} }
@ -227,7 +227,10 @@ FontStyle::UpdateFace(FT_Face face)
void void
FontStyle::_SetFontFamily(FontFamily* family, uint16 id) FontStyle::_SetFontFamily(FontFamily* family, uint16 id)
{ {
fFamily = family; if (fFamily.IsSet())
fFamily->RemoveStyle(this);
fFamily.SetTo(family);
fID = id; fID = id;
} }

View File

@ -144,6 +144,7 @@ class FontStyle : public BReferenceable {
private: private:
friend class FontFamily; friend class FontFamily;
friend class FontManager;
uint16 _TranslateStyleToFace(const char *name) const; uint16 _TranslateStyleToFace(const char *name) const;
void _SetFontFamily(FontFamily* family, uint16 id); void _SetFontFamily(FontFamily* family, uint16 id);
private: private:
@ -152,7 +153,8 @@ class FontStyle : public BReferenceable {
BPath fPath; BPath fPath;
node_ref fNodeRef; node_ref fNodeRef;
FontFamily* fFamily; BReference<FontFamily>
fFamily;
uint16 fID; uint16 fID;
BRect fBounds; BRect fBounds;