diff --git a/headers/private/servers/app/FontFamily.h b/headers/private/servers/app/FontFamily.h index f6aee71602..5f0e1609ea 100644 --- a/headers/private/servers/app/FontFamily.h +++ b/headers/private/servers/app/FontFamily.h @@ -84,85 +84,81 @@ typedef struct { */ class FontStyle : public SharedObject, public BLocker { public: - FontStyle(const char* filepath, - FT_Face face); - virtual ~FontStyle(); + FontStyle(const char* path, FT_Face face); + virtual ~FontStyle(); /*! \fn bool FontStyle::IsFixedWidth(void) \brief Determines whether the font's character width is fixed \return true if fixed, false if not */ - inline bool IsFixedWidth() const - { return fFTFace->face_flags & FT_FACE_FLAG_FIXED_WIDTH; } + bool IsFixedWidth() const + { return fFTFace->face_flags & FT_FACE_FLAG_FIXED_WIDTH; } /*! \fn bool FontStyle::IsScalable(void) \brief Determines whether the font can be scaled to any size \return true if scalable, false if not */ - inline bool IsScalable() const - { return fFTFace->face_flags & FT_FACE_FLAG_SCALABLE; } + bool IsScalable() const + { return fFTFace->face_flags & FT_FACE_FLAG_SCALABLE; } /*! \fn bool FontStyle::HasKerning(void) \brief Determines whether the font has kerning information \return true if kerning info is available, false if not */ - inline bool HasKerning() const - { return fFTFace->face_flags & FT_FACE_FLAG_KERNING; } + bool HasKerning() const + { return fFTFace->face_flags & FT_FACE_FLAG_KERNING; } /*! \fn bool FontStyle::HasTuned(void) \brief Determines whether the font contains strikes \return true if it has strikes included, false if not */ - inline bool HasTuned() const - { return fFTFace->num_fixed_sizes > 0; } + bool HasTuned() const + { return fFTFace->num_fixed_sizes > 0; } /*! \fn bool FontStyle::TunedCount(void) \brief Returns the number of strikes the style contains \return The number of strikes the style contains */ - inline int32 TunedCount() const - { return fFTFace->num_fixed_sizes; } + int32 TunedCount() const + { return fFTFace->num_fixed_sizes; } /*! \fn bool FontStyle::GlyphCount(void) \brief Returns the number of glyphs in the style \return The number of glyphs the style contains */ - inline uint16 GlyphCount() const - { return fFTFace->num_glyphs; } + uint16 GlyphCount() const + { return fFTFace->num_glyphs; } /*! \fn bool FontStyle::CharMapCount(void) \brief Returns the number of character maps the style contains \return The number of character maps the style contains */ - inline uint16 CharMapCount() const - { return fFTFace->num_charmaps; } + uint16 CharMapCount() const + { return fFTFace->num_charmaps; } - const char* Name() const; - inline FontFamily* Family() const - { return fFontFamily; } - inline uint16 ID() const - { return fID; } - int32 Flags() const; + const char* Name() const; + FontFamily* Family() const + { return fFontFamily; } + uint16 ID() const + { return fID; } + int32 Flags() const; - inline uint16 Face() const - { return fFace; } - uint16 PreservedFace(uint16) const; + uint16 Face() const + { return fFace; } + uint16 PreservedFace(uint16) const; - const char* Path() const; - font_height GetHeight(const float& size) const; - font_direction Direction() const - { return B_FONT_LEFT_TO_RIGHT; } + const char* Path() const; + font_height GetHeight(const float& size) const; + font_direction Direction() const + { return B_FONT_LEFT_TO_RIGHT; } - inline FT_Face GetFTFace() const - { return fFTFace; } - - // TODO: Re-enable when I understand how the FT2 Cache system changed from - // 2.1.4 to 2.1.8 -// int16 ConvertToUnicode(uint16 c); + FT_Face GetFTFace() const + { return fFTFace; } - void AttachedToFamily(FontFamily* family); - void DetachedFromFamily(); +// TODO: Re-enable when I understand how the FT2 Cache system changed from +// 2.1.4 to 2.1.8 +// int16 ConvertToUnicode(uint16 c); private: friend class FontFamily; @@ -198,8 +194,7 @@ class FontStyle : public SharedObject, public BLocker { */ class FontFamily : public SharedObject { public: - FontFamily(const char* namestr, - const uint16& index); + FontFamily(const char* name, uint16 id); virtual ~FontFamily(); const char* Name() const; @@ -220,10 +215,11 @@ class FontFamily : public SharedObject { int32 CountStyles() const; FontStyle* StyleAt(int32 index) const; - protected: + private: BString fName; BObjectList fStyles; uint16 fID; + uint16 fNextID; int32 fFlags; }; diff --git a/headers/private/servers/app/FontServer.h b/headers/private/servers/app/FontServer.h index d5f4daa0f6..7f9be97085 100644 --- a/headers/private/servers/app/FontServer.h +++ b/headers/private/servers/app/FontServer.h @@ -20,6 +20,8 @@ #include FT_FREETYPE_H #include FT_CACHE_H +class BPath; + class FontFamily; class FontStyle; class ServerFont; @@ -41,7 +43,6 @@ class FontServer : public BLocker { void RemoveFamily(const char *family); void ScanSystemFolders(); status_t ScanDirectory(const char *path); - void SaveList(); FontFamily* GetFamilyByIndex(int32 index) const; FontFamily *GetFamily(uint16 familyID) const; @@ -67,8 +68,8 @@ class FontServer : public BLocker { */ void FontsUpdated() { fNeedUpdate = false; } - protected: - uint16 TranslateStyleToFace(const char *name) const; + private: + void _AddFont(BPath &path); FT_CharMap _GetSupportedCharmap(const FT_Face &face); @@ -77,6 +78,7 @@ class FontServer : public BLocker { BObjectList fFamilies; ServerFont *fPlain, *fBold, *fFixed; bool fNeedUpdate; + int32 fNextID; }; extern FTC_Manager ftmanager; diff --git a/src/servers/app/AppServer.cpp b/src/servers/app/AppServer.cpp index 0cb2636963..64cd8d0347 100644 --- a/src/servers/app/AppServer.cpp +++ b/src/servers/app/AppServer.cpp @@ -101,7 +101,6 @@ AppServer::AppServer() gFontServer = new FontServer; gFontServer->Lock(); gFontServer->ScanSystemFolders(); - gFontServer->SaveList(); if (!gFontServer->SetSystemPlain(DEFAULT_PLAIN_FONT_FAMILY, DEFAULT_PLAIN_FONT_STYLE, diff --git a/src/servers/app/FontFamily.cpp b/src/servers/app/FontFamily.cpp index 30a260d70a..41c8801118 100644 --- a/src/servers/app/FontFamily.cpp +++ b/src/servers/app/FontFamily.cpp @@ -1,50 +1,43 @@ -//------------------------------------------------------------------------------ -// Copyright (c) 2001-2002, Haiku, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -// -// File Name: FontFamily.cpp -// Author: DarkWyrm -// Description: classes to represent font styles and families -// -//------------------------------------------------------------------------------ +/* + * Copyright 2001-2005, Haiku. + * Distributed under the terms of the MIT License. + * + * Authors: + * DarkWyrm + * Axel Dörfler, axeld@pinc-software.de + */ + +/** Classes to represent font styles and families */ + + #include "FontFamily.h" #include "ServerFont.h" #include FT_CACHE_H + +const int32 kInvalidFamilyFlags = -1; + FTC_Manager ftmanager; + /*! \brief Constructor \param filepath path to a font file \param face FreeType handle for the font file after it is loaded - it will be kept open until the FontStyle is destroied */ -FontStyle::FontStyle(const char *filepath, FT_Face face) +FontStyle::FontStyle(const char *path, FT_Face face) : fFTFace(face), fFontFamily(NULL), fName(face->style_name), - fPath(filepath), + fPath(path), fBounds(0, 0, 0, 0), fID(0), fFace(_TranslateStyleToFace(face->style_name)) { + fName.Truncate(B_FONT_STYLE_LENGTH); + // make sure this style can be found using the Be API + // cachedface = new CachedFaceRec; // cachedface->file_path = filepath; @@ -71,8 +64,7 @@ FontStyle::~FontStyle() { // TODO: what was the purpose of this? // delete cachedface; -// TODO: figure out if it is safe to call this: -// FT_Done_Face(fFTFace); + FT_Done_Face(fFTFace); } @@ -200,13 +192,15 @@ FontStyle::_TranslateStyleToFace(const char *name) const \brief Constructor \param namestr Name of the family */ -FontFamily::FontFamily(const char *name, const uint16 &index) +FontFamily::FontFamily(const char *name, uint16 id) + : + fName(name), + fID(id), + fNextID(0), + fFlags(kInvalidFamilyFlags) { - fName = name; - fID = index; - - // will stay uninitialized until needed - fFlags = -1; + fName.Truncate(B_FONT_FAMILY_LENGTH); + // make sure this family can be found using the Be API } /*! @@ -220,7 +214,7 @@ FontFamily::~FontFamily() { int32 count = fStyles.CountItems(); for (int32 i = 0; i < count; i++) - delete (FontStyle*)fStyles.ItemAt(i); + delete fStyles.ItemAt(i); } @@ -245,30 +239,22 @@ FontFamily::AddStyle(FontStyle *style) if (!style) return false; - FontStyle *item; - // Don't add if it already is in the family. int32 count = fStyles.CountItems(); for (int32 i = 0; i < count; i++) { - item = (FontStyle*)fStyles.ItemAt(i); - if (item->Name() == style->Name()) + FontStyle *item = fStyles.ItemAt(i); + if (!strcmp(item->Name(), style->Name())) return false; } style->_SetFontFamily(this); - - if (fStyles.CountItems() > 0) { - item = (FontStyle*)fStyles.ItemAt(fStyles.CountItems() - 1); - style->_SetID(item->ID() + 1); - } else { - style->_SetID(0); - } + style->_SetID(fNextID++); fStyles.AddItem(style); AddDependent(); // force a refresh if a request for font flags is needed - fFlags = -1; + fFlags = kInvalidFamilyFlags; return true; } @@ -291,7 +277,7 @@ FontFamily::RemoveStyle(const char* styleName) RemoveDependent(); // force a refresh if a request for font flags is needed - fFlags = -1; + fFlags = kInvalidFamilyFlags; } @@ -306,7 +292,7 @@ FontFamily::RemoveStyle(FontStyle* style) RemoveDependent(); // force a refresh if a request for font flags is needed - fFlags = -1; + fFlags = kInvalidFamilyFlags; } } @@ -403,17 +389,16 @@ FontFamily::GetStyleMatchingFace(uint16 face) const int32 FontFamily::Flags() { - if (fFlags == -1) { + if (fFlags == kInvalidFamilyFlags) { fFlags = 0; for (int32 i = 0; i < fStyles.CountItems(); i++) { - FontStyle* style = (FontStyle*)fStyles.ItemAt(i); - if (style) { - if (style->IsFixedWidth()) - fFlags |= B_IS_FIXED; - if (style->TunedCount() > 0) - fFlags |= B_HAS_TUNED_FONT; - } + FontStyle* style = fStyles.ItemAt(i); + + if (style->IsFixedWidth()) + fFlags |= B_IS_FIXED; + if (style->TunedCount() > 0) + fFlags |= B_HAS_TUNED_FONT; } } diff --git a/src/servers/app/FontServer.cpp b/src/servers/app/FontServer.cpp index e65dfee4b9..25eb94440c 100644 --- a/src/servers/app/FontServer.cpp +++ b/src/servers/app/FontServer.cpp @@ -21,6 +21,8 @@ #include #include "ServerConfig.h" +#include + extern FTC_Manager ftmanager; FT_Library ftlib; @@ -52,7 +54,8 @@ FontServer::FontServer() fFamilies(20), fPlain(NULL), fBold(NULL), - fFixed(NULL) + fFixed(NULL), + fNextID(0) { fInitStatus = FT_Init_FreeType(&ftlib) == 0 ? B_OK : B_ERROR; @@ -132,19 +135,50 @@ FontServer::ScanSystemFolders(void) #endif } + +/*! + \brief Adds the FontFamily/FontStyle that is represented by this path. +*/ +void +FontServer::_AddFont(BPath &path) +{ + FT_Face face; + FT_Error error = FT_New_Face(ftlib, path.Path(), 0, &face); + if (error != 0) + return; + + FontFamily *family = GetFamily(face->family_name); + if (family != NULL && family->HasStyle(face->style_name)) { + // prevent adding the same style twice + // (this indicates a problem with the installed fonts maybe?) + FT_Done_Face(face); + return; + } + + if (family == NULL) { + family = new (nothrow) FontFamily(face->family_name, fNextID++); + if (family == NULL + || !fFamilies.AddItem(family)) { + delete family; + FT_Done_Face(face); + return; + } + } + +#ifdef PRINT_FONT_LIST + printf("\tFont Style: %s, %s\n", face->family_name, face->style_name); +#endif + + // the FontStyle takes over ownership of the FT_Face object + FontStyle *style = new FontStyle(path.Path(), face); + if (!family->AddStyle(style)) + delete style; +} + + /*! \brief Scan a folder for all valid fonts - \param fontspath Path of the folder to scan. - \return - - \c B_OK Success - - \c B_NAME_TOO_LONG The path specified is too long - - \c B_ENTRY_NOT_FOUND The path does not exist - - \c B_LINK_LIMIT A cyclic loop was detected in the file system - - \c B_BAD_VALUE Invalid input specified - - \c B_NO_MEMORY Insufficient memory to open the folder for reading - - \c B_BUSY A busy node could not be accessed - - \c B_FILE_ERROR An invalid file prevented the operation. - - \c B_NO_MORE_FDS All file descriptors are in use (too many open files). + \param directoryPath Path of the folder to scan. */ status_t FontServer::ScanDirectory(const char *directoryPath) @@ -165,10 +199,6 @@ FontServer::ScanDirectory(const char *directoryPath) if (status < B_OK) continue; - FT_Face face; - FT_Error error = FT_New_Face(ftlib, path.Path(), 0, &face); - if (error != 0) - continue; // TODO: Commenting this out makes my "Unicode glyph lookup" // work with our default fonts. The real fix is to select the @@ -186,34 +216,8 @@ FontServer::ScanDirectory(const char *directoryPath) face->charmap = charmap; #endif - FontFamily *family = GetFamily(face->family_name); - if (family == NULL) { - #ifdef PRINT_FONT_LIST - printf("Font Family: %s\n", face->family_name); - #endif - - family = new FontFamily(face->family_name, fFamilies.CountItems()); - fFamilies.AddItem(family); - } else { - // prevent adding the same style twice - // (this indicates a problem with the installed fonts maybe?) - if (family->HasStyle(face->style_name)) { - FT_Done_Face(face); - continue; - } - } - - #ifdef PRINT_FONT_LIST - printf("\tFont Style: %s\n", face->style_name); - #endif - - FontStyle *style = new FontStyle(path.Path(), face); - if (!family->AddStyle(style)) - delete style; - - // FT_Face is kept open in FontStyle and will be unset in the - // FontStyle destructor - // TODO: nope, it is not (yet) + _AddFont(path); + // takes over ownership of the FT_Face object } fNeedUpdate = true; @@ -261,82 +265,6 @@ FontServer::_GetSupportedCharmap(const FT_Face& face) } -/*! - \brief This saves all family names and styles to the file specified in - ServerConfig.h as SERVER_FONT_LIST as a flattened BMessage. - - This operation is not done very often because the access to disk adds a significant - performance hit. - - The format for storage consists of two things: an array of strings with the name 'family' - and a number of small string arrays which have the name of the font family. These are - the style lists. - - Additionally, any fonts which have bitmap strikes contained in them or any fonts which - are fixed-width are named in the arrays 'tuned' and 'fixed'. -*/ -void -FontServer::SaveList(void) -{ -/* int32 famcount=0, stycount=0,i=0,j=0; - FontFamily *fam; - FontStyle *sty; - BMessage fontmsg, familymsg('FONT'); - BString famname, styname, extraname; - bool fixed,tuned; - - famcount=families->CountItems(); - for(i=0; iItemAt(i); - fixed=false; - tuned=false; - if(!fam) - continue; - - famname=fam->Name(); - - // Add the family to the message - familymsg.AddString("name",famname); - - stycount=fam->CountStyles(); - for(j=0;jGetStyle(j)); - if(styname.CountChars()>0) - { - // Add to list - familymsg.AddString("styles", styname); - - // Check to see if it has prerendered strikes (has "tuned" fonts) - sty=fam->GetStyle(styname.String()); - if(!sty) - continue; - - if(sty->HasTuned() && sty->IsScalable()) - tuned=true; - - // Check to see if it is fixed-width - if(sty->IsFixedWidth()) - fixed=true; - } - } - if(tuned) - familymsg.AddBool("tuned",true); - if(fixed) - familymsg.AddBool("fixed",true); - - fontmsg.AddMessage("family",&familymsg); - familymsg.MakeEmpty(); - } - - BFile file(SERVER_FONT_LIST,B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE); - if(file.InitCheck()==B_OK) - fontmsg.Flatten(&file); -*/ -} - - FontFamily* FontServer::GetFamilyByIndex(int32 index) const {