? 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 =================================================================== --- src/configure.ac.orig +++ src/configure.ac @@ -27,11 +27,9 @@ dnl ------------------------------------ dnl Initialization and Versioning dnl ------------------------------------------------ -AC_INIT AC_PREREQ(2.52) AC_INIT(gnu-ghostscript, 8.16, didier.link@wanadoo.fr) AC_CONFIG_SRCDIR(src/gs.c) -AM_INIT_AUTOMAKE dnl TOPDIR=`pwd` @@ -345,6 +343,13 @@ AC_ARG_ENABLE(compile-inits, AC_HELP_STR fi]) AC_SUBST(COMPILE_INITS) +PKG_CHECK_MODULES([FONTCONFIG], [fontconfig], [have_fontconfig=yes], [have_fontconfig=no]) +if test "x$have_fontconfig" = "xyes"; then + AC_DEFINE_UNQUOTED(HAVE_FONTCONFIG, 1, [Defines if your system has the libfontconfig library]) +fi +CFLAGS="$CFLAGS $FONTCONFIG_CFLAGS" +AC_SUBST(FONTCONFIG_LIBS) + dnl -------------------------------------------------- dnl Check for library functions dnl -------------------------------------------------- Index: src/gp_unix.c =================================================================== --- src/gp_unix.c.orig +++ src/gp_unix.c @@ -30,6 +30,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. @@ -182,16 +188,193 @@ gp_close_printer(FILE * pfile, const cha * 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 +} + Index: src/Makefile.in =================================================================== --- src/Makefile.in.orig +++ src/Makefile.in @@ -253,7 +253,7 @@ LDFLAGS=@LDFLAGS@ $(XLDFLAGS) # Solaris may need -lnsl -lsocket -lposix4. # (Libraries required by individual drivers are handled automatically.) -EXTRALIBS= +EXTRALIBS=@FONTCONFIG_LIBS@ # Define the standard libraries to search at the end of linking. # Most platforms require -lpthread for the POSIX threads library;