* 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
This commit is contained in:
Axel Dörfler
2005-11-10 17:32:35 +00:00
parent 779d5736a3
commit c12196d47b
6 changed files with 106 additions and 78 deletions
+3 -4
View File
@@ -19,7 +19,7 @@
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
#include "SharedObject.h" #include "ReferenceCounting.h"
#include "HashTable.h" #include "HashTable.h"
@@ -66,7 +66,7 @@ class FontKey : public Hashable {
FontStyle objects help abstract a lot of the font engine details while FontStyle objects help abstract a lot of the font engine details while
still offering plenty of information the style in question. 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: public:
FontStyle(node_ref& nodeRef, const char* path, FT_Face face); FontStyle(node_ref& nodeRef, const char* path, FT_Face face);
virtual ~FontStyle(); virtual ~FontStyle();
@@ -189,8 +189,7 @@ class FontFamily {
const char* Name() const; const char* Name() const;
bool AddStyle(FontStyle* style); bool AddStyle(FontStyle* style);
bool RemoveStyle(const char* style, bool deleteSelfIfEmpty = true); bool RemoveStyle(FontStyle* style);
bool RemoveStyle(FontStyle* style, bool deleteSelfIfEmpty = true);
FontStyle* GetStyle(const char* style) const; FontStyle* GetStyle(const char* style) const;
FontStyle* GetStyleMatchingFace(uint16 face) const; FontStyle* GetStyleMatchingFace(uint16 face) const;
+5 -2
View File
@@ -17,7 +17,6 @@
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
#include FT_CACHE_H
class BPath; class BPath;
@@ -56,6 +55,9 @@ class FontManager : public BLooper {
FontStyle *GetStyle(uint16 familyID, uint16 styleID) const; FontStyle *GetStyle(uint16 familyID, uint16 styleID) const;
FontStyle* FindStyleMatchingFace(uint16 face) 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* DefaultPlainFont() const;
const ServerFont* DefaultBoldFont() const; const ServerFont* DefaultBoldFont() const;
const ServerFont* DefaultFixedFont() const; const ServerFont* DefaultFixedFont() const;
@@ -78,8 +80,9 @@ class FontManager : public BLooper {
status_t _AddPath(const char* path); status_t _AddPath(const char* path);
status_t _AddPath(BEntry& entry, font_directory** _newDirectory = NULL); 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; FontFamily* _FindFamily(const char* family) const;
void _RemoveFamily(const char* family);
void _ScanFontsIfNecessary(); void _ScanFontsIfNecessary();
void _ScanFonts(); void _ScanFonts();
@@ -6,26 +6,26 @@
* DarkWyrm <bpmagic@columbus.rr.com> * DarkWyrm <bpmagic@columbus.rr.com>
* Axel Dörfler, axeld@pinc-software.de * Axel Dörfler, axeld@pinc-software.de
*/ */
#ifndef SHARED_OBJECT_H #ifndef REFERENCE_COUNTING_H
#define SHARED_OBJECT_H #define REFERENCE_COUNTING_H
#include <SupportDefs.h> #include <SupportDefs.h>
/*! /*!
\class SharedObject SharedObject.h \class ReferenceCounting ReferenceCounting.h
\brief Base class for shared objects \brief Base class for reference counting objects
SharedObjects track dependencies upon a particular object. In this way, is is ReferenceCounting objects track dependencies upon a particular object. In this way,
possible to ensure that a shared resource is not deleted if something else 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. needs it. How the dependency tracking is done largely depends on the child class.
*/ */
class SharedObject { class ReferenceCounting {
public: public:
SharedObject() ReferenceCounting()
: fReferenceCount(1) {} : fReferenceCount(1) {}
virtual ~SharedObject() {} virtual ~ReferenceCounting() {}
inline void Acquire(); inline void Acquire();
inline bool Release(); inline bool Release();
@@ -36,13 +36,13 @@ class SharedObject {
inline void inline void
SharedObject::Acquire() ReferenceCounting::Acquire()
{ {
atomic_add(&fReferenceCount, 1); atomic_add(&fReferenceCount, 1);
} }
inline bool inline bool
SharedObject::Release() ReferenceCounting::Release()
{ {
if (atomic_add(&fReferenceCount, -1) == 1) { if (atomic_add(&fReferenceCount, -1) == 1) {
delete this; delete this;
@@ -52,4 +52,4 @@ SharedObject::Release()
return false; return false;
} }
#endif /* SHARED_OBJECT_H */ #endif /* REFERENCE_COUNTING_H */
+15 -30
View File
@@ -84,7 +84,7 @@ FontStyle::~FontStyle()
{ {
// make sure the font server is ours // make sure the font server is ours
if (fFamily != NULL && gFontManager->Lock()) { if (fFamily != NULL && gFontManager->Lock()) {
fFamily->RemoveStyle(this, false); gFontManager->RemoveStyle(this);
gFontManager->Unlock(); gFontManager->Unlock();
} }
@@ -264,15 +264,19 @@ FontFamily::FontFamily(const char *name, uint16 id)
/*! /*!
\brief Destructor \brief Destructor
Deletes all child styles. Note that a FontFamily should not be deleted unless Deletes all attached styles. Note that a FontFamily must only be deleted
its styles have no dependencies or some other really good reason, such as by the font manager.
system shutdown.
*/ */
FontFamily::~FontFamily() FontFamily::~FontFamily()
{ {
// styles are removing itself when deleted for (int32 i = fStyles.CountItems(); i-- > 0;) {
for (int32 i = fStyles.CountItems(); i-- > 0;) FontStyle* style = fStyles.RemoveItemAt(i);
delete fStyles.ItemAt(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. \brief Removes a style from the family.
The font family may be deleted during this call - the object might not The font style will not be deleted.
be valid anymore after this call.
The font style will not be altered.
\param style The style to be removed from the family
*/ */
bool bool
FontFamily::RemoveStyle(FontStyle* style, bool deleteSelfIfEmpty) FontFamily::RemoveStyle(FontStyle* style)
{ {
if (!gFontManager->IsLocked()) { if (!gFontManager->IsLocked()) {
debugger("FontFamily::RemoveStyle() called without having the font manager locked!"); debugger("FontFamily::RemoveStyle() called without having the font manager locked!");
@@ -348,14 +337,10 @@ FontFamily::RemoveStyle(FontStyle* style, bool deleteSelfIfEmpty)
if (!fStyles.RemoveItem(style)) if (!fStyles.RemoveItem(style))
return false; return false;
// force a refresh if a request for font flags is needed
fFlags = kInvalidFamilyFlags;
style->_SetFontFamily(NULL, -1); style->_SetFontFamily(NULL, -1);
if (deleteSelfIfEmpty && CountStyles() == 0) // force a refresh if a request for font flags is needed
delete this; fFlags = kInvalidFamilyFlags;
return true; return true;
} }
+69 -29
View File
@@ -38,7 +38,6 @@
// TODO: needs some more work for multi-user support // TODO: needs some more work for multi-user support
static FTC_Manager ftmanager;
FT_Library gFreeTypeLibrary; FT_Library gFreeTypeLibrary;
FontManager *gFontManager = NULL; FontManager *gFontManager = NULL;
@@ -116,29 +115,22 @@ FontManager::FontManager()
fInitStatus = _SetDefaultFonts(); 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 //! Frees items allocated in the constructor and shuts down FreeType
FontManager::~FontManager() FontManager::~FontManager()
{ {
delete fDefaultPlainFont;
delete fDefaultBoldFont;
delete fDefaultFixedFont;
// free families before we're done with FreeType // free families before we're done with FreeType
for (int32 i = fFamilies.CountItems(); i-- > 0;) { for (int32 i = fFamilies.CountItems(); i-- > 0;) {
delete fFamilies.ItemAt(i); delete fFamilies.ItemAt(i);
} }
FTC_Manager_Done(ftmanager);
FT_Done_FreeType(gFreeTypeLibrary); FT_Done_FreeType(gFreeTypeLibrary);
} }
@@ -165,6 +157,10 @@ FontManager::MessageReceived(BMessage* message)
|| message->FindString("name", &name) != B_OK) || message->FindString("name", &name) != B_OK)
break; break;
// TODO: make this better (possible under Haiku)
snooze(100000);
// let the font be written completely before trying to open it
BEntry entry; BEntry entry;
if (set_entry(nodeRef, name, entry) != B_OK) if (set_entry(nodeRef, name, entry) != B_OK)
break; break;
@@ -184,6 +180,7 @@ FontManager::MessageReceived(BMessage* message)
} }
break; break;
} }
case B_ENTRY_MOVED: case B_ENTRY_MOVED:
{ {
// has the entry been moved into a monitored directory or has // 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 if (entry.GetNodeRef(&nodeRef) == B_OK
&& (directory = _FindDirectory(nodeRef)) != NULL) && (directory = _FindDirectory(nodeRef)) != NULL)
_RemoveDirectory(directory); _RemoveDirectory(directory);
} else } else {
WTRACE(("font removed: %s\n", name)); // remove font style from directory
_RemoveStyle(nodeRef.device, fromNode, node);
}
} }
break; break;
} }
case B_ENTRY_REMOVED: case B_ENTRY_REMOVED:
{ {
node_ref nodeRef; node_ref nodeRef;
uint64 directoryNode;
if (message->FindInt32("device", &nodeRef.device) != B_OK if (message->FindInt32("device", &nodeRef.device) != B_OK
|| message->FindInt64("directory", (int64 *)&directoryNode) != B_OK
|| message->FindInt64("node", &nodeRef.node) != B_OK) || message->FindInt64("node", &nodeRef.node) != B_OK)
break; break;
@@ -252,8 +253,8 @@ FontManager::MessageReceived(BMessage* message)
// the directory has been removed, so we remove it as well // the directory has been removed, so we remove it as well
_RemoveDirectory(directory); _RemoveDirectory(directory);
} else { } else {
// a font was removed? // remove font style from directory
WTRACE(("removed a font?")); _RemoveStyle(nodeRef.device, directoryNode, nodeRef.node);
} }
break; break;
} }
@@ -278,23 +279,40 @@ FontManager::_LoadRecentFontMappings()
/*! /*!
\brief Removes a font family from the font list \brief Removes the style from the font directory.
\param family The family to remove
It doesn't necessary delete the font style, if it's still
in use, though.
*/ */
void void
FontManager::_RemoveFamily(const char *familyName) FontManager::_RemoveStyle(font_directory& directory, FontStyle* style)
{ {
FontFamily *family = GetFamily(familyName); WTRACE(("font removed: %s\n", style->Name()));
if (family) {
// remove styles from hash
for (int32 i = 0; i < family->CountStyles(); i++) {
FontStyle* style = family->StyleAt(i);
fStyleHashTable.RemoveItem(*style); directory.styles.RemoveItem(style);
} directory.revision++;
fFamilies.RemoveItem(family); fStyleHashTable.RemoveItem(*style);
delete family;
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* const ServerFont*
FontManager::DefaultPlainFont() const FontManager::DefaultPlainFont() const
{ {
+1
View File
@@ -19,6 +19,7 @@
#include "truncate_string.h" #include "truncate_string.h"
#include FT_FREETYPE_H #include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_OUTLINE_H #include FT_OUTLINE_H
#include "ServerFont.h" #include "ServerFont.h"