|
Graphviz
2.31.20130618.0446
|
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 }
1.7.5