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 <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
#include "SharedObject.h"
|
#include "SharedObject.h"
|
||||||
|
#include "HashTable.h"
|
||||||
|
|
||||||
|
|
||||||
class FontFamily;
|
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
|
\class FontStyle FontFamily.h
|
||||||
\brief Object used to represent a font style
|
\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
|
FontStyle objects help abstract a lot of the font engine details while
|
||||||
still offering plenty of information the style in question.
|
still offering plenty of information the style in question.
|
||||||
*/
|
*/
|
||||||
class FontStyle : public SharedObject, public BLocker {
|
class FontStyle : public SharedObject, public Hashable, public BLocker {
|
||||||
public:
|
public:
|
||||||
FontStyle(const char* path, FT_Face face);
|
FontStyle(const char* path, FT_Face face);
|
||||||
virtual ~FontStyle();
|
virtual ~FontStyle();
|
||||||
|
|
||||||
|
virtual uint32 Hash() const;
|
||||||
|
virtual bool CompareTo(Hashable& other) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\fn bool FontStyle::IsFixedWidth(void)
|
\fn bool FontStyle::IsFixedWidth(void)
|
||||||
\brief Determines whether the font's character width is fixed
|
\brief Determines whether the font's character width is fixed
|
||||||
|
|||||||
@@ -10,9 +10,10 @@
|
|||||||
#define FONT_MANAGER_H
|
#define FONT_MANAGER_H
|
||||||
|
|
||||||
|
|
||||||
|
#include "HashTable.h"
|
||||||
|
|
||||||
#include <Looper.h>
|
#include <Looper.h>
|
||||||
#include <ObjectList.h>
|
#include <ObjectList.h>
|
||||||
#include <SupportDefs.h>
|
|
||||||
|
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
@@ -85,6 +86,7 @@ class FontManager : public BLooper {
|
|||||||
BObjectList<font_directory> fDirectories;
|
BObjectList<font_directory> fDirectories;
|
||||||
BObjectList<font_mapping> fMappings;
|
BObjectList<font_mapping> fMappings;
|
||||||
BObjectList<FontFamily> fFamilies;
|
BObjectList<FontFamily> fFamilies;
|
||||||
|
HashTable fStyleHashTable;
|
||||||
ServerFont *fDefaultFont;
|
ServerFont *fDefaultFont;
|
||||||
bool fScanned;
|
bool fScanned;
|
||||||
int32 fNextID;
|
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
|
void
|
||||||
FontStyle::GetHeight(float size, font_height& height) const
|
FontStyle::GetHeight(float size, font_height& height) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -124,6 +124,13 @@ FontManager::_RemoveFamily(const char *familyName)
|
|||||||
{
|
{
|
||||||
FontFamily *family = GetFamily(familyName);
|
FontFamily *family = GetFamily(familyName);
|
||||||
if (family) {
|
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);
|
fFamilies.RemoveItem(family);
|
||||||
delete family;
|
delete family;
|
||||||
}
|
}
|
||||||
@@ -239,6 +246,7 @@ FontManager::_AddFont(BPath &path)
|
|||||||
if (!family->AddStyle(style))
|
if (!family->AddStyle(style))
|
||||||
delete style;
|
delete style;
|
||||||
|
|
||||||
|
fStyleHashTable.AddItem(style);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,11 +531,10 @@ FontManager::GetFamily(const char* name)
|
|||||||
FontFamily*
|
FontFamily*
|
||||||
FontManager::GetFamily(uint16 familyID) const
|
FontManager::GetFamily(uint16 familyID) const
|
||||||
{
|
{
|
||||||
for (int32 i = 0; i < fFamilies.CountItems(); i++) {
|
FontKey key(familyID, 0);
|
||||||
FontFamily *family = (FontFamily*)fFamilies.ItemAt(i);
|
FontStyle* style = (FontStyle*)fStyleHashTable.GetValue(key);
|
||||||
if (family->ID() == familyID)
|
if (style != NULL)
|
||||||
return family;
|
return style->Family();
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -594,11 +601,8 @@ FontManager::GetStyle(const char* familyName, const char* styleName, uint16 fami
|
|||||||
FontStyle*
|
FontStyle*
|
||||||
FontManager::GetStyle(uint16 familyID, uint16 styleID) const
|
FontManager::GetStyle(uint16 familyID, uint16 styleID) const
|
||||||
{
|
{
|
||||||
FontFamily *family = GetFamily(familyID);
|
FontKey key(familyID, styleID);
|
||||||
if (family)
|
return (FontStyle*)fStyleHashTable.GetValue(key);
|
||||||
return family->GetStyleByID(styleID);
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2005, Haiku.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Axel Dörfler, [email protected]
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
CursorSet.cpp
|
||||||
DrawState.cpp
|
DrawState.cpp
|
||||||
FontFamily.cpp
|
FontFamily.cpp
|
||||||
|
HashTable.cpp
|
||||||
IPoint.cpp
|
IPoint.cpp
|
||||||
RGBColor.cpp
|
RGBColor.cpp
|
||||||
ServerBitmap.cpp
|
ServerBitmap.cpp
|
||||||
|
|||||||
Reference in New Issue
Block a user