Graphviz  2.31.20130618.0446
plugin/pango/gvgetfontlist_pango.c
Go to the documentation of this file.
00001 /* $Id$Revision: */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 #ifdef HAVE_CONFIG_H
00015 #include "config.h"
00016 #endif
00017 
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <string.h>
00021 #include <ctype.h>
00022 
00023 /* FIXME - the following declaration should be removed
00024  * when configure is coordinated with flags passed to the
00025  * compiler. On Linux, strcasestr is defined but needs a special
00026  * preprocessor constant to be defined. Configure sets the
00027  * HAVE_STRCASESTR, but the flag is not used during compilation,
00028  * so strcasestr is undeclared.
00029  */
00030 char* strcasestr (const char *str, const char *pat);
00031 #ifndef HAVE_STRCASESTR
00032 char* strcasestr (const char *str, const char *pat)
00033 {
00034     int slen, plen;
00035     char p0, pc;
00036     const char *endp, *sp, *pp;
00037     if (!(p0 = *pat)) return (char*)str;
00038     plen = strlen (pat++);
00039     slen = strlen (str);
00040     if (slen < plen) return NULL;
00041     endp = str + slen - plen;
00042     p0 = toupper (p0);
00043     do {
00044         while ((str <= endp) && (p0 != toupper(*str))) str++;
00045         if (str > endp) return NULL;
00046         pp = pat;
00047         sp = ++str;
00048         while ((pc = *pp++) && (toupper(pc) == toupper(*sp))) sp++;
00049     } while (pc);
00050     return (char*)(str-1);
00051 }
00052 
00053 #endif
00054 
00055 #include "agxbuf.h"
00056 #include "gvplugin_textlayout.h"
00057 #ifdef HAVE_PANGOCAIRO
00058 #include <pango/pangocairo.h>
00059 #include "gvgetfontlist.h"
00060 #endif
00061 
00062 extern int Verbose;
00063 
00064 #define FNT_BOLD        1<<0
00065 #define FNT_BOOK        1<<1
00066 #define FNT_CONDENSED   1<<2
00067 #define FNT_DEMI        1<<3
00068 #define FNT_EXTRALIGHT  1<<4
00069 #define FNT_ITALIC      1<<5
00070 #define FNT_LIGHT       1<<6
00071 #define FNT_MEDIUM      1<<7
00072 #define FNT_OBLIQUE     1<<8
00073 #define FNT_REGULAR     1<<9
00074 #define FNT_ROMAN       1<<9
00075 
00076 #define PS_AVANTGARDE "AvantGarde"
00077 #define PS_BOOKMAN "Bookman"
00078 #define PS_COURIER "Courier"
00079 #define PS_HELVETICA SAN_5
00080 #define PS_NEWCENTURYSCHLBK "NewCenturySchlbk"
00081 #define PS_PALATINO "Palatino"
00082 #define PS_SYMBOL "Symbol"
00083 #define PS_TIMES SER_3
00084 #define PS_CHANCERY "ZapfChancery"
00085 #define PS_DINGBATS "ZapfDingbats"
00086 
00087 #define FNT_BOLD_ST     "BOLD"
00088 #define FNT_BOOK_ST     "BOOK"
00089 #define FNT_CONDENSED_ST        "CONDENSED"
00090 #define FNT_DEMI_ST     "DEMI"
00091 #define FNT_EXTRALIGHT_ST       "EXTRALIGHT"
00092 #define FNT_ITALIC_ST   "ITALIC"
00093 #define FNT_LIGHT_ST    "LIGHT"
00094 #define FNT_MEDIUM_ST   "MEDIUM"
00095 #define FNT_OBLIQUE_ST  "OBLIQUE"
00096 #define FNT_REGULAR_ST  "REGULAR"
00097 #define FNT_ROMAN_ST    "ROMAN"
00098 
00099 #define SAN_0           "sans"
00100 #define SAN_1           "URW Gothic L"
00101 #define SAN_2           "Charcoal"
00102 #define SAN_3           "Nimbus Sans L"
00103 #define SAN_4           "Verdana"
00104 #define SAN_5           "Helvetica"
00105 #define SAN_6           "Bitstream Vera Sans"
00106 #define SAN_7           "DejaVu Sans"
00107 #define SAN_8           "Liberation Sans"
00108 #define SAN_9           "Luxi Sans"
00109 #define SAN_10          "FreeSans"
00110 #define SAN_11          "Arial"
00111 
00112 #define SER_0           "serif"
00113 #define SER_1           "URW Bookman L"
00114 #define SER_2           "Times New Roman"
00115 #define SER_3           "Times"
00116 #define SER_4           "Nimbus Roman No9 L"
00117 #define SER_5           "Bitstream Vera Serif"
00118 #define SER_6           "DejaVu Serif"
00119 #define SER_7           "Liberation Serif"
00120 #define SER_8           "Luxi Serif"
00121 #define SER_9           "FreeSerif"
00122 #define SER_10          "Century Schoolbook L"
00123 #define SER_11          "Charcoal"
00124 #define SER_12          "Georgia"
00125 #define SER_13          "URW Palladio L"
00126 #define SER_14          "Norasi"
00127 #define SER_15          "Rekha"
00128 #define SER_16          "URW Chancery L"
00129 
00130 #define MON_0           "monospace"
00131 #define MON_1           "Nimbus Mono L"
00132 #define MON_2           "Inconsolata"
00133 #define MON_3           "Courier New"
00134 #define MON_4           "Bitstream Vera Sans Mono"
00135 #define MON_5           "DejaVu Sans Mono"
00136 #define MON_6           "Liberation Mono"
00137 #define MON_7           "Luxi Mono"
00138 #define MON_8           "FreeMono"
00139 
00140 #define SYM_0           "fantasy"
00141 #define SYM_1           "Impact"
00142 #define SYM_2           "Copperplate Gothic Std"
00143 #define SYM_3           "Cooper Std"
00144 #define SYM_4           "Bauhaus Std"
00145 
00146 #define DING_0          "fantasy"
00147 #define DING_1          "Dingbats"
00148 #define DING_2          "Impact"
00149 #define DING_3          "Copperplate Gothic Std"
00150 #define DING_4          "Cooper Std"
00151 #define DING_5          "Bauhaus Std"
00152 
00153 
00154 typedef struct {
00155     int flag;
00156     char* name;
00157 } face_t;
00158 static face_t facelist[] = {
00159     { FNT_BOLD, FNT_BOLD_ST}, 
00160     { FNT_BOOK, FNT_BOOK_ST}, 
00161     { FNT_CONDENSED, FNT_CONDENSED_ST}, 
00162     { FNT_DEMI, FNT_DEMI_ST},
00163     { FNT_EXTRALIGHT, FNT_EXTRALIGHT_ST}, 
00164     { FNT_ITALIC, FNT_ITALIC_ST}, 
00165     { FNT_LIGHT, FNT_LIGHT_ST}, 
00166     { FNT_MEDIUM, FNT_MEDIUM_ST}, 
00167     { FNT_OBLIQUE, FNT_OBLIQUE_ST}, 
00168     { FNT_REGULAR, FNT_REGULAR_ST}, 
00169     { FNT_ROMAN, FNT_ROMAN_ST},
00170 };
00171 #define FACELIST_SZ (sizeof(facelist)/sizeof(face_t))
00172 
00173 /* This is where the hierarchy of equivalent fonts is established. The order can be changed
00174    here or new equivalent fonts can be added here. Each font family used by the Graphviz
00175    PS fonts is set up.
00176 */
00177 static const char *PS_AVANT_E[] = { 
00178     SAN_1, SAN_2, SAN_3, SAN_4, SAN_5, SAN_6, SAN_7, SAN_8, SAN_9, SAN_10
00179 };
00180 #define PS_AVANT_E_SZ  (sizeof(PS_AVANT_E) / sizeof(char *))
00181 
00182 static const char *PS_BOOKMAN_E[] = { 
00183     SER_1, SER_2, SER_3, SER_4, SER_5, SER_6, SER_7, SER_8, SER_9 
00184 };
00185 #define PS_BOOKMAN_E_SZ (sizeof(PS_BOOKMAN_E) / sizeof(char *))
00186 
00187 static const char *PS_COURIER_E[] = { 
00188     MON_1, MON_2, MON_3, MON_4, MON_5, MON_6, MON_7, MON_8 
00189 };
00190 #define PS_COURIER_E_SZ (sizeof(PS_COURIER_E) / sizeof(char *))
00191 
00192 static const char *PS_HELVETICA_E[] = { 
00193     SAN_3, SAN_11, SAN_4, SAN_6, SAN_7, SAN_8, SAN_9, SAN_10 
00194 };
00195 #define PS_HELVETICA_E_SZ (sizeof(PS_HELVETICA_E) / sizeof(char *))
00196 
00197 static const char *PS_NEWCENT_E[] = { 
00198     SER_10, SER_2, SER_3, SER_4, SER_12, SER_5, SER_6, SER_7, SER_8, SER_9
00199 };
00200 #define PS_NEWCENT_E_SZ (sizeof(PS_NEWCENT_E) / sizeof(char *))
00201 
00202 static const char *PS_PALATINO_E[] = { 
00203     SER_13, SER_2, SER_3, SER_4, SER_14, SER_15, SER_5, SER_6, SER_7, SER_8, SER_9
00204 };
00205 #define PS_PALATINO_E_SZ (sizeof(PS_PALATINO_E) / sizeof(char *))
00206 
00207 static const char *PS_TIMES_E[] = { 
00208     SER_4, SER_2, SER_11, SER_5, SER_6, SER_7, SER_8, SER_9 
00209 };
00210 #define PS_TIMES_E_SZ (sizeof(PS_TIMES_E) / sizeof(char *))
00211 
00212 static const char *PS_SYMBOL_E[] = { SYM_1, SYM_2, SYM_3, SYM_4 };
00213 #define PS_SYMBOL_E_SZ (sizeof(PS_SYMBOL_E) / sizeof(char *))
00214 
00215 static const char *PS_CHANCERY_E[] = { 
00216     SER_16, SER_11, SER_2, SER_3, SER_4, SER_5, SER_6, SER_7, SER_8, SER_9
00217 };
00218 #define PS_CHANCERY_E_SZ (sizeof(PS_CHANCERY_E) / sizeof(char *))
00219 
00220 static const char *PS_DINGBATS_E[] = { DING_1, SYM_1, SYM_2, SYM_3, SYM_4 };
00221 #define PS_DINGBATS_E_SZ (sizeof(PS_DINGBATS_E) / sizeof(char *))
00222 
00223 typedef struct {
00224     char *generic_name;
00225     char *fontname;
00226     int eq_sz;
00227     const char **equiv;
00228 } fontdef_t;
00229 
00230 /* array of recognized Graphviz PS font names */
00231 static fontdef_t gv_ps_fontdefs[] = {
00232   { SAN_0, PS_AVANTGARDE, PS_AVANT_E_SZ, PS_AVANT_E},
00233   { SER_0, PS_BOOKMAN, PS_BOOKMAN_E_SZ, PS_BOOKMAN_E},
00234   { MON_0, PS_COURIER, PS_COURIER_E_SZ, PS_COURIER_E},
00235   { SAN_0, PS_HELVETICA, PS_HELVETICA_E_SZ, PS_HELVETICA_E},
00236   { SER_0, PS_NEWCENTURYSCHLBK, PS_NEWCENT_E_SZ, PS_NEWCENT_E},
00237   { SER_0, PS_PALATINO, PS_PALATINO_E_SZ, PS_PALATINO_E},
00238   { SYM_0, PS_SYMBOL, PS_SYMBOL_E_SZ, PS_SYMBOL_E},
00239   { SER_0, PS_TIMES, PS_TIMES_E_SZ, PS_TIMES_E},
00240   { SER_0, PS_CHANCERY, PS_CHANCERY_E_SZ, PS_CHANCERY_E},
00241   { DING_0, PS_DINGBATS, PS_DINGBATS_E_SZ, PS_DINGBATS_E},
00242 };
00243 #define GV_FONT_LIST_SIZE (sizeof(gv_ps_fontdefs)/sizeof(fontdef_t))
00244 
00245 typedef struct {
00246     char *gv_ps_fontname;
00247     char *fontname;
00248     int faces;
00249 } availfont_t;
00250 
00251 #define NEW(t)          (t*)malloc(sizeof(t))
00252 #define N_NEW(n,t)      (t*)malloc((n)*sizeof(t))
00253 
00254 static PostscriptAlias postscript_alias[] = {
00255 #include "ps_font_equiv.h"
00256 };
00257 
00258 /* Frees memory used by the available system font definitions */
00259 static void gv_flist_free_af(availfont_t* gv_af_p)
00260 {
00261     int i;
00262 
00263     for (i = 0; i < GV_FONT_LIST_SIZE; i++) {
00264         if (gv_af_p[i].fontname)
00265             free(gv_af_p[i].fontname);
00266     }
00267     free(gv_af_p);
00268 }
00269 
00270 static int get_faces(PangoFontFamily * family)
00271 {
00272     PangoFontFace **faces;
00273     PangoFontFace *face;
00274     int i, j, n_faces;
00275     const char *name;
00276     int availfaces = 0;
00277     /* Get the faces (Bold, Italic, etc.) for the current font family */
00278     pango_font_family_list_faces(family, &faces, &n_faces);
00279     for (i = 0; i < n_faces; i++) {
00280         face = faces[i];
00281         name = pango_font_face_get_face_name(face);
00282 
00283         /* if the family face type is one of the known types, logically OR the known type value
00284            to the available faces integer */
00285         for (j = 0; j < FACELIST_SZ; j++) {
00286             if (strcasestr(name, facelist[j].name)) {
00287                 availfaces |= facelist[j].flag;
00288                 break;
00289             }
00290         }
00291     }
00292     g_free(faces);
00293     return availfaces;
00294 }
00295 
00296 #ifdef DEBUG
00297 static void 
00298 display_available_fonts(availfont_t* gv_af_p)
00299 {
00300     int i, j, faces;
00301 
00302 /* Displays the Graphviz PS font name, system available font name and associated faces */
00303     for (j = 0; j < GV_FONT_LIST_SIZE; j++) {
00304         if ((gv_af_p[j].faces == 0) || (gv_af_p[j].fontname == NULL)) {
00305             fprintf (stderr, "ps font = %s not available\n", gv_ps_fontdefs[j].fontname);
00306             continue;
00307         }
00308         fprintf (stderr, "ps font = %s available %d font = %s\n",
00309             gv_ps_fontdefs[j].fontname, gv_af_p[j].faces, gv_af_p[j].fontname);
00310         faces = gv_af_p[j].faces;
00311         for (i = 0; i < FACELIST_SZ; i++) {
00312             if (faces & facelist[i].flag)
00313                 fprintf (stderr, "\t%s\n", facelist[i].name);
00314         }
00315     }
00316 }
00317 #endif
00318 
00319 /* Construct the list of font faces */
00320 static char *get_avail_faces(int faces, agxbuf* xb)
00321 {
00322     int i;
00323     for (i = 0; i < FACELIST_SZ; i++) {
00324         if (faces & facelist[i].flag) {
00325             agxbput (xb, facelist[i].name); 
00326             agxbputc(xb, ' ');
00327         }
00328     }
00329     return agxbuse (xb);
00330 }
00331 
00332 
00333 /* This function creates an array of font definitions. Each entry corresponds to one of 
00334    the Graphviz PS fonts.  The font definitions contain the generic font name and a list 
00335    of equivalent fonts that can be used in place of the PS font if the PS font is not 
00336    available on the system
00337 */
00338 static availfont_t *gv_get_ps_fontlist(PangoFontMap * fontmap)
00339 {
00340     PangoFontFamily **families;
00341     PangoFontFamily *family;
00342     fontdef_t* gv_ps_fontdef;
00343     int n_families;
00344     int i, j, k, array_sz, availfaces;
00345     availfont_t *gv_af_p, *gv_afs;
00346     const char *name;
00347     char *family_name;
00348 
00349     /* Get a list of font families installed on the system */
00350     pango_font_map_list_families(fontmap, &families, &n_families);
00351 
00352     /* Setup a pointer to available font structs */
00353     gv_af_p = N_NEW(GV_FONT_LIST_SIZE, availfont_t);
00354 
00355     for (j = 0; j < GV_FONT_LIST_SIZE; j++) {
00356         /* get the Graphviz PS font information and create the
00357            available font definition structs */
00358         gv_afs = gv_af_p+j;
00359         gv_ps_fontdef = gv_ps_fontdefs+j;
00360         gv_afs->gv_ps_fontname = gv_ps_fontdef->fontname;
00361         family_name = NULL;
00362         /* Search the installed system font families for the current 
00363            Graphvis PS font family name, i.e. AvantGarde */
00364         for (i = 0; i < n_families; i++) {
00365             family = families[i];
00366             name = pango_font_family_get_name(family);
00367             /* if a match is found get the installed font faces */
00368             if (strcasecmp(gv_ps_fontdef->fontname, name) == 0) {
00369                 family_name = strdup(name);
00370                 availfaces = get_faces(family);
00371             }
00372             if (family_name)
00373                 break;
00374         }
00375         /* if a match is not found on the primary Graphviz font family,
00376            search for a match on the equivalent font family names */
00377         if (!family_name) {
00378             array_sz = gv_ps_fontdef->eq_sz;
00379             for (k = 0; k < array_sz; k++) {
00380                 for (i = 0; i < n_families; i++) {
00381                     family = families[i];
00382                     name = pango_font_family_get_name(family);
00383                     if (strcasecmp(gv_ps_fontdef->equiv[k], name) == 0) {
00384                         family_name = strdup(name);
00385                         availfaces = get_faces(family);
00386                         break;
00387                     }
00388                 }
00389                 if (family_name)
00390                     break;
00391             }
00392         }
00393         /* if a match is not found on the equivalent font family names, search
00394            for a match on the generic family name assigned to the Graphviz PS font */
00395         if (!family_name) {
00396             for (i = 0; i < n_families; i++) {
00397                 family = families[i];
00398                 name = pango_font_family_get_name(family);
00399                 if (strcasecmp(gv_ps_fontdef->generic_name, name) == 0) {
00400                     family_name = strdup(name);
00401                     availfaces = get_faces(family);
00402                     break;
00403                 }
00404             }
00405         }
00406         /* if not match is found on the generic name, set the available font
00407            name to NULL */
00408         if (family_name && availfaces) {
00409             gv_afs->fontname = family_name;
00410             gv_afs->faces = availfaces;
00411         } else {
00412             gv_afs->fontname = NULL;
00413             gv_afs->faces = 0;
00414         }
00415     }
00416     g_free(families);
00417 #ifdef DEBUG
00418     display_available_fonts(gv_af_p);
00419 #endif
00420 /* Free the Graphviz PS font definitions */
00421     return (gv_af_p);
00422 }
00423 
00424 static void copyUpper (agxbuf* xb, char* s)
00425 {
00426     int c;
00427 
00428     while ((c = *s++))
00429         (void)agxbputc (xb, toupper(c));
00430 }
00431 
00432 /* Returns the font corresponding to a Graphviz PS font. 
00433    AvantGarde-Book may return URW Gothic L, book
00434    Returns NULL if no appropriate font found.
00435 */
00436 static char *gv_get_font(availfont_t* gv_af_p,
00437                   PostscriptAlias * ps_alias, agxbuf* xb, agxbuf *xb2)
00438 {
00439     char *avail_faces;
00440     int i;
00441 
00442     for (i = 0; i < GV_FONT_LIST_SIZE; i++) {
00443         /* Searches the array of available system fonts for the one that
00444            corresponds to the current Graphviz PS font name. Sets up the
00445            font string with the available font name and the installed font 
00446            faces that match what are required by the Graphviz PS font.
00447          */
00448         if (gv_af_p[i].faces && strstr(ps_alias->name, gv_af_p[i].gv_ps_fontname)) {
00449             agxbput(xb2, gv_af_p[i].fontname);
00450             agxbput(xb2, ", ");
00451             avail_faces = get_avail_faces(gv_af_p[i].faces, xb);
00452             if (ps_alias->weight) {
00453                 if (strcasestr(avail_faces, ps_alias->weight)) {
00454                     agxbputc(xb2, ' ');
00455                     copyUpper(xb2, ps_alias->weight);
00456                 }
00457             } else if (strcasestr(avail_faces, "REGULAR")) {
00458                 agxbputc(xb2, ' ');
00459                 agxbput(xb2, "REGULAR");
00460             } else if (strstr(avail_faces, "ROMAN")) {
00461                 agxbputc(xb2, ' ');
00462                 agxbput(xb2, "ROMAN");
00463             }
00464             if (ps_alias->stretch) {
00465                 if (strcasestr(avail_faces, ps_alias->stretch)) {
00466                     agxbputc(xb2, ' ');
00467                     copyUpper(xb2, ps_alias->stretch);
00468                 }
00469             }
00470             if (ps_alias->style) {
00471                 if (strcasestr(avail_faces, ps_alias->style)) {
00472                     agxbputc(xb2, ' ');
00473                     copyUpper(xb2, ps_alias->style);
00474                 } else if (!strcasecmp(ps_alias->style, "ITALIC")) {
00475                     /* try to use ITALIC in place of OBLIQUE & visa versa */
00476                     if (strcasestr(avail_faces, "OBLIQUE")) {
00477                         agxbputc(xb2, ' ');
00478                         agxbput(xb2, "OBLIQUE");
00479                     }
00480                 } else if (!strcasecmp(ps_alias->style, "OBLIQUE")) {
00481                     if (strcasestr(avail_faces, "ITALIC")) {
00482                         agxbputc(xb2, ' ');
00483                         agxbput(xb2, "ITALIC");
00484                     }
00485                 }
00486             }
00487             return strdup(agxbuse(xb2));
00488         }
00489     }
00490     return NULL;
00491 }
00492 
00493 static void
00494 printFontMap (gv_font_map*gv_fmap, int sz)
00495 {
00496     int j;
00497     char* font;
00498 
00499     for (j = 0; j < sz; j++) {
00500         font = gv_fmap[j].gv_font;
00501         if (!font)
00502             fprintf (stderr, " [%d] %s => <Not available>\n", j, gv_fmap[j].gv_ps_fontname);
00503         else
00504             fprintf (stderr, " [%d] %s => \"%s\"\n", j, gv_fmap[j].gv_ps_fontname, font);
00505     }
00506 }
00507 
00508 /* Sets up a structure array that contains the Graphviz PS font name
00509    and the corresponding installed font string.  
00510 */
00511 gv_font_map* get_font_mapping(PangoFontMap * fontmap)
00512 {
00513     PostscriptAlias *ps_alias;
00514     availfont_t *gv_af_p;
00515     int j, ps_fontnames_sz = sizeof(postscript_alias) / sizeof(PostscriptAlias);
00516     gv_font_map* gv_fmap = N_NEW(ps_fontnames_sz, gv_font_map);
00517     agxbuf xb;
00518     agxbuf xb2;
00519     unsigned char buf[BUFSIZ];
00520     unsigned char buf2[BUFSIZ];
00521 
00522     agxbinit(&xb, BUFSIZ, buf);
00523     agxbinit(&xb2, BUFSIZ, buf2);
00524     gv_af_p = gv_get_ps_fontlist(fontmap);      // get the available installed fonts
00525     /* add the Graphviz PS font name and available system font string to the array */
00526     for (j = 0; j < ps_fontnames_sz; j++) {
00527         ps_alias = &postscript_alias[j];
00528         gv_fmap[ps_alias->xfig_code].gv_ps_fontname = ps_alias->name;
00529         gv_fmap[ps_alias->xfig_code].gv_font = gv_get_font(gv_af_p, ps_alias, &xb, &xb2);
00530     }
00531     gv_flist_free_af(gv_af_p);
00532     agxbfree(&xb);
00533     agxbfree(&xb2);
00534 #ifndef WIN32
00535     if (Verbose > 1)
00536         printFontMap (gv_fmap, ps_fontnames_sz);
00537 #endif
00538     return gv_fmap;
00539 }
00540 
00541 /* Returns a list of the fonts that are available for use
00542 
00543 */
00544 
00545 void get_font_list(char **fonts[], int *cnt){
00546 
00547 PangoFontMap *fontmap;
00548 availfont_t *gv_af_p;
00549 int j, i;
00550 char **fontlist;
00551 fontlist = N_NEW(GV_FONT_LIST_SIZE,char *);
00552 fontmap = pango_cairo_font_map_new();
00553 gv_af_p = gv_get_ps_fontlist(fontmap);  // get the available installed fonts
00554 g_object_unref(fontmap);
00555 /* load array with available font names */
00556 i=0;
00557 for (j = 0; j < GV_FONT_LIST_SIZE; j++) {
00558         *(fontlist + j) = 0;
00559         if ((gv_af_p[j].faces == 0) || (gv_af_p[j].fontname == NULL)) {
00560             continue;
00561         }
00562         *(fontlist + i++) = strdup(gv_af_p[j].fontname);
00563 }
00564 /* Free unused array elements */
00565 for(j=i;j<GV_FONT_LIST_SIZE;j++){
00566     free(*(fontlist + j));
00567 }
00568 /* Free available fonts structure */
00569 gv_flist_free_af(gv_af_p);
00570 
00571 *cnt = i;
00572 *fonts = fontlist;
00573 return;
00574 }