? 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 +#endif + /* * This is the only place in Ghostscript that calls 'exit'. Including * 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 +} +