[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