? autom4te.cache
? fontconfig-patch-0.diff
? fontconfig-patch-1.diff
? fontconfig-patch-2.diff
? fontconfig-patch-3.diff
? fontconfig-patch-4.diff
? loadall.log
? loadall.ps
? native.ps
? test.ps
? src/gp_unix_fc.c
? src/gp_unix_nofc.c
Index: src/configure.ac
===================================================================
RCS file: /cvs/ghostscript/gs/src/configure.ac,v
retrieving revision 1.50
diff -u -r1.50 configure.ac
--- src/configure.ac	25 Jan 2005 01:19:34 -0000	1.50
+++ src/configure.ac	29 Jun 2005 08:10:44 -0000
@@ -399,6 +399,43 @@
                fi])
 AC_SUBST(COMPILE_INITS)
 
+dnl Do we have libfontconfig ?
+dnl Don't bother trying to use fontconfig-config, recent fontconfig versions
+dnl provide pkg-config instead.
+PKG_CONFIG=""
+AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+LIBFONTCONFIG_LIBS=
+LIBFONTCONFIG_CFLAGS=
+AC_MSG_CHECKING([for fontconfig])
+if test -n "${PKG_CONFIG}"; then
+	LIBFONTCONFIG_LIBS="`${PKG_CONFIG} fontconfig --libs`"
+	LIBFONTCONFIG_CFLAGS="`${PKG_CONFIG} fontconfig --cflags`"
+	if test -n "$LIBFONTCONFIG_LIBS" || test -n "$LIBFONTCONFIG_CFLAGS"; then
+		AC_MSG_RESULT([found])
+	else
+		AC_MSG_RESULT([not found])
+	fi
+else
+	AC_MSG_RESULT([failed: pkg-config not found])
+fi
+dnl We found fontconfig, or think we did, but need to check if it's usable
+SAVE_CFLAGS="${CFLAGS}"
+SAVE_LDFLAGS="${LDFLAGS}"
+CFLAGS="${CFLAGS} ${LIBFONTCONFIG_CFLAGS}"
+LDFLAGS="${LDFLAGS} ${LIBFONTCONFIG_LIBS}"
+AC_CHECK_LIB(fontconfig, FcPatternBuild, [hafontconfig=yes],[hafontconfig=no])
+CFLAGS="${SAVE_CFLAGS}"
+LDFLAGS="${SAVE_LDFLAGS}"
+AC_MSG_CHECKING([if fontconfig is usable])
+if test $hafontconfig = yes; then
+	AC_DEFINE_UNQUOTED(HAVE_FONTCONFIG, 1, [Defines if your system has the libfontconfig library])
+	AC_MSG_RESULT([yes])
+else
+	AC_MSG_RESULT([no])
+fi
+AC_SUBST(LIBFONTCONFIG_LIBS)
+AC_SUBST(LIBFONTCONFIG_CFLAGS)
+
 dnl --------------------------------------------------
 dnl Check for library functions
 dnl --------------------------------------------------
Index: src/gp_unix.c
===================================================================
RCS file: /cvs/ghostscript/gs/src/gp_unix.c,v
retrieving revision 1.13
diff -u -r1.13 gp_unix.c
--- src/gp_unix.c	15 Jan 2004 09:27:10 -0000	1.13
+++ src/gp_unix.c	29 Jun 2005 08:10:45 -0000
@@ -24,6 +24,12 @@
 #include "gsexit.h"
 #include "gp.h"
 
+#define HAVE_FONTCONFIG
+
+#ifdef HAVE_FONTCONFIG
+#include <fontconfig/fontconfig.h>
+#endif
+
 /*
  * This is the only place in Ghostscript that calls 'exit'.  Including
  * <stdlib.h> is overkill, but that's where it's declared on ANSI systems.
@@ -175,16 +181,193 @@
   * building a custom fontmap file.
   */
  
