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:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ SharedLibrary libappserver.so :
|
||||
CursorSet.cpp
|
||||
DrawState.cpp
|
||||
FontFamily.cpp
|
||||
HashTable.cpp
|
||||
IPoint.cpp
|
||||
RGBColor.cpp
|
||||
ServerBitmap.cpp
|
||||
|
||||
Reference in New Issue
Block a user