View Issue Details

IDProjectCategoryView StatusLast Update
0002075ScribusImport / Exportpublic2007-01-04 10:33
ReporterringercAssigned Toringerc 
PrioritynormalSeverityfeatureReproducibilityalways
Status closedResolutionno change required 
Platformx86 Linux 
Summary0002075: Finish GhostScript fontconfig work
DescriptionAfter exams, talk to GhostGum about finishing the gs work.

Dig out the old patch, finish the fontconfig detection in configure, then get gg's help to do the gs build integration.
TagsNo tags attached.
Patch

Activities

2005-11-03 17:18

 

fontconfig-patch-4.diff (8,446 bytes)   
? 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
+}
+
fontconfig-patch-4.diff (8,446 bytes)   

ringerc

2005-11-03 17:20

reporter   ~0007317

Attached most recent version of patch against 8.51cvs (IIRC - it's been a while since I worked on this).

Should all be good to go, pending a final check, some extensive testing, and the build integration. gs's build system is unique, and I haven't had time to look at how to do it yet.

Note that to build gs with this patch you'll need to hack the Makefile to add -lfontconfig to LDFLAGS and add '#define HAVE_FONTCONFIG' to the top of gp_unix.c because the build integration is absent. You might also have to ensure that the fontconfig libs and headers are on LD_LIBRARY_PATH and CPATH, respectively. Again, this is only necessary because we're not using pkg-config to find fontconfig, since the build integration is missing.

plinnell

2005-11-03 21:13

viewer   ~0007320

8.53 is out with a new ps2write high level device

cbradney

2006-01-14 13:40

administrator   ~0008078

This is not a Scribus bug, but its ok to have here to share the diffs. Has this work gone into GS? It'd be nice to get it there and close this.

pva

2006-09-20 13:39

reporter   ~0012579

Forwarding information from https://bugs.gentoo.org/show_bug.cgi?id=104512.

Patch was forwardered upstream and applyed in ESP ghostscript:
http://www.cups.org/espgs/str.php?L1631+P0+S-2+C0+I0+E0+Q

ringerc

2006-09-20 14:11

reporter   ~0012580

Brilliant, thanks for letting me know. I've been meaning to get onto this for ages, but I always end up looking at gs's build system but have simply never got around to it.

I'll update the upstream gs bug so this round of bug tracker tag can continue. Oh, and so they can hopefully import the ESP GS patch.

cbradney

2006-10-15 22:46

administrator   ~0012991

This is not a Scribus bug, can we please get this pushed upstream and close this as not a bug.

cbradney

2007-01-04 10:32

administrator   ~0014486

Not a Scribus task, closing.

Issue History

Date Modified Username Field Change
2005-06-08 07:11 ringerc New Issue
2005-06-08 07:12 ringerc Status new => assigned
2005-06-08 07:12 ringerc Assigned To => ringerc
2005-10-11 13:28 ringerc Priority urgent => normal
2005-11-03 17:18 ringerc File Added: fontconfig-patch-4.diff
2005-11-03 17:20 ringerc Note Added: 0007317
2005-11-03 17:20 ringerc OS Fedora Core =>
2005-11-03 17:20 ringerc OS Version 3 =>
2005-11-03 21:13 plinnell Note Added: 0007320
2006-01-14 13:40 cbradney Note Added: 0008078
2006-09-20 13:39 pva Note Added: 0012579
2006-09-20 14:11 ringerc Note Added: 0012580
2006-10-15 22:46 cbradney Note Added: 0012991
2007-01-04 10:32 cbradney Note Added: 0014486
2007-01-04 10:33 cbradney Status assigned => resolved
2007-01-04 10:33 cbradney Resolution open => no change required
2007-01-04 10:33 cbradney Status resolved => closed