[mapguide-commits] r5176 - trunk/MgDev/Common/Renderers
svn_mapguide at osgeo.org
svn_mapguide at osgeo.org
Tue Sep 21 14:43:36 EDT 2010
Author: traianstanev
Date: 2010-09-21 18:43:36 +0000 (Tue, 21 Sep 2010)
New Revision: 5176
Modified:
trunk/MgDev/Common/Renderers/FontManager.cpp
trunk/MgDev/Common/Renderers/FontManager.h
Log:
Walt pointed out that my FontManager cleanup submission clobbered some more recent fixes to the FontManager. I am reverting my submission until I can merge it properly with the latest fixes.
Modified: trunk/MgDev/Common/Renderers/FontManager.cpp
===================================================================
--- trunk/MgDev/Common/Renderers/FontManager.cpp 2010-09-21 18:41:02 UTC (rev 5175)
+++ trunk/MgDev/Common/Renderers/FontManager.cpp 2010-09-21 18:43:36 UTC (rev 5176)
@@ -34,14 +34,7 @@
#include <wctype.h>
#endif
-// FreeType includes
-#include "ft2build.h"
-#include FT_FREETYPE_H
-#include FT_GLYPH_H
-#include FT_CACHE_H
-#include FT_CACHE_MANAGER_H
-
// local functions
wstring ToLower(const wstring& source)
{
@@ -54,12 +47,8 @@
// static initializations
CustomThreadMutex FontManager::sm_mutex;
FontManager FontManager::sm_manager;
-bool FontManager::sm_init = false;
-//Option whether to preload or delay load all fonts
-static bool DELAY_LOAD_FONTS = false;
-
//-------------------------------------------------------------------------
// Constructor/Desctructor
//-------------------------------------------------------------------------
@@ -67,7 +56,11 @@
FontManager::FontManager()
{
-
+ AutoMutexLocker autoLocker(sm_mutex);
+
+ FT_Init_FreeType(&m_library); // TODO: check error code
+
+ sm_manager.init_font_list();
}
@@ -75,36 +68,52 @@
{
AutoMutexLocker autoLocker(sm_mutex);
- if (sm_init)
+ FaceMapIterator it;
+ FaceMapEntryType* pEntry = NULL;
+ char* pData = NULL;
+
+ it = m_facemap.begin();
+
+ // clean up entries
+ while (it != m_facemap.end())
{
- // free up font map entries
- for (FontMapIterator fmi = m_fontAliases.begin(); fmi != m_fontAliases.end(); fmi++)
- {
- delete (*fmi).first;
- delete (*fmi).second;
- }
+ pEntry = (FaceMapEntryType*)(*it).second;
+ pData = pEntry->pData;
+ free(pData);
+ delete pEntry;
+ ++it;
+ }
- m_fontAliases.clear();
+ // free up font map entries
+ for (FontMapIterator fmi = m_fontAliases.begin(); fmi != m_fontAliases.end(); fmi++)
+ {
+ delete (*fmi).first;
+ delete (*fmi).second;
+ }
- // clean up fontlist
- FontListIterator it_font;
- RS_Font* font = NULL;
+ m_fontAliases.clear();
- it_font = m_fontlist.begin();
+ // clear map
+ m_facemap.clear();
- while (it_font != m_fontlist.end())
- {
- font = (RS_Font*)(*it_font);
- delete font;
- ++it_font;
- }
+ // clean up fontlist
+ FontListIterator it_font;
+ RS_Font* font = NULL;
- // clean fontlist
- m_fontlist.clear();
+ it_font = m_fontlist.begin();
- // clean up the library
- FT_Done_FreeType((FT_Library)m_library);
+ while (it_font != m_fontlist.end())
+ {
+ font = (RS_Font*)(*it_font);
+ delete font;
+ ++it_font;
}
+
+ // clean fontlist
+ m_fontlist.clear();
+
+ // clean up the library
+ FT_Done_FreeType(m_library);
}
@@ -115,69 +124,108 @@
FontManager* FontManager::Instance()
{
+ return &sm_manager;
+}
+
+
+int FontManager::get_face(const char* filename, FT_Long index, FT_Face* face)
+{
AutoMutexLocker autoLocker(sm_mutex);
- if (!sm_init)
+ int ret = 0; // our return error code
+ FaceMapIterator it; // an interator
+ FaceMapEntryType* pEntry = NULL; // pointer to loaded font data
+
+ // look for face in map
+ it = m_facemap.find(filename);
+
+ if (it != m_facemap.end())
{
- FT_Init_FreeType((FT_Library*)(&sm_manager.m_library)); // TODO: check error code
+ // found an entry
+ pEntry = (FaceMapEntryType*)(*it).second;
- if (!DELAY_LOAD_FONTS)
+ // create a new face
+ ret = FT_New_Memory_Face(m_library, (FT_Byte*)pEntry->pData, (FT_Long)pEntry->length, index, face);
+ }
+ else
+ {
+ // ok, we have to load it
+// ret = FT_New_Face(m_library, filename, index, face);
+
+ pEntry = load_file(filename);
+
+ if (pEntry)
{
- sm_manager.init_font_list();
+ // insert the entry into the map
+ m_facemap.insert(FaceMapPair(filename, pEntry));
+
+ // create a new face
+ ret = FT_New_Memory_Face(m_library, (FT_Byte*)pEntry->pData, (FT_Long)pEntry->length, index, face);
}
-
- sm_init = true;
+ else
+ {
+ face = NULL;
+ ret = -1;
+ }
}
- return &sm_manager;
+ return ret;
}
-//Caches the fonts/faces within a single given font file
-bool FontManager::CacheFont(wchar_t const* filename)
+
+FaceMapEntryType* FontManager::load_file(const char* filename)
{
AutoMutexLocker autoLocker(sm_mutex);
- // ok, load up the face information
- int error = 0;
- FT_Face face = NULL;
- FT_Long index = 0;
- FT_Long num_faces = 0;
+ int errcode = 0; // an error code
+ FaceMapEntryType* pEntry = NULL; // pointer to return value
+ char* pData = NULL; // pointer to loaded font file
+ size_t length = 0; // length of buffer
+ size_t count = 0; // length of file (obviously should be equal to above)
- do
+ FILE* pFile = fopen(filename, "rb");
+
+ if (pFile)
{
- string en;
- UnicodeString::WideCharToMultiByte(filename, en);
- error = FT_New_Face((FT_Library)m_library, en.c_str(), index, &face);
-
- if (!error)
+ errcode = fseek(pFile, 0L, SEEK_END);
+ if (!errcode)
{
- // init num_faces if necessary
- if (!num_faces)
- num_faces = face->num_faces;
- }
+ length = (unsigned long)ftell(pFile);
- create_font(face, index, filename);
+ errcode = fseek(pFile, 0L, SEEK_SET);
+ if (!errcode)
+ {
+ pData = (char*)malloc(sizeof(char) * length);
+ if (pData)
+ {
+ count = fread(pData, sizeof(char), length, pFile);
- // dispose of face
- FT_Done_Face(face);
+ if (ferror(pFile) == 0 && count == length)
+ errcode = fclose(pFile);
+ }
+ }
+ }
+ }
- // increment our face index
- index++;
+ if (pData)
+ {
+ pEntry = new FaceMapEntryType();
+ pEntry->pData = pData;
+ pEntry->length = length;
}
- while (!error && index < num_faces);
- return !error;
+ return pEntry;
}
-
#ifdef _WIN32
-// initialize the font list -- if a non-null argument is passed, only fonts
-// having the given string in their name will be cached
-void FontManager::init_font_list(const wchar_t* specificName)
+// initialize the font list
+void FontManager::init_font_list()
{
AutoMutexLocker autoLocker(sm_mutex);
+ int error = 0;
+
// look for the windows font directory
wchar_t fontpath[MAX_PATH];
HRESULT hres = SHGetFolderPath(NULL, CSIDL_FONTS, NULL, 0, fontpath);
@@ -186,10 +234,6 @@
if (S_OK == hres)
fontdir = fontpath;
- wstring searchString;
- if (specificName)
- searchString = ToLower(specificName);
-
// enum fonts
if (!fontdir.empty())
{
@@ -205,41 +249,73 @@
// do we have a file?
if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
- wstring entryName(fontdir);
- entryName += L"\\";
- entryName += FindFileData.cFileName;
-
- //are we searching for a specific font
- if (!searchString.empty())
+ // skip special Windows files
+ if (wcscmp(FindFileData.cFileName, L"desktop.ini") != 0)
{
- wstring lowerFileName = ToLower(FindFileData.cFileName);
+ wstring entryName(fontdir);
+ entryName += L"\\";
+ entryName += FindFileData.cFileName;
- if (!wcsstr(lowerFileName.c_str(), searchString.c_str()))
- goto keepgoing;
+ // ok, load up the face information
+ FT_Face face = NULL;
+ FT_Long index = 0;
+ FT_Long num_faces = 0;
+
+ do
+ {
+ string en;
+ UnicodeString::WideCharToMultiByte(entryName.c_str(), en);
+ error = FT_New_Face(m_library, en.c_str(), index, &face);
+
+ if (!error)
+ {
+ // init num_faces if necessary
+ if (!num_faces)
+ num_faces = face->num_faces;
+ }
+
+ create_font(face, index, entryName.c_str());
+
+ // dispose of face
+ FT_Done_Face(face);
+
+ // increment our face index
+ index++;
+ }
+ while (!error && index < num_faces);
}
+ }
- CacheFont(entryName.c_str());
- }
-keepgoing:
bOK = FindNextFile(hFile, &FindFileData);
}
FindClose(hFile);
}
+
+ // The font matching code iterates over the font list, and the first font in the
+ // list always becomes the one to beat. In the case where none of the fonts match
+ // (they all have the same score), this first font ends up winning. So make sure
+ // a reasonably good font, like Arial, is the first one in the list.
+ wstring lowerName = L"arial"; // use lower-case
+ RS_Font* font = (RS_Font*)FindFont(lowerName, false, false);
+ if (font && font->m_fullname == lowerName)
+ {
+ // we found Arial - move it to the front
+ m_fontlist.remove(font);
+ m_fontlist.push_front(font);
+ }
}
#else
// initialize the font list
-void FontManager::init_font_list(const wchar_t* specificName)
+void FontManager::init_font_list()
{
AutoMutexLocker autoLocker(sm_mutex);
+ int error = 0;
+
string dirname(".");
DIR* pCurrent = opendir(dirname.c_str());
- wstring searchString;
- if (specificName)
- searchString = ToLower(specificName);
-
while (pCurrent)
{
errno = 0;
@@ -254,21 +330,36 @@
struct stat st;
if (stat(entryName.c_str(), &st) == 0)
{
- wstring en;
- UnicodeString::MultiByteToWideChar(entryName.c_str(), en);
+ // ok, load up the face information
+ FT_Face face = NULL;
+ FT_Long index = 0;
+ FT_Long num_faces = 0;
- //are we searching for a specific font
- if (!searchString.empty())
+ do
{
- wstring wFilename;
- UnicodeString::MultiByteToWideChar(entryName.c_str(), wFilename);
- wstring lowerFileName = ToLower(wFilename);
+ error = FT_New_Face(m_library, entryName.c_str(), index, &face);
- if (!wcsstr(lowerFileName.c_str(), searchString.c_str()))
- continue;
+ // TODO: revisit using the font manager here
+// error = m_FM->get_face(entryName.c_str(), index, &face);
+
+ if (!error)
+ {
+ // init num_faces if necessary
+ if (!num_faces)
+ num_faces = face->num_faces;
+ }
+
+ wstring en;
+ UnicodeString::MultiByteToWideChar(entryName.c_str(), en);
+ create_font(face, index, en.c_str());
+
+ // dispose of face
+ FT_Done_Face(face);
+
+ // increment our face index
+ index++;
}
-
- CacheFont(en.c_str());
+ while (!error && index < num_faces);
}
}
else
@@ -283,10 +374,8 @@
// create a font with the given face information
-void FontManager::create_font(void* facePtr, FT_Long index, wchar_t const* filename)
+void FontManager::create_font(FT_Face face, FT_Long index, wchar_t const* filename)
{
- FT_Face face = (FT_Face)facePtr;
-
// do we have a valid face?
if (!face)
return;
@@ -411,12 +500,6 @@
if (entry.stylearray[index])
return entry.stylearray[index];
- //If we are delay loading, attempt to cache the specific font
- if (DELAY_LOAD_FONTS)
- {
- init_font_list(sfontname.c_str());
- }
-
const wchar_t* fontname = sfontname.c_str();
// if there is an alias for the font use that instead
@@ -430,7 +513,7 @@
}
}
- wstring lowername = ToLower(sfontname);
+ wstring lowername = ToLower(fontname);
const wchar_t* buf = lowername.c_str();
int score = 0;
Modified: trunk/MgDev/Common/Renderers/FontManager.h
===================================================================
--- trunk/MgDev/Common/Renderers/FontManager.h 2010-09-21 18:41:02 UTC (rev 5175)
+++ trunk/MgDev/Common/Renderers/FontManager.h 2010-09-21 18:43:36 UTC (rev 5176)
@@ -22,6 +22,12 @@
#include "RS_Font.h" // for FontList
#include "CriticalSection.h"
+// FreeType includes
+#include "ft2build.h"
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+#include FT_CACHE_H
+#include FT_CACHE_MANAGER_H
#include <map>
@@ -56,11 +62,11 @@
~FontManager();
public:
+ int get_face(const char* filename, FT_Long index, FT_Face* face);
- RENDERERS_API void init_font_list(const wchar_t* specificName = NULL);
+ void init_font_list();
+ void create_font(FT_Face face, FT_Long index, wchar_t const* filename);
- void create_font(void* face, long index, wchar_t const* filename);
-
RENDERERS_API void AddFontAlias(const wchar_t* alias, const wchar_t* asciiName);
FontList* GetFontList();
@@ -72,10 +78,10 @@
private:
FaceMapEntryType* load_file(const char* filename);
- bool CacheFont(wchar_t const* fileName);
private:
- void* m_library;
+ FT_Library m_library;
+ FaceMap m_facemap;
FontList m_fontlist;
FontMap m_fontAliases;
@@ -83,7 +89,6 @@
static CustomThreadMutex sm_mutex;
static FontManager sm_manager;
- static bool sm_init;
};
#endif
More information about the mapguide-commits
mailing list