+
+/* Mangle the FontConfig family and style information into a
+ * PostScript font name */
+#ifdef HAVE_FONTCONFIG
+static void makePSFontName(char* family, int weight, int slant, char *buf, int bufsize)
+{
+    int bytesCopied, length, i;
+    const char *slantname, *weightname;
+
+    switch (slant) {
+	case FC_SLANT_ROMAN:   slantname=""; break;;
+	case FC_SLANT_OBLIQUE: slantname="Oblique"; break;;
+	case FC_SLANT_ITALIC:  slantname="Italic"; break;;
+	default:               slantname="Unknown"; break;;
+    }
+
+    switch (weight) {
+	case FC_WEIGHT_MEDIUM:   weightname=""; break;;
+	case FC_WEIGHT_LIGHT:    weightname="Light"; break;;
+	case FC_WEIGHT_DEMIBOLD: weightname="Demi"; break;;
+	case FC_WEIGHT_BOLD:     weightname="Bold"; break;;
+	case FC_WEIGHT_BLACK:    weightname="Black"; break;;
+	default:                 weightname="Unknown"; break;;
+    }
+
+    length = strlen(family);
+    if (length >= bufsize)
+	length = bufsize;
+    /* Copy the family name, stripping spaces */
+    bytesCopied=0;
+    for (i = 0; i < length; i++)
+	if (family[i] != ' ')
+	    buf[bytesCopied++] = family[i];
+
+    if ( ((slant != FC_SLANT_ROMAN) || (weight != FC_WEIGHT_MEDIUM)) \
+	    && bytesCopied < bufsize )
+    {
+	buf[bytesCopied] = '-';
+	bytesCopied++;
+	if (weight != FC_WEIGHT_MEDIUM)
+	{
+	    length = strlen(family);
+	    if ((length + bytesCopied) >= bufsize)
+		length = bufsize - bytesCopied - 1;
+	    strncpy(buf+bytesCopied, weightname, length);
+	    bytesCopied += length;
+	}
+	if (slant != FC_SLANT_ROMAN)
+	{
+	    length = strlen(family);
+	    if ((length + bytesCopied) >= bufsize)
+		length = bufsize - bytesCopied - 1;
+	    strncpy(buf+bytesCopied, slantname, length);
+	    bytesCopied += length;
+	}
+    }
+    buf[bytesCopied] = '\0';
+}
+#endif
+
+/* State struct for font iteration - passed as an opaque 'void*' through the rest of gs */
+#ifdef HAVE_FONTCONFIG
+typedef struct {
+    int index;              /* current index of iteration over font_list */
+    FcConfig* fc;           /* FontConfig library handle */
+    FcFontSet* font_list;   /* FontConfig font list */
+    char name[255];         /* name of last font */
+} unix_fontenum_t;
+#endif
+
 void *gp_enumerate_fonts_init(gs_memory_t *mem)
 {
+#ifdef HAVE_FONTCONFIG
+    unix_fontenum_t *state = (unix_fontenum_t *)malloc(sizeof(unix_fontenum_t));
+    if (state == NULL)
+	return NULL;    /* Failed to allocate state */
+
+    state->index     = 0;
+    state->fc        = NULL;
+    state->font_list = NULL;
+
+    /* Load the fontconfig library */
+    state->fc = FcInitLoadConfigAndFonts();
+    if (state->fc == NULL) {
+	free(state);
+	state = NULL;
+	dlprintf("destroyed state - fontconfig init failed");
+	return NULL;  /* Failed to open fontconfig library */
+    }
+
+    /* load the font set that we'll iterate over */
+    FcPattern *pat = FcPatternBuild(NULL,
+	    FC_OUTLINE, FcTypeBool, 1,
+	    FC_SCALABLE, FcTypeBool, 1,
+	    NULL);
+    FcObjectSet* os = FcObjectSetBuild(FC_FILE, FC_OUTLINE, FC_FAMILY, FC_WEIGHT, FC_SLANT, 0);
+    state->font_list = FcFontList(0, pat, os);
+    FcPatternDestroy(pat);
+    FcObjectSetDestroy(os);
+    if (state->font_list == NULL) {
+	free(state);
+	state = NULL;
+	return NULL;  /* Failed to generate font list */
+    }
+    return (void *)state;
+#else
     return NULL;
+#endif
 }
-         
+
 int gp_enumerate_fonts_next(void *enum_state, char **fontname, char **path)
 {
+#ifdef HAVE_FONTCONFIG
+    char* psname = NULL;
+
+    unix_fontenum_t* state = (unix_fontenum_t *)enum_state;
+    if (state == NULL) {
+	return 0;   /* gp_enumerate_fonts_init failed for some reason */
+    }
+
+    /* Bits of the following were borrowed from Red Hat's GS 7 FontConfig patch */
+    FcChar8* file_fc = NULL;
+    FcChar8* family_fc = NULL;
+    int outline_fc, slant_fc, weight_fc;
+    FcResult result;
+
+    if (state->index == state->font_list->nfont) {
+	return 0; /* we've run out of fonts */
+    }
+
+    FcPattern* font = state->font_list->fonts[state->index];
+
+    result = FcPatternGetString (font, FC_FAMILY, 0, &family_fc);
+    if (result != FcResultMatch || family_fc == NULL) {
+	dlprintf ("DEBUG: FC_FAMILY mismatch\n");
+	return 0;
+    }
+
+    result = FcPatternGetString (font, FC_FILE, 0, &file_fc);
+    if (result != FcResultMatch || file_fc == NULL) {
+	dlprintf ("DEBUG: FC_FILE mismatch\n");
+	return 0;
+    }
+
+    result = FcPatternGetBool (font, FC_OUTLINE, 0, &outline_fc);
+    if (result != FcResultMatch) {
+	dlprintf1 ("DEBUG: FC_OUTLINE failed to match on %s\n", (char*)family_fc);
+	return 0;
+    }
+
+    result = FcPatternGetInteger (font, FC_SLANT, 0, &slant_fc);
+    if (result != FcResultMatch) {
+	dlprintf ("DEBUG: FC_SLANT didn't match\n");
+	return 0;
+    }
+
+    result = FcPatternGetInteger (font, FC_WEIGHT, 0, &weight_fc);
+    if (result != FcResultMatch) {
+	dlprintf ("DEBUG: FC_WEIGHT didn't match\n");
+	return 0;
+    }
+
+    /* Gross hack to work around Fontconfig's inability to tell
+     * us the font's PostScript name - generate it ourselves.
+     * We must free the memory allocated here next time around. */
+    makePSFontName((char *)family_fc, weight_fc, slant_fc, &state->name, sizeof(state->name));
+    *fontname = &state->name;
+
+    /* return the font path straight out of fontconfig */
+    *path = (char*)file_fc;
+
+    state->index ++;
+    return 1;
+#else
     return 0;
+#endif
 }
-                         
+
 void gp_enumerate_fonts_free(void *enum_state)
 {
-}           
+#ifdef HAVE_FONTCONFIG
+    unix_fontenum_t* state = (unix_fontenum_t *)enum_state;
+    if (state != NULL) {
+	if (state->font_list != NULL)
+	    FcFontSetDestroy(state->font_list);
+	free(state);
+    }
+#endif
+}
+
