* The font list is now cached client-side. The app_server is only queried for

updates.
* Optimized retrieving the font list from the server.
* This greatly simplifies the app_server communication for getting the font
  list as well - there are now only 2 commands instead of 6.
* Moved extra font flags creation from ServerApp to FontStyle::Flags().


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14751 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-11-07 16:19:40 +00:00
parent 41572514dd
commit e37155c670
7 changed files with 329 additions and 240 deletions
+2 -6
View File
@@ -115,12 +115,8 @@ enum {
AS_SET_SYSTEM_FONT, AS_SET_SYSTEM_FONT,
AS_GET_SYSTEM_FONTS, AS_GET_SYSTEM_FONTS,
AS_QUERY_FONTS_CHANGED, AS_GET_FONT_LIST_REVISION,
AS_UPDATED_CLIENT_FONTLIST, AS_GET_FAMILY_AND_STYLES,
AS_GET_FAMILY_NAME,
AS_GET_STYLE_NAME,
AS_COUNT_FONT_FAMILIES,
AS_COUNT_FONT_STYLES,
AS_GET_FAMILY_AND_STYLE, AS_GET_FAMILY_AND_STYLE,
AS_GET_FAMILY_AND_STYLE_IDS, AS_GET_FAMILY_AND_STYLE_IDS,
+269 -85
View File
@@ -9,11 +9,14 @@
*/ */
#include <new>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <AppServerLink.h> #include <Autolock.h>
#include <Font.h> #include <Font.h>
#include <Locker.h>
#include <Message.h> #include <Message.h>
#include <PortLink.h> #include <PortLink.h>
#include <Rect.h> #include <Rect.h>
@@ -21,9 +24,11 @@
#include <Shape.h> #include <Shape.h>
#include <String.h> #include <String.h>
#include <AppServerLink.h>
#include <moreUTF8.h> #include <moreUTF8.h>
#include <truncate_string.h> #include <truncate_string.h>
#include <FontPrivate.h> #include <FontPrivate.h>
#include <ObjectList.h>
const float kUninitializedAscent = INFINITY; const float kUninitializedAscent = INFINITY;
@@ -39,6 +44,261 @@ const BFont *be_bold_font = &sBoldFont;
const BFont *be_fixed_font = &sFixedFont; const BFont *be_fixed_font = &sFixedFont;
struct style {
BString name;
uint16 face;
uint32 flags;
};
struct family {
BString name;
uint32 flags;
BObjectList<style> styles;
};
namespace BPrivate {
class FontList : public BLocker {
public:
FontList();
~FontList();
bool UpdatedOnServer();
status_t FamilyAt(int32 index, font_family *_family, uint32 *_flags);
status_t StyleAt(font_family family, int32 index, font_style *_style,
uint16 *_face, uint32 *_flags);
int32 CountFamilies();
int32 CountStyles(font_family family);
private:
status_t _UpdateIfNecessary();
status_t _Update();
int32 _RevisionOnServer();
family* _FindFamily(font_family name);
BObjectList<family> fFamilies;
family* fLastFamily;
bigtime_t fLastUpdate;
int32 fRevision;
};
} // namespace BPrivate
static BPrivate::FontList sFontList;
namespace BPrivate {
FontList::FontList()
: BLocker("font list"),
fLastFamily(NULL),
fLastUpdate(0),
fRevision(0)
{
}
FontList::~FontList()
{
}
bool
FontList::UpdatedOnServer()
{
return _RevisionOnServer() != fRevision;
}
int32
FontList::_RevisionOnServer()
{
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_FONT_LIST_REVISION);
int32 code;
if (link.FlushWithReply(code) != B_OK || code != B_OK)
return B_ERROR;
int32 revision;
link.Read<int32>(&revision);
return revision;
}
status_t
FontList::_Update()
{
// check version
int32 revision = _RevisionOnServer();
fLastUpdate = system_time();
// are we up-to-date already?
if (revision == fRevision)
return B_OK;
fFamilies.MakeEmpty();
fLastFamily = NULL;
BPrivate::AppServerLink link;
for (int32 index = 0;; index++) {
link.StartMessage(AS_GET_FAMILY_AND_STYLES);
link.Attach<int32>(index);
int32 status;
if (link.FlushWithReply(status) != B_OK
|| status != B_OK)
break;
::family* family = new (nothrow) ::family;
if (family == NULL)
return B_NO_MEMORY;
link.ReadString(family->name);
link.Read<uint32>(&family->flags);
int32 styleCount;
link.Read<int32>(&styleCount);
for (int32 i = 0; i < styleCount; i++) {
::style* style = new (nothrow) ::style;
if (style == NULL) {
delete family;
return B_NO_MEMORY;
}
link.ReadString(style->name);
link.Read<uint16>(&style->face);
link.Read<uint32>(&style->flags);
family->styles.AddItem(style);
}
fFamilies.AddItem(family);
}
fRevision = revision;
// if the font list has been changed in the mean time, just update again
if (UpdatedOnServer())
_Update();
return B_OK;
}
status_t
FontList::_UpdateIfNecessary()
{
// an updated font list is at least valid for 1 second
if (fLastUpdate > system_time() - 1000000)
return B_OK;
return _Update();
}
family*
FontList::_FindFamily(font_family name)
{
if (fLastFamily != NULL && fLastFamily->name == name)
return fLastFamily;
for (int32 i = 0; i < fFamilies.CountItems(); i++) {
family* family = fFamilies.ItemAt(i);
if (family->name == name) {
fLastFamily = family;
return family;
}
}
return NULL;
}
status_t
FontList::FamilyAt(int32 index, font_family *_family, uint32 *_flags)
{
BAutolock locker(this);
status_t status = _UpdateIfNecessary();
if (status < B_OK)
return status;
::family* family = fFamilies.ItemAt(index);
if (family == NULL)
return B_BAD_VALUE;
memcpy(*_family, family->name.String(), family->name.Length() + 1);
if (_flags)
*_flags = family->flags;
return B_OK;
}
status_t
FontList::StyleAt(font_family familyName, int32 index, font_style *_style,
uint16 *_face, uint32 *_flags)
{
BAutolock locker(this);
status_t status = _UpdateIfNecessary();
if (status < B_OK)
return status;
::family* family = _FindFamily(familyName);
if (family == NULL)
return B_BAD_VALUE;
::style* style = family->styles.ItemAt(index);
if (style == NULL)
return B_BAD_VALUE;
memcpy(*_style, style->name.String(), style->name.Length() + 1);
if (_face)
*_face = style->face;
if (_flags)
*_flags = style->flags;
return B_OK;
}
int32
FontList::CountFamilies()
{
BAutolock locker(this);
_UpdateIfNecessary();
return fFamilies.CountItems();
}
int32
FontList::CountStyles(font_family familyName)
{
BAutolock locker(this);
_UpdateIfNecessary();
::family* family = _FindFamily(familyName);
if (family == NULL)
return 0;
return family->styles.CountItems();
}
} // namespace BPrivate
// #pragma mark -
void void
_init_global_fonts_() _init_global_fonts_()
{ {
@@ -121,19 +381,9 @@ _set_system_font_(const char *which, font_family family, font_style style,
*/ */
int32 int32
count_font_families(void) count_font_families()
{ {
int32 code, count; return sFontList.CountFamilies();
BPrivate::AppServerLink link;
link.StartMessage(AS_COUNT_FONT_FAMILIES);
if (link.FlushWithReply(code) != B_OK
|| code != B_OK)
return -1;
link.Read<int32>(&count);
return count;
} }
@@ -145,18 +395,7 @@ count_font_families(void)
int32 int32
count_font_styles(font_family family) count_font_styles(font_family family)
{ {
BPrivate::AppServerLink link; return sFontList.CountStyles(family);
link.StartMessage(AS_COUNT_FONT_STYLES);
link.AttachString(family);
int32 code;
if (link.FlushWithReply(code) != B_OK
|| code != B_OK)
return -1;
int32 count;
link.Read<int32>(&count);
return count;
} }
@@ -174,23 +413,7 @@ get_font_family(int32 index, font_family *_name, uint32 *_flags)
if (_name == NULL) if (_name == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
BPrivate::AppServerLink link; return sFontList.FamilyAt(index, _name, _flags);
link.StartMessage(AS_GET_FAMILY_NAME);
link.Attach<int32>(index);
int32 status = B_ERROR;
if (link.FlushWithReply(status) != B_OK
|| status != B_OK)
return status;
link.ReadString(*_name, sizeof(font_family));
uint32 flags;
link.Read<uint32>(&flags);
if (_flags)
*_flags = flags;
return B_OK;
} }
@@ -229,59 +452,20 @@ get_font_style(font_family family, int32 index, font_style *_name,
if (_name == NULL) if (_name == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
// TODO: maybe cache the whole font list locally? return sFontList.StyleAt(family, index, _name, _face, _flags);
BPrivate::AppServerLink link;
link.StartMessage(AS_GET_STYLE_NAME);
link.AttachString(family);
link.Attach<int32>(index);
int32 status = B_ERROR;
if (link.FlushWithReply(status) != B_OK
|| status != B_OK)
return status;
link.ReadString(*_name, sizeof(font_style));
uint16 face;
uint32 flags;
link.Read<uint16>(&face);
link.Read<uint32>(&flags);
if (_face)
*_face = face;
if (_flags)
*_flags = flags;
return B_OK;
} }
/*! /*!
\brief Updates the font family list \brief Updates the font family list
\param check_only If true, the function only checks to see if the font list has changed \param checkOnly is ignored
\return true if the font list has changed, false if not. \return true if the font list has changed, false if not.
*/ */
bool bool
update_font_families(bool checkOnly) update_font_families(bool /*checkOnly*/)
{ {
int32 code; return sFontList.UpdatedOnServer();
bool value;
BPrivate::AppServerLink link;
// TODO: get some kind of change counter or timestamp and use node-monitoring
// for fonts in the app_server
link.StartMessage(AS_QUERY_FONTS_CHANGED);
link.Attach<bool>(checkOnly);
if (link.FlushWithReply(code) != B_OK
|| code != B_OK)
return false;
link.Read<bool>(&value);
return value;
} }
-24
View File
@@ -341,30 +341,6 @@ AppServer::_DispatchMessage(int32 code, BPrivate::LinkReceiver& msg)
break; break;
} }
case AS_QUERY_FONTS_CHANGED:
{
// Client application is asking if the font list has changed since
// the last client-side refresh
// Attached data:
// 1) port_id reply port
gFontManager->Lock();
bool needsUpdate = false; //gFontManager->FontsNeedUpdated();
gFontManager->Unlock();
// Seeing how the client merely wants an answer, we'll skip the BPortLink
// and all its overhead and just write the code to port.
port_id replyPort;
if (msg.Read<port_id>(&replyPort) < B_OK)
break;
BPrivate::PortLink reply(replyPort);
reply.StartMessage(needsUpdate ? SERVER_TRUE : SERVER_FALSE);
reply.Flush();
break;
}
#if TEST_MODE #if TEST_MODE
case B_QUIT_REQUESTED: case B_QUIT_REQUESTED:
{ {
+12 -4
View File
@@ -14,10 +14,12 @@
#include "ServerFont.h" #include "ServerFont.h"
#include "FontManager.h" #include "FontManager.h"
#include <FontPrivate.h>
#include FT_CACHE_H #include FT_CACHE_H
const int32 kInvalidFamilyFlags = -1; const uint32 kInvalidFamilyFlags = ~0UL;
/*! /*!
@@ -81,15 +83,21 @@ FontStyle::Path() const
} }
int32 /*!
\brief Unlike BFont::Flags() this returns the extra flags field as used
in the private part of BFont.
*/
uint32
FontStyle::Flags() const FontStyle::Flags() const
{ {
int32 flags = 0; uint32 flags = uint32(Direction()) << B_PRIVATE_FONT_DIRECTION_SHIFT;
if (IsFixedWidth()) if (IsFixedWidth())
flags |= B_IS_FIXED; flags |= B_IS_FIXED;
if (TunedCount() > 0) if (TunedCount() > 0)
flags |= B_HAS_TUNED_FONT; flags |= B_HAS_TUNED_FONT;
if (HasKerning())
flags |= B_PRIVATE_FONT_HAS_KERNING;
return flags; return flags;
} }
@@ -392,7 +400,7 @@ FontFamily::GetStyleMatchingFace(uint16 face) const
} }
int32 uint32
FontFamily::Flags() FontFamily::Flags()
{ {
if (fFlags == kInvalidFamilyFlags) { if (fFlags == kInvalidFamilyFlags) {
+19
View File
@@ -407,6 +407,25 @@ FontManager::_GetSupportedCharmap(const FT_Face& face)
} }
int32
FontManager::CheckRevision(uid_t user)
{
BAutolock locker(this);
int32 revision = 0;
_ScanFontsIfNecessary();
for (int32 i = 0; i < fDirectories.CountItems(); i++) {
font_directory* directory = fDirectories.ItemAt(i);
// TODO: for now, add all directories
revision += directory->revision;
}
return revision;
}
/*! /*!
\brief Counts the number of font families available \brief Counts the number of font families available
\return The number of unique font families currently available \return The number of unique font families currently available
+25 -114
View File
@@ -1108,90 +1108,51 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
/* font messages */ /* font messages */
case AS_UPDATED_CLIENT_FONTLIST: case AS_GET_FONT_LIST_REVISION:
{ {
STRACE(("ServerApp %s: Acknowledged update of client-side font list\n", STRACE(("ServerApp %s: AS_GET_FONT_LIST_REVISION\n", Signature()));
Signature()));
// received when the client-side global font list has been fLink.StartMessage(B_OK);
// refreshed fLink.Attach<int32>(gFontManager->CheckRevision(fDesktop->UserID()));
gFontManager->Lock(); fLink.Flush();
//gFontManager->FontsUpdated();
gFontManager->Unlock();
break; break;
} }
case AS_QUERY_FONTS_CHANGED: case AS_GET_FAMILY_AND_STYLES:
{ {
FTRACE(("ServerApp %s: AS_QUERY_FONTS_CHANGED\n",Signature())); FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLES\n", Signature()));
// Attached Data:
// 1) bool check flag
bool checkonly;
link.Read<bool>(&checkonly);
gFontManager->Lock();
bool needsUpdate = false; //gFontManager->FontsNeedUpdated();
gFontManager->Unlock();
if (checkonly) {
fLink.StartMessage(needsUpdate ? SERVER_TRUE : SERVER_FALSE);
fLink.Flush();
} else {
fLink.StartMessage(SERVER_FALSE);
fLink.Flush();
}
break;
}
case AS_GET_FAMILY_NAME:
{
FTRACE(("ServerApp %s: AS_GET_FAMILY_NAME\n", Signature()));
// Attached Data: // Attached Data:
// 1) int32 the index of the font family to get // 1) int32 the index of the font family to get
// Returns: // Returns:
// 1) font_family - name of family // 1) string - name of family
// 2) uint32 - flags of font family (B_IS_FIXED || B_HAS_TUNED_FONT) // 2) uint32 - flags of font family (B_IS_FIXED || B_HAS_TUNED_FONT)
// 3) count of styles in that family
// For each style:
// 1) string - name of style
// 2) uint16 - face of style
// 3) uint32 - flags of style
int32 index; int32 index;
link.Read<int32>(&index); link.Read<int32>(&index);
gFontManager->Lock(); gFontManager->Lock();
FontFamily *family = gFontManager->FamilyAt(index); FontFamily* family = gFontManager->FamilyAt(index);
if (family) { if (family) {
fLink.StartMessage(B_OK); fLink.StartMessage(B_OK);
fLink.AttachString(family->Name()); fLink.AttachString(family->Name());
fLink.Attach<uint32>(family->Flags()); fLink.Attach<uint32>(family->Flags());
} else
fLink.StartMessage(B_BAD_VALUE); int32 count = family->CountStyles();
fLink.Attach<int32>(count);
gFontManager->Unlock(); for (int32 i = 0; i < count; i++) {
fLink.Flush(); FontStyle* style = family->StyleAt(i);
break;
}
case AS_GET_STYLE_NAME:
{
FTRACE(("ServerApp %s: AS_GET_STYLE_NAME\n", Signature()));
// Attached Data:
// 1) font_family The name of the font family
// 2) int32 index of the style to get
// Returns: fLink.AttachString(style->Name());
// 1) font_style - name of the style fLink.Attach<uint16>(style->Face());
// 2) uint16 - appropriate face values fLink.Attach<uint32>(style->Flags());
// 3) uint32 - flags of font style (B_IS_FIXED || B_HAS_TUNED_FONT) }
font_family family;
int32 styleIndex;
link.ReadString(family, sizeof(font_family));
link.Read<int32>(&styleIndex);
gFontManager->Lock();
FontStyle *fontStyle = gFontManager->GetStyleByIndex(family, styleIndex);
if (fontStyle != NULL) {
fLink.StartMessage(B_OK);
fLink.AttachString(fontStyle->Name());
fLink.Attach<uint16>(fontStyle->Face());
fLink.Attach<uint32>(fontStyle->Flags());
} else } else
fLink.StartMessage(B_BAD_VALUE); fLink.StartMessage(B_BAD_VALUE);
@@ -1401,18 +1362,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID); FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID);
if (fontStyle != NULL) { if (fontStyle != NULL) {
fLink.StartMessage(B_OK); fLink.StartMessage(B_OK);
fLink.Attach<uint32>(fontStyle->Flags());
uint32 flags = 0;
if (fontStyle->IsFixedWidth())
flags |= B_IS_FIXED;
if (fontStyle->HasTuned())
flags |= B_HAS_TUNED_FONT;
if (fontStyle->HasKerning())
flags |= B_PRIVATE_FONT_HAS_KERNING;
flags |= uint32(fontStyle->Direction()) << B_PRIVATE_FONT_DIRECTION_SHIFT;
fLink.Attach<uint32>(flags);
} else } else
fLink.StartMessage(B_BAD_VALUE); fLink.StartMessage(B_BAD_VALUE);
@@ -1469,45 +1419,6 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
fLink.Flush(); fLink.Flush();
break; break;
} }
case AS_COUNT_FONT_FAMILIES:
{
FTRACE(("ServerApp %s: AS_COUNT_FONT_FAMILIES\n", Signature()));
// Returns:
// 1) int32 - # of font families
gFontManager->Lock();
fLink.StartMessage(B_OK);
fLink.Attach<int32>(gFontManager->CountFamilies());
fLink.Flush();
gFontManager->Unlock();
break;
}
case AS_COUNT_FONT_STYLES:
{
FTRACE(("ServerApp %s: AS_COUNT_FONT_STYLES\n", Signature()));
// Attached Data:
// 1) font_family - name of font family
// Returns:
// 1) int32 - # of font styles
font_family familyName;
link.ReadString(familyName, sizeof(font_family));
gFontManager->Lock();
FontFamily *family = gFontManager->GetFamily(familyName);
if (family != NULL) {
fLink.StartMessage(B_OK);
fLink.Attach<int32>(family->CountStyles());
} else
fLink.StartMessage(B_BAD_VALUE);
gFontManager->Unlock();
fLink.Flush();
break;
}
case AS_GET_SYSTEM_FONTS: case AS_GET_SYSTEM_FONTS:
{ {
FTRACE(("ServerApp %s: AS_GET_SYSTEM_FONTS\n", Signature())); FTRACE(("ServerApp %s: AS_GET_SYSTEM_FONTS\n", Signature()));
+2 -7
View File
@@ -239,15 +239,10 @@ AppServer::MainLoop(void)
switch (code) { switch (code) {
case B_QUIT_REQUESTED: case B_QUIT_REQUESTED:
case AS_GET_DESKTOP:
case AS_CREATE_APP: case AS_CREATE_APP:
case AS_DELETE_APP: case AS_DELETE_APP:
case AS_UPDATED_CLIENT_FONTLIST: case AS_SET_SYSCURSOR_DEFAULTS:
case AS_QUERY_FONTS_CHANGED:
case AS_SET_UI_COLORS:
case AS_GET_UI_COLOR:
case AS_SET_DECORATOR:
case AS_GET_DECORATOR:
case AS_R5_SET_DECORATOR:
DispatchMessage(code, pmsg); DispatchMessage(code, pmsg);
break; break;
default: default: