From c12196d47bdd9c037dc4ec7f2810663274f32897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 10 Nov 2005 17:32:35 +0000 Subject: [PATCH] * Removing fonts now works as expected. * removing a font family or style now always goes through the font manager. * removed FreeType "cache" remains (it wasn't used, anyway, and won't be used by us). * renamed SharedObject to ReferenceCounting as that's what it does. * the default fonts weren't deleted on shutdown. * added temporary work-around for waiting until a newly created entry is complete (just waits a moment...) - this will be fixed once Haiku supports this in a better way. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14833 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/servers/app/FontFamily.h | 7 +- headers/private/servers/app/FontManager.h | 7 +- .../{SharedObject.h => ReferenceCounting.h} | 26 ++--- src/servers/app/FontFamily.cpp | 45 +++------ src/servers/app/FontManager.cpp | 98 +++++++++++++------ src/servers/app/ServerFont.cpp | 1 + 6 files changed, 106 insertions(+), 78 deletions(-) rename headers/private/servers/app/{SharedObject.h => ReferenceCounting.h} (54%) diff --git a/headers/private/servers/app/FontFamily.h b/headers/private/servers/app/FontFamily.h index c878a99dff..6d61ad3aa7 100644 --- a/headers/private/servers/app/FontFamily.h +++ b/headers/private/servers/app/FontFamily.h @@ -19,7 +19,7 @@ #include #include FT_FREETYPE_H -#include "SharedObject.h" +#include "ReferenceCounting.h" #include "HashTable.h" @@ -66,7 +66,7 @@ class FontKey : public Hashable { FontStyle objects help abstract a lot of the font engine details while still offering plenty of information the style in question. */ -class FontStyle : public SharedObject, public Hashable, public BLocker { +class FontStyle : public ReferenceCounting, public Hashable, public BLocker { public: FontStyle(node_ref& nodeRef, const char* path, FT_Face face); virtual ~FontStyle(); @@ -189,8 +189,7 @@ class FontFamily { const char* Name() const; bool AddStyle(FontStyle* style); - bool RemoveStyle(const char* style, bool deleteSelfIfEmpty = true); - bool RemoveStyle(FontStyle* style, bool deleteSelfIfEmpty = true); + bool RemoveStyle(FontStyle* style); FontStyle* GetStyle(const char* style) const; FontStyle* GetStyleMatchingFace(uint16 face) const; diff --git a/headers/private/servers/app/FontManager.h b/headers/private/servers/app/FontManager.h index 3539bb9b84..082a4252ad 100644 --- a/headers/private/servers/app/FontManager.h +++ b/headers/private/servers/app/FontManager.h @@ -17,7 +17,6 @@ #include #include FT_FREETYPE_H -#include FT_CACHE_H class BPath; @@ -56,6 +55,9 @@ class FontManager : public BLooper { FontStyle *GetStyle(uint16 familyID, uint16 styleID) const; FontStyle* FindStyleMatchingFace(uint16 face) const; + void RemoveStyle(FontStyle* style); + // this call must not be used by anything else than class FontStyle + const ServerFont* DefaultPlainFont() const; const ServerFont* DefaultBoldFont() const; const ServerFont* DefaultFixedFont() const; @@ -78,8 +80,9 @@ class FontManager : public BLooper { status_t _AddPath(const char* path); status_t _AddPath(BEntry& entry, font_directory** _newDirectory = NULL); + void _RemoveStyle(font_directory& directory, FontStyle* style); + void _RemoveStyle(dev_t device, uint64 directory, uint64 node); FontFamily* _FindFamily(const char* family) const; - void _RemoveFamily(const char* family); void _ScanFontsIfNecessary(); void _ScanFonts(); diff --git a/headers/private/servers/app/SharedObject.h b/headers/private/servers/app/ReferenceCounting.h similarity index 54% rename from headers/private/servers/app/SharedObject.h rename to headers/private/servers/app/ReferenceCounting.h index 016be5d6ff..2b8f5435cc 100644 --- a/headers/private/servers/app/SharedObject.h +++ b/headers/private/servers/app/ReferenceCounting.h @@ -6,26 +6,26 @@ * DarkWyrm * Axel Dörfler, axeld@pinc-software.de */ -#ifndef SHARED_OBJECT_H -#define SHARED_OBJECT_H +#ifndef REFERENCE_COUNTING_H +#define REFERENCE_COUNTING_H #include /*! - \class SharedObject SharedObject.h - \brief Base class for shared objects - - SharedObjects track dependencies upon a particular object. In this way, is is - possible to ensure that a shared resource is not deleted if something else + \class ReferenceCounting ReferenceCounting.h + \brief Base class for reference counting objects + + ReferenceCounting objects track dependencies upon a particular object. In this way, + it is possible to ensure that a shared resource is not deleted if something else needs it. How the dependency tracking is done largely depends on the child class. */ -class SharedObject { +class ReferenceCounting { public: - SharedObject() + ReferenceCounting() : fReferenceCount(1) {} - virtual ~SharedObject() {} + virtual ~ReferenceCounting() {} inline void Acquire(); inline bool Release(); @@ -36,13 +36,13 @@ class SharedObject { inline void -SharedObject::Acquire() +ReferenceCounting::Acquire() { atomic_add(&fReferenceCount, 1); } inline bool -SharedObject::Release() +ReferenceCounting::Release() { if (atomic_add(&fReferenceCount, -1) == 1) { delete this; @@ -52,4 +52,4 @@ SharedObject::Release() return false; } -#endif /* SHARED_OBJECT_H */ +#endif /* REFERENCE_COUNTING_H */ diff --git a/src/servers/app/FontFamily.cpp b/src/servers/app/FontFamily.cpp index a2fb967760..d8da5e2893 100644 --- a/src/servers/app/FontFamily.cpp +++ b/src/servers/app/FontFamily.cpp @@ -84,7 +84,7 @@ FontStyle::~FontStyle() { // make sure the font server is ours if (fFamily != NULL && gFontManager->Lock()) { - fFamily->RemoveStyle(this, false); + gFontManager->RemoveStyle(this); gFontManager->Unlock(); } @@ -264,15 +264,19 @@ FontFamily::FontFamily(const char *name, uint16 id) /*! \brief Destructor - Deletes all child styles. Note that a FontFamily should not be deleted unless - its styles have no dependencies or some other really good reason, such as - system shutdown. + Deletes all attached styles. Note that a FontFamily must only be deleted + by the font manager. */ FontFamily::~FontFamily() { - // styles are removing itself when deleted - for (int32 i = fStyles.CountItems(); i-- > 0;) - delete fStyles.ItemAt(i); + 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); + delete style; + } } @@ -317,28 +321,13 @@ FontFamily::AddStyle(FontStyle *style) } -bool -FontFamily::RemoveStyle(const char* styleName, bool deleteSelfIfEmpty) -{ - FontStyle *style = GetStyle(styleName); - if (style != NULL) - return RemoveStyle(style, deleteSelfIfEmpty); - - return false; -} - - /*! \brief Removes a style from the family. - The font family may be deleted during this call - the object might not - be valid anymore after this call. - The font style will not be altered. - - \param style The style to be removed from the family + The font style will not be deleted. */ bool -FontFamily::RemoveStyle(FontStyle* style, bool deleteSelfIfEmpty) +FontFamily::RemoveStyle(FontStyle* style) { if (!gFontManager->IsLocked()) { debugger("FontFamily::RemoveStyle() called without having the font manager locked!"); @@ -348,14 +337,10 @@ FontFamily::RemoveStyle(FontStyle* style, bool deleteSelfIfEmpty) if (!fStyles.RemoveItem(style)) return false; - // force a refresh if a request for font flags is needed - fFlags = kInvalidFamilyFlags; - style->_SetFontFamily(NULL, -1); - if (deleteSelfIfEmpty && CountStyles() == 0) - delete this; - + // force a refresh if a request for font flags is needed + fFlags = kInvalidFamilyFlags; return true; } diff --git a/src/servers/app/FontManager.cpp b/src/servers/app/FontManager.cpp index 26e4d25c5f..a90d9df410 100644 --- a/src/servers/app/FontManager.cpp +++ b/src/servers/app/FontManager.cpp @@ -38,7 +38,6 @@ // TODO: needs some more work for multi-user support -static FTC_Manager ftmanager; FT_Library gFreeTypeLibrary; FontManager *gFontManager = NULL; @@ -116,29 +115,22 @@ FontManager::FontManager() fInitStatus = _SetDefaultFonts(); } - -/* - Fire up the font caching subsystem. - The three zeros tell FreeType to use the defaults, which are 2 faces, - 4 face sizes, and a maximum of 200000 bytes. I will probably change - these numbers in the future to maximize performance for your "average" - application. -*/ -// if (FTC_Manager_New(gFreeTypeLibrary, 0, 0, 0, &face_requester, NULL, &ftmanager) != 0) -// fInit = false; } //! Frees items allocated in the constructor and shuts down FreeType FontManager::~FontManager() { + delete fDefaultPlainFont; + delete fDefaultBoldFont; + delete fDefaultFixedFont; + // free families before we're done with FreeType for (int32 i = fFamilies.CountItems(); i-- > 0;) { delete fFamilies.ItemAt(i); } - FTC_Manager_Done(ftmanager); FT_Done_FreeType(gFreeTypeLibrary); } @@ -165,6 +157,10 @@ FontManager::MessageReceived(BMessage* message) || message->FindString("name", &name) != B_OK) break; + // TODO: make this better (possible under Haiku) + snooze(100000); + // let the font be written completely before trying to open it + BEntry entry; if (set_entry(nodeRef, name, entry) != B_OK) break; @@ -184,6 +180,7 @@ FontManager::MessageReceived(BMessage* message) } break; } + case B_ENTRY_MOVED: { // has the entry been moved into a monitored directory or has @@ -234,16 +231,20 @@ FontManager::MessageReceived(BMessage* message) if (entry.GetNodeRef(&nodeRef) == B_OK && (directory = _FindDirectory(nodeRef)) != NULL) _RemoveDirectory(directory); - } else - WTRACE(("font removed: %s\n", name)); + } else { + // remove font style from directory + _RemoveStyle(nodeRef.device, fromNode, node); + } } - break; } + case B_ENTRY_REMOVED: { node_ref nodeRef; + uint64 directoryNode; if (message->FindInt32("device", &nodeRef.device) != B_OK + || message->FindInt64("directory", (int64 *)&directoryNode) != B_OK || message->FindInt64("node", &nodeRef.node) != B_OK) break; @@ -252,8 +253,8 @@ FontManager::MessageReceived(BMessage* message) // the directory has been removed, so we remove it as well _RemoveDirectory(directory); } else { - // a font was removed? - WTRACE(("removed a font?")); + // remove font style from directory + _RemoveStyle(nodeRef.device, directoryNode, nodeRef.node); } break; } @@ -278,23 +279,40 @@ FontManager::_LoadRecentFontMappings() /*! - \brief Removes a font family from the font list - \param family The family to remove + \brief Removes the style from the font directory. + + It doesn't necessary delete the font style, if it's still + in use, though. */ void -FontManager::_RemoveFamily(const char *familyName) +FontManager::_RemoveStyle(font_directory& directory, FontStyle* style) { - FontFamily *family = GetFamily(familyName); - if (family) { - // remove styles from hash - for (int32 i = 0; i < family->CountStyles(); i++) { - FontStyle* style = family->StyleAt(i); + WTRACE(("font removed: %s\n", style->Name())); - fStyleHashTable.RemoveItem(*style); - } + directory.styles.RemoveItem(style); + directory.revision++; - fFamilies.RemoveItem(family); - delete family; + fStyleHashTable.RemoveItem(*style); + + style->Release(); +} + + +void +FontManager::_RemoveStyle(dev_t device, uint64 directoryNode, uint64 node) +{ + // remove font style from directory + node_ref nodeRef; + nodeRef.device = device; + nodeRef.node = directoryNode; + + font_directory* directory = _FindDirectory(nodeRef); + if (directory != NULL) { + // find style in directory and remove it + nodeRef.node = node; + FontStyle* style = directory->FindStyle(nodeRef); + if (style != NULL) + _RemoveStyle(*directory, style); } } @@ -863,6 +881,28 @@ FontManager::FindStyleMatchingFace(uint16 face) const } +/*! + \brief This call is used by the FontStyle class - and the FontStyle class + only - to remove itself from the font manager. + At this point, the style is already no longer available to the user. +*/ +void +FontManager::RemoveStyle(FontStyle* style) +{ + FontFamily* family = style->Family(); + if (family == NULL) + debugger("family is NULL!"); + + FontStyle* check = GetStyle(family->ID(), style->ID()); + if (check != NULL) + debugger("style removed but still available!"); + + if (family->RemoveStyle(style) + && family->CountStyles() == 0) + fFamilies.RemoveItem(family); +} + + const ServerFont* FontManager::DefaultPlainFont() const { diff --git a/src/servers/app/ServerFont.cpp b/src/servers/app/ServerFont.cpp index add2712017..4dc2f01234 100644 --- a/src/servers/app/ServerFont.cpp +++ b/src/servers/app/ServerFont.cpp @@ -19,6 +19,7 @@ #include "truncate_string.h" #include FT_FREETYPE_H +#include FT_GLYPH_H #include FT_OUTLINE_H #include "ServerFont.h"