* 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_GET_SYSTEM_FONTS,
AS_QUERY_FONTS_CHANGED,
AS_UPDATED_CLIENT_FONTLIST,
AS_GET_FAMILY_NAME,
AS_GET_STYLE_NAME,
AS_COUNT_FONT_FAMILIES,
AS_COUNT_FONT_STYLES,
AS_GET_FONT_LIST_REVISION,
AS_GET_FAMILY_AND_STYLES,
AS_GET_FAMILY_AND_STYLE,
AS_GET_FAMILY_AND_STYLE_IDS,
+269 -85
View File
@@ -9,11 +9,14 @@
*/
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <AppServerLink.h>
#include <Autolock.h>
#include <Font.h>
#include <Locker.h>
#include <Message.h>
#include <PortLink.h>
#include <Rect.h>
@@ -21,9 +24,11 @@
#include <Shape.h>
#include <String.h>
#include <AppServerLink.h>
#include <moreUTF8.h>
#include <truncate_string.h>
#include <FontPrivate.h>
#include <ObjectList.h>
const float kUninitializedAscent = INFINITY;
@@ -39,6 +44,261 @@ const BFont *be_bold_font = &sBoldFont;
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
_init_global_fonts_()
{
@@ -121,19 +381,9 @@ _set_system_font_(const char *which, font_family family, font_style style,
*/
int32
count_font_families(void)
count_font_families()
{
int32 code, count;
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;
return sFontList.CountFamilies();
}
@@ -145,18 +395,7 @@ count_font_families(void)
int32
count_font_styles(font_family family)
{
BPrivate::AppServerLink link;
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;
return sFontList.CountStyles(family);
}
@@ -174,23 +413,7 @@ get_font_family(int32 index, font_family *_name, uint32 *_flags)
if (_name == NULL)
return B_BAD_VALUE;
BPrivate::AppServerLink link;
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;
return sFontList.FamilyAt(index, _name, _flags);
}
@@ -229,59 +452,20 @@ get_font_style(font_family family, int32 index, font_style *_name,
if (_name == NULL)
return B_BAD_VALUE;
// TODO: maybe cache the whole font list locally?
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;
return sFontList.StyleAt(family, index, _name, _face, _flags);
}
/*!
\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.
*/
bool
update_font_families(bool checkOnly)
update_font_families(bool /*checkOnly*/)
{
int32 code;
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;
return sFontList.UpdatedOnServer();
}
-24
View File
@@ -341,30 +341,6 @@ AppServer::_DispatchMessage(int32 code, BPrivate::LinkReceiver& msg)
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
case B_QUIT_REQUESTED:
{
+12 -4
View File
@@ -14,10 +14,12 @@
#include "ServerFont.h"
#include "FontManager.h"
#include <FontPrivate.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
{
int32 flags = 0;
uint32 flags = uint32(Direction()) << B_PRIVATE_FONT_DIRECTION_SHIFT;
if (IsFixedWidth())
flags |= B_IS_FIXED;
if (TunedCount() > 0)
flags |= B_HAS_TUNED_FONT;
if (HasKerning())
flags |= B_PRIVATE_FONT_HAS_KERNING;
return flags;
}
@@ -392,7 +400,7 @@ FontFamily::GetStyleMatchingFace(uint16 face) const
}
int32
uint32
FontFamily::Flags()
{
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
\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 */
case AS_UPDATED_CLIENT_FONTLIST:
case AS_GET_FONT_LIST_REVISION:
{
STRACE(("ServerApp %s: Acknowledged update of client-side font list\n",
Signature()));
STRACE(("ServerApp %s: AS_GET_FONT_LIST_REVISION\n", Signature()));
// received when the client-side global font list has been
// refreshed
gFontManager->Lock();
//gFontManager->FontsUpdated();
gFontManager->Unlock();
fLink.StartMessage(B_OK);
fLink.Attach<int32>(gFontManager->CheckRevision(fDesktop->UserID()));
fLink.Flush();
break;
}
case AS_QUERY_FONTS_CHANGED:
case AS_GET_FAMILY_AND_STYLES:
{
FTRACE(("ServerApp %s: AS_QUERY_FONTS_CHANGED\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()));
FTRACE(("ServerApp %s: AS_GET_FAMILY_AND_STYLES\n", Signature()));
// Attached Data:
// 1) int32 the index of the font family to get
// 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)
// 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;
link.Read<int32>(&index);
gFontManager->Lock();
FontFamily *family = gFontManager->FamilyAt(index);
FontFamily* family = gFontManager->FamilyAt(index);
if (family) {
fLink.StartMessage(B_OK);
fLink.AttachString(family->Name());
fLink.Attach<uint32>(family->Flags());
} else
fLink.StartMessage(B_BAD_VALUE);
int32 count = family->CountStyles();
fLink.Attach<int32>(count);
gFontManager->Unlock();
fLink.Flush();
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
for (int32 i = 0; i < count; i++) {
FontStyle* style = family->StyleAt(i);
// Returns:
// 1) font_style - name of the style
// 2) uint16 - appropriate face values
// 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());
fLink.AttachString(style->Name());
fLink.Attach<uint16>(style->Face());
fLink.Attach<uint32>(style->Flags());
}
} else
fLink.StartMessage(B_BAD_VALUE);
@@ -1401,18 +1362,7 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
FontStyle *fontStyle = gFontManager->GetStyle(familyID, styleID);
if (fontStyle != NULL) {
fLink.StartMessage(B_OK);
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);
fLink.Attach<uint32>(fontStyle->Flags());
} else
fLink.StartMessage(B_BAD_VALUE);
@@ -1469,45 +1419,6 @@ ServerApp::_DispatchMessage(int32 code, BPrivate::LinkReceiver &link)
fLink.Flush();
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:
{
FTRACE(("ServerApp %s: AS_GET_SYSTEM_FONTS\n", Signature()));
+2 -7
View File
@@ -239,15 +239,10 @@ AppServer::MainLoop(void)
switch (code) {
case B_QUIT_REQUESTED:
case AS_GET_DESKTOP:
case AS_CREATE_APP:
case AS_DELETE_APP:
case AS_UPDATED_CLIENT_FONTLIST:
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:
case AS_SET_SYSCURSOR_DEFAULTS:
DispatchMessage(code, pmsg);
break;
default: