Re: use of pango in main window

Robert Hart <[email protected]>
Newsgroups gmane.comp.audio.zinf.devel
Organization University of Nottingham
Message-ID <1060700626.1033.77.camel@euclid>
and now the patch...


On Tue, 2003-08-12 at 14:19, Robert Hart wrote:
> Ok, here's a patch to use pango to render fonts in the main window, so
> we get back much of the functionality of FreeType in much less code.
> 
> At the moment, this code makes no attempt to load anything from a
> specified .ttf file, so the appearance will depend on what fonts you
> have installed on your system.
> 
> I'm not quite sure what's going on with the destructor for GTKFont,
> because it seems to be called many more times than I'd expect. I'm also
> not sure I am doing the right thing with regards to unreffing things.
> 
> Rob
-- 
+-------------------------------------+
| "It's only a trap if you don't take |
| a ladder with you to get out of it" |
| 		-S Ring, Bath Uni     |
|                                     |
| [email protected]                   |
| http://www.nott.ac.uk/~enxrah       |
+-------------------------------------+
pango.diff (text/x-patch, 13.4 KB)
Index: ui/zinf/unix/include/GTKFont.h
===================================================================
RCS file: /cvsroot/zinf/zinf/ui/zinf/unix/include/GTKFont.h,v
retrieving revision 1.3
diff -a -u -r1.3 GTKFont.h
--- ui/zinf/unix/include/GTKFont.h	1 Feb 2003 05:08:03 -0000	1.3
+++ ui/zinf/unix/include/GTKFont.h	12 Aug 2003 13:15:15 -0000
@@ -64,12 +64,10 @@
       FAContext *m_context;
 
     private:
-      FontTypeEnum type;
 
-      GdkFont *gfont;
-#ifdef HAVE_FREETYPE
-      Efont   *ttfont;
-#endif
+      PangoFontDescription* pfont;
+      PangoContext* pango_context;
+      PangoLayout* layout;
      std::string   BuildFontString(bool bBold, bool bItalic, int iFontHeight);
       Error    AddFont(std::string &oFontFile);
 
Index: ui/zinf/unix/src/GTKFont.cpp
===================================================================
RCS file: /cvsroot/zinf/zinf/ui/zinf/unix/src/GTKFont.cpp,v
retrieving revision 1.6
diff -a -u -r1.6 GTKFont.cpp
--- ui/zinf/unix/src/GTKFont.cpp	19 Feb 2003 07:39:23 -0000	1.6
+++ ui/zinf/unix/src/GTKFont.cpp	12 Aug 2003 13:15:15 -0000
@@ -26,6 +26,7 @@
 #include <sys/types.h>
 #include <dirent.h>
 #include <string>
+#include <iostream>
 
 using namespace std;
 #include "path_max.h"
@@ -42,147 +43,18 @@
                  string &oFile, string &oDefault) :
                 Font(oName, oFace, oFile, oDefault)
 {
+  cerr << "Constructor\n";
     m_context = context;
-
-    type = kFontTypeUnknown;
- 
-#ifdef HAVE_FREETYPE
-    if (oFile.length() > 0) {
-        AddFont(oFile);
-        type = kFontTypeTTF;
-        gfont = NULL;
-        ttfont = NULL;
-        bold = false;
-        italic = false;
-        underline = false;
-        first = true;
-        return;
-    }
-#endif
-
-    string finalName;    
-    vector<string> Names;
-    vector<string>::iterator i;
-
-    char *dup = strdup(m_oFace.c_str());
-    char *token = strtok(dup, ",");
-    while (token) {
-         Names.push_back(string(token));
-         token = strtok(NULL, ",");
-    }
-
-    bool gdkfound = false;
-    bool ttffound = false;
-
-#ifdef HAVE_FREETYPE
-    string dir;
-    string ttfbase, ttfpath;
-    WIN32_FIND_DATA find;
-    HANDLE handle;
- 
-    m_context->prefs->GetPrefString(kInstallDirPref, &dir);
-    ttfbase = dir + "/" + BRANDING_SHARE_PATH + "/fonts";
-    ttfpath = ttfbase + "/*.ttf";
- 
-    struct stat st;
-    if (-1 == stat(ttfbase.c_str(), &st))
-        mkdir(ttfbase.c_str(), 0755);
-
-    handle = FindFirstFile((char *)ttfpath.c_str(), &find);
-    if (handle != INVALID_HANDLE_VALUE) {
-        do { 
-            i = Names.begin(); 
-            for (; i != Names.end(); i++) {
-                if (!strncasecmp(find.cFileName, (*i).c_str(), (*i).length())) {
-                    finalName = ttfbase + string("/") + string(find.cFileName);
-                    ttffound = true;
-                    break;
-                }
-            }
-            if (ttffound == true)
-                break;
-        } while (FindNextFile(handle, &find));
-        FindClose(handle);
-    }
-
-    char *fadir = ZinfDir(NULL);
-    ttfbase = string(fadir) + string("/fonts");
-    delete [] fadir;
-
-    if (-1 == stat(ttfbase.c_str(), &st))
-        mkdir(ttfbase.c_str(), 0755);
-
-    ttfpath = ttfbase + string("/*.ttf");
-    handle = FindFirstFile((char *)ttfpath.c_str(), &find);
-    if (handle != INVALID_HANDLE_VALUE) {
-        do {
-            i = Names.begin();
-            for (; i != Names.end(); i++) {
-                if (!strncasecmp(find.cFileName, (*i).c_str(), (*i).length())) {
-                    finalName = ttfbase + string("/") + string(find.cFileName);
-                    ttffound = true;
-                    break;
-                }
-            }
-            if (ttffound == true)
-                break;
-        } while (FindNextFile(handle, &find));
-        FindClose(handle);
-    }
-
-    ttfbase = "./fonts";
-    ttfpath = ttfbase + string("/*.ttf");
-    handle = FindFirstFile((char *)ttfpath.c_str(), &find);
-    if (handle != INVALID_HANDLE_VALUE) {
-        do {
-            i = Names.begin();
-            for (; i != Names.end(); i++) {
-                if (!strncasecmp(find.cFileName, (*i).c_str(), (*i).length())) {
-                    finalName = ttfbase + string("/") + string(find.cFileName);
-                    ttffound = true;
-                    break;
-                }
-            }
-            if (ttffound == true)
-                break;
-        } while (FindNextFile(handle, &find));
-        FindClose(handle);
-    }
-#endif
-
-    if (!ttffound) {
-        gdk_threads_enter();
-        i = Names.begin();
-        for (; i != Names.end(); i++) {
-            if (gdkfound = ListFonts((char *)(*i).c_str())) {
-                finalName = *i;
-                break;
-            }
-        }
-        gdk_threads_leave();
-    }
-
-    if (gdkfound) {
-        m_oFace = finalName; 
-        type = kFontTypeGdk;
-    }
-#ifdef HAVE_FREETYPE
-    else if (ttffound) { 
-        m_oFace = finalName;
-        type = kFontTypeTTF;
-    }
-#endif
-    else {
-        m_oFace = m_oDefault;
-        type = kFontTypeGdk;
-    }
-    free(dup);
-
-    gfont = NULL;
-#ifdef HAVE_FREETYPE
-    ttfont = NULL;
-#endif
+    gdk_threads_enter();
+    pango_context = gdk_pango_context_get();
+    gdk_threads_leave();
+    m_oFace = oFace;
+    m_oName = oName;
+    m_oFile = oFile;
+    pfont = NULL;
+    layout = NULL;
     bold = false;
+    size=0;
     italic = false;
     underline = false;
     first = true;
@@ -190,88 +62,70 @@
 
 Error GTKFont::AddFont(string &oFontFile)
 {
-    string oFontDest;
-    char fcopy[_MAX_PATH], *filename, *ext;
-    struct stat st;
-    string tempfile;
-
-    char *fadir = ZinfDir(NULL);
-    oFontDest = string(fadir) + string ("/fonts");
-    delete [] fadir;
-
-    if (-1 == stat(oFontDest.c_str(), &st))
-        mkdir(oFontDest.c_str(), 0755);
-
-    strcpy(fcopy, oFontFile.c_str());
-    filename = strrchr(fcopy, '/');
-    if (filename) 
-        filename = filename + 1;
-    ext = strrchr(filename, '.');
-    if (ext) {
-        *ext = '\0';
-        ext++;
-    }
-
-    tempfile = oFontFile;
-    if (-1 == stat(tempfile.c_str(), &st)) 
-        tempfile = FindFile(tempfile);
+  //  cerr << "AddFont(" << oFontFile << ")" <<endl;
+//     string oFontDest;
+//     char fcopy[_MAX_PATH], *filename, *ext;
+//     struct stat st;
+//     string tempfile;
+
+//     char *fadir = ZinfDir(NULL);
+//     oFontDest = string(fadir) + string ("/fonts");
+//     delete [] fadir;
+
+//     if (-1 == stat(oFontDest.c_str(), &st))
+//         mkdir(oFontDest.c_str(), 0755);
+
+//     strcpy(fcopy, oFontFile.c_str());
+//     filename = strrchr(fcopy, '/');
+//     if (filename) 
+//         filename = filename + 1;
+//     ext = strrchr(filename, '.');
+//     if (ext) {
+//         *ext = '\0';
+//         ext++;
+//     }
+
+//     tempfile = oFontFile;
+//     if (-1 == stat(tempfile.c_str(), &st)) 
+//         tempfile = FindFile(tempfile);
          
-    oFontDest += string("/") + string(filename);
-    if (ext)
-        oFontDest += string(".") + string(ext);
+//     oFontDest += string("/") + string(filename);
+//     if (ext)
+//         oFontDest += string(".") + string(ext);
 
-    CopyFile(tempfile.c_str(), oFontDest.c_str(), true);
+//     CopyFile(tempfile.c_str(), oFontDest.c_str(), true);
 
-    m_oFace = oFontDest;
+//     m_oFace = oFontDest;
 
     return kError_NoErr;
 }
     
 Error GTKFont::Load(int iFontHeight, bool bBold, bool bItalic)
 {
-    gdk_threads_enter();
-    if (type == kFontTypeGdk) {
-        if (bold != bBold || italic != bItalic || size != iFontHeight || 
-            !gfont) {
-            bold = bBold;
-            italic = bItalic;
-            size = iFontHeight;
-            if (gfont)
-                gdk_font_unref(gfont);
-            string fontname = BuildFontString(bold, italic, size);
-            gfont = gdk_font_load(fontname.c_str());
-            if (!gfont) {
-                fontname = BuildFontString(bold, italic, size - 1);
-                gfont = gdk_font_load(fontname.c_str());
-                if (!gfont) {
-                    gfont = gdk_font_load("variable");  
-                    if (!gfont) {
-                        gfont = gdk_font_load("fixed");
-                        if (!gfont) {
-                            gdk_threads_leave();
-                            //cout << "oops, couldn't load _any_ fonts...\n";
-                            return kError_YouScrewedUp;
-                        }
-                    }
-                }
-            } 
-        }
-    }
-#ifdef HAVE_FREETYPE
-    else {
-        if (!ttfont || iFontHeight != size) {
-            size = iFontHeight;
-            if (ttfont)
-                Efont_free(ttfont);
-            ttfont = Efont_load((char *)m_oFace.c_str(), iFontHeight - 3);
-            if (!ttfont) {
-                gdk_threads_leave();
-                //cout << "ERROR loading ttf " << m_oFace << "\n";
-                return kError_YouScrewedUp;
-            }
-        }
-    }
-#endif
+  gdk_threads_enter();
+  if (pfont==NULL)
+        layout = pango_layout_new(pango_context);
+  if (bold != bBold || italic != bItalic || size != iFontHeight) {
+      bold = bBold;
+      italic = bItalic;
+      size = iFontHeight;
+      if (pfont)
+	pango_font_description_free(pfont);
+      string fontname = BuildFontString(bold, italic, size);
+      pfont = pango_font_description_from_string(fontname.c_str());
+      if (!pfont) {
+	pfont = pango_font_description_from_string("sans");  
+	if (!pfont) {
+	  gdk_threads_leave();
+	  //cout << "oops, couldn't load _any_ fonts...\n";
+	  return kError_YouScrewedUp;
+	}
+      }
+    pango_context_load_font(pango_context, pfont);
+    pango_layout_set_font_description (layout, pfont);
+    pango_layout_context_changed(layout);
+   }
+
     gdk_threads_leave();
     return kError_NoErr;
 }
@@ -279,35 +133,20 @@
 int GTKFont::GetLength(string &oText)
 {
     int retvalue = 0;
-
     gdk_threads_enter();
-    if (type == kFontTypeGdk) 
-        retvalue = gdk_string_measure(gfont, oText.c_str());
-#ifdef HAVE_FREETYPE
-    else if (type == kFontTypeTTF) {
-        Efont_extents(ttfont, (char *)oText.c_str(), NULL, NULL, &retvalue, 
-                      NULL, NULL, NULL, NULL);
-    }
-#endif
+    pango_layout_set_text(layout, oText.c_str(), -1);
+    pango_layout_get_pixel_size (layout, &retvalue, NULL);
     gdk_threads_leave();
     return retvalue;
+
 }
 
 int GTKFont::GetHeight(string &oText)
 {
     int retvalue = 0;
-
     gdk_threads_enter();
-    if (type == kFontTypeGdk)
-       retvalue = gdk_string_height(gfont, oText.c_str());
-#ifdef HAVE_FREETYPE
-    else if (type == kFontTypeTTF) {
-       int ascent = 0, descent = 0;
-       Efont_extents(ttfont, (char *)oText.c_str(), &ascent, &descent, NULL, 
-                     NULL, NULL, NULL, NULL);
-       retvalue = ascent + descent;
-    }
-#endif
+    pango_layout_set_text(layout, oText.c_str(), -1);
+    pango_layout_get_pixel_size (layout, NULL, &retvalue);
     gdk_threads_leave();
     return retvalue;
 }
@@ -331,26 +170,13 @@
 
     gdk_gc_set_clip_rectangle(gc, &clipRect);
 
-    if (type == kFontTypeGdk) {
-       gdk_draw_string(bitmap->GetBitmap(), gfont, gc, oClipRect.x1 + iOffset, 
-                       oClipRect.y1 + oClipRect.Height() - 3, oText.c_str());
+    pango_layout_set_text(layout,oText.c_str(),-1);
+    gdk_draw_layout(bitmap->GetBitmap(), gc, 
+		    oClipRect.x1 + iOffset, 
+		    oClipRect.y1 - 3,
+		    layout);
 
-    // TODO: Underline...
-    }
-#ifdef HAVE_FREETYPE
-    else if (type == kFontTypeTTF) {
-       int ycoord;
-       ycoord = oClipRect.y1 + oClipRect.Height();
-       if (ttfont->ascent < oClipRect.Height()) 
-           ycoord -= ttfont->descent;
-       else 
-           ycoord -= ttfont->descent / 2;
-       ycoord++;
 
-       EFont_draw_string(bitmap->GetBitmap(), gc, oClipRect.x1 + iOffset, 
-                         ycoord, (char *)oText.c_str(), ttfont);
-    }
-#endif
     gdk_flush();
     gdk_gc_unref(gc);
     gdk_threads_leave();
@@ -360,36 +186,34 @@
 
 string GTKFont::BuildFontString(bool bBold, bool bItalic, int iFontHeight)
 {
-   // This isn't the greatest method, as it will probably return stuff we
-   // don't have....
-   string retstring = "-*-" + m_oFace;
+   string retstring = m_oFace;
    if (bBold)
-       retstring += string("-bold-");
-   else
-       retstring += string("-medium-");
+       retstring += string(" bold");
+
    if (bItalic)
-       retstring += string("i-normal-*-");
-   else 
-       retstring += string("r-normal-*-");
+       retstring += string(" italic");
+
    char tempstr[16];
-   sprintf(tempstr, "%d", iFontHeight);
-   retstring += string(tempstr) + string("-*-*-*-*-*-*-*");
+   sprintf(tempstr, " %d", iFontHeight);
+   retstring += string(tempstr);
    return retstring;
 }
 
 GTKFont::~GTKFont(void)
 {
-    gdk_threads_enter();
-    if (type == kFontTypeGdk) {
-        if (gfont)
-            gdk_font_unref(gfont);
-    }
-#ifdef HAVE_FREETYPE
-    else {
-        if (ttfont) {
-            Efont_free(ttfont);
-         }
-    }
-#endif
-    gdk_threads_leave();
+  cerr << "Destructor\n";
+  gdk_threads_enter();
+  if (pfont)
+    {
+
+      pango_font_description_free(pfont);
+      pfont=NULL;
+    }
+    //what else do we need to free here? layout, context?
+    //shot in the dark. is this right?
+  if (G_IS_OBJECT(layout))
+    g_object_unref(layout);
+  if (G_IS_OBJECT(pango_context))
+    g_object_unref(pango_context);
+  gdk_threads_leave();
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.