The font manager now utilizes a hash table to look up fonts by ID.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@14777 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2005-11-08 16:49:33 +00:00
parent 5f5dfa87e1
commit ec9b3f7ca1
7 changed files with 301 additions and 12 deletions
+22 -1
View File
@@ -19,6 +19,7 @@
#include <ft2build.h>
#include FT_FREETYPE_H
#include "SharedObject.h"
#include "HashTable.h"
class FontFamily;
@@ -39,6 +40,23 @@ enum font_format {
};
class FontKey : public Hashable {
public:
FontKey(uint16 familyID, uint16 styleID)
: fHash(familyID | (styleID << 16UL))
{
}
virtual uint32 Hash() const
{ return fHash; }
virtual bool CompareTo(Hashable& other) const
{ return fHash == other.Hash(); }
private:
uint32 fHash;
};
/*!
\class FontStyle FontFamily.h
\brief Object used to represent a font style
@@ -46,11 +64,14 @@ enum font_format {
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 BLocker {
class FontStyle : public SharedObject, public Hashable, public BLocker {
public:
FontStyle(const char* path, FT_Face face);
virtual ~FontStyle();
virtual uint32 Hash() const;
virtual bool CompareTo(Hashable& other) const;
/*!
\fn bool FontStyle::IsFixedWidth(void)
\brief Determines whether the font's character width is fixed
+3 -1
View File
@@ -10,9 +10,10 @@
#define FONT_MANAGER_H
#include "HashTable.h"
#include <Looper.h>
#include <ObjectList.h>
#include <SupportDefs.h>
#include <ft2build.h>
#include FT_FREETYPE_H
@@ -85,6 +86,7 @@ class FontManager : public BLooper {
BObjectList<font_directory> fDirectories;
BObjectList<font_mapping> fMappings;
BObjectList<FontFamily> fFamilies;
HashTable fStyleHashTable;
ServerFont *fDefaultFont;
bool fScanned;
int32 fNextID;
+47
View File
@@ -0,0 +1,47 @@
/*
* Copyright 2005, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, [email protected]
*/
#ifndef _HASH_TABLE_H_
#define _HASH_TABLE_H_
#include <SupportDefs.h>
class Hashable {
public:
virtual uint32 Hash() const = 0;
virtual bool CompareTo(Hashable& hashable) const = 0;
};
class HashTable {
public:
HashTable(int32 capacity = 100, float loadFactor = 0.75);
~HashTable();
void MakeEmpty();
bool IsEmpty() const { return fCount == 0; }
bool ContainsKey(Hashable& key) const { return _GetHashEntry(key) != NULL; }
int32 CountItems() const { return fCount; }
Hashable *GetValue(Hashable& key) const;
bool AddItem(Hashable* value);
Hashable *RemoveItem(Hashable& key);
protected:
struct entry;
bool _Rehash();
entry *_GetHashEntry(Hashable& key) const;
entry** fTable;
int32 fCapacity, fCount, fThreshold;
float fLoadFactor;
};
#endif /* HASHTABLE_H */
+15
View File
@@ -63,6 +63,21 @@ FontStyle::~FontStyle()
}
uint32
FontStyle::Hash() const
{
return (ID() << 16) | fFamily->ID();
}
bool
FontStyle::CompareTo(Hashable& other) const
{
// our hash values are unique (unless you have more than 65536 font families installed...)
return Hash() == other.Hash();
}
void
FontStyle::GetHeight(float size, font_height& height) const
{
+14 -10
View File
@@ -124,6 +124,13 @@ FontManager::_RemoveFamily(const char *familyName)
{
FontFamily *family = GetFamily(familyName);
if (family) {
// remove styles from hash
for (int32 i = 0; i < family->CountStyles(); i++) {
FontStyle* style = family->StyleAt(i);
fStyleHashTable.RemoveItem(*style);
}
fFamilies.RemoveItem(family);
delete family;
}
@@ -239,6 +246,7 @@ FontManager::_AddFont(BPath &path)
if (!family->AddStyle(style))
delete style;
fStyleHashTable.AddItem(style);
return B_OK;
}
@@ -523,11 +531,10 @@ FontManager::GetFamily(const char* name)
FontFamily*
FontManager::GetFamily(uint16 familyID) const
{
for (int32 i = 0; i < fFamilies.CountItems(); i++) {
FontFamily *family = (FontFamily*)fFamilies.ItemAt(i);
if (family->ID() == familyID)
return family;
}
FontKey key(familyID, 0);
FontStyle* style = (FontStyle*)fStyleHashTable.GetValue(key);
if (style != NULL)
return style->Family();
return NULL;
}
@@ -594,11 +601,8 @@ FontManager::GetStyle(const char* familyName, const char* styleName, uint16 fami
FontStyle*
FontManager::GetStyle(uint16 familyID, uint16 styleID) const
{
FontFamily *family = GetFamily(familyID);
if (family)
return family->GetStyleByID(styleID);
return NULL;
FontKey key(familyID, styleID);
return (FontStyle*)fStyleHashTable.GetValue(key);
}
+199
View File
@@ -0,0 +1,199 @@
/*
* Copyright 2005, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, axeld@pinc-software.de
*/
#include "HashTable.h"
#include <new>
#include <stdlib.h>
//#include <stdarg.h>
#include <string.h>
struct HashTable::entry {
entry* next;
Hashable* value;
};
HashTable::HashTable(int32 capacity, float loadFactor)
:
fTable(NULL),
fCount(0),
fThreshold(0)
{
if (capacity < 10)
capacity = 10;
if (loadFactor <= 0.3)
loadFactor = 0.3;
fLoadFactor = loadFactor;
fCapacity = capacity;
}
HashTable::~HashTable()
{
MakeEmpty();
}
void
HashTable::MakeEmpty()
{
for (int32 index = fCapacity; --index >= 0;) {
struct entry *entry, *next;
for (entry = fTable[index]; entry != NULL; entry = next) {
next = entry->next;
delete entry->value;
delete entry;
}
}
free(fTable);
fTable = NULL;
}
Hashable *
HashTable::GetValue(Hashable& key) const
{
struct entry* entry = _GetHashEntry(key);
return entry != NULL ? entry->value : NULL;
}
bool
HashTable::AddItem(Hashable *value)
{
struct entry *entry = _GetHashEntry(*value);
int32 hash = value->Hash();
int32 index;
// already in hash?
if (entry != NULL)
return true;
if (fCount >= fThreshold)
_Rehash();
index = hash % fCapacity;
entry = new (nothrow) HashTable::entry;
if (entry == NULL)
return false;
entry->value = value;
entry->next = fTable[index];
fTable[index] = entry;
fCount++;
return true;
}
Hashable *
HashTable::RemoveItem(Hashable& key)
{
struct entry* previous = NULL;
struct entry* entry;
uint32 hash;
int32 index;
if (fTable == NULL)
return NULL;
hash = key.Hash();
index = hash % fCapacity;
for (entry = fTable[index]; entry != NULL; entry = entry->next) {
if (entry->value->Hash() == hash && entry->value->CompareTo(key)) {
// found value in array
Hashable* value;
if (previous)
previous->next = entry->next;
else
fTable[index] = entry->next;
fCount--;
value = entry->value;
delete entry;
return value;
}
previous = entry;
}
return NULL;
}
bool
HashTable::_Rehash()
{
struct entry** newTable;
int32 oldCapacity = fCapacity;
int32 newCapacity, i;
if (fCount != 0)
newCapacity = oldCapacity * 2 + 1;
else
newCapacity = fCapacity;
newTable = (struct entry **)malloc(newCapacity * sizeof(struct entry *));
if (newTable == NULL)
return false;
memset(newTable, 0, newCapacity * sizeof(struct entry *));
if (fTable != NULL) {
// repopulate the entries into the new array
for (i = fCapacity; i-- > 0;) {
struct entry* entry;
struct entry* next;
for (entry = fTable[i]; entry != NULL; entry = next) {
next = entry->next;
int32 index = entry->value->Hash() % newCapacity;
entry->next = newTable[index];
newTable[index] = entry;
}
}
free(fTable);
}
fTable = newTable;
fCapacity = newCapacity;
fThreshold = int32(newCapacity * fLoadFactor);
return true;
}
struct HashTable::entry *
HashTable::_GetHashEntry(Hashable& key) const
{
struct entry* entry;
uint32 hash = key.Hash();
if (fTable == NULL)
return NULL;
for (entry = fTable[hash % fCapacity]; entry != NULL; entry = entry->next) {
if (entry->value->Hash() == hash && entry->value->CompareTo(key))
return entry;
}
return NULL;
}
+1
View File
@@ -29,6 +29,7 @@ SharedLibrary libappserver.so :
CursorSet.cpp
DrawState.cpp
FontFamily.cpp
HashTable.cpp
IPoint.cpp
RGBColor.cpp
ServerBitmap.cpp