[PATCH libXfont] Add a new 'catalogue' FPE, which takes font paths from symlinks in a dir.

Kristian Høgsberg krh at bitplanet.net
Tue Jun 19 08:00:05 PDT 2007


This patch adds a new FPE type, which will match font path elements of the
form

	catalogue:<dir>

The dir specified after the catalogue: prefix will be scanned for symlinks
and each symlink destination will be added as a local fontfile FPE.
The symlink can be suffixed by attributes, such as 'unscaled', which
will be passed through to the underlying fontfile FPE.  Except the new
attribute 'pri' which will be used for ordering the fontfile FPEs.

An example configuration:

	75dpi:unscaled:pri=20 -> /usr/share/X11/fonts/75dpi
	ghostscript:pri=60 -> /usr/share/fonts/default/ghostscript
	misc:unscaled:pri=10 -> /usr/share/X11/fonts/misc
	type1:pri=40 -> /usr/share/X11/fonts/Type1
	type1:pri=50 -> /usr/share/fonts/default/Type1

will add /usr/share/X11/fonts/misc as the first FPE with the attribute
'unscaled', second FPE will be /usr/share/X11/fonts/75dpi, also with
the attribute unscaled etc.  This is functionally equivalent to setting
the following font path:

	/usr/share/X11/fonts/misc:unscaled,
	/usr/share/X11/fonts/75dpi:unscaled,
	/usr/share/X11/fonts/Type1,
	/usr/share/fonts/default/Type1,
	/usr/share/fonts/default/ghostscript

The motivation is to let font packages add a symlink to the new font
directory they provide instead of rewriting either the Xorg config file
or the xfs config file.
---
 include/X11/fonts/fntfil.h |    4 +
 src/fontfile/Makefile.am   |    3 +-
 src/fontfile/catalogue.c   |  391 ++++++++++++++++++++++++++++++++++++++++++++
 src/fontfile/fontfile.c    |   41 ++---
 src/fontfile/register.c    |    1 +
 5 files changed, 413 insertions(+), 27 deletions(-)
 create mode 100644 src/fontfile/catalogue.c

diff --git a/include/X11/fonts/fntfil.h b/include/X11/fonts/fntfil.h
index 81d2cbc..074f2d0 100644
--- a/include/X11/fonts/fntfil.h
+++ b/include/X11/fonts/fntfil.h
@@ -92,6 +92,9 @@ extern int FontFileOpenBitmap ( FontPathElementPtr fpe, FontPtr *pFont,
 extern int FontFileListFonts ( pointer client, FontPathElementPtr fpe, 
 			       char *pat, int len, int max, 
 			       FontNamesPtr names );
+extern int FontFileStartListFonts ( pointer client, FontPathElementPtr fpe, 
+				    char *pat, int len, int max, 
+				    pointer *privatep, int mark_aliases );
 extern int FontFileStartListFontsWithInfo ( pointer client, 
 					    FontPathElementPtr fpe, 
 					    char *pat, int len, int max, 
@@ -111,6 +114,7 @@ extern int FontFileListNextFontOrAlias ( pointer client,
 					 char **resolvedp, int *resolvedlenp, 
 					 pointer private );
 extern void FontFileRegisterLocalFpeFunctions ( void );
+extern void CatalogueRegisterLocalFpeFunctions ( void );
 
 
 extern FontEntryPtr FontFileAddEntry ( FontTablePtr table, 
diff --git a/src/fontfile/Makefile.am b/src/fontfile/Makefile.am
index a80f437..8c361bd 100644
--- a/src/fontfile/Makefile.am
+++ b/src/fontfile/Makefile.am
@@ -26,4 +26,5 @@ libfontfile_la_SOURCES = 	\
 	gunzip.c		\
 	printerfont.c		\
 	register.c		\
-	renderers.c
+	renderers.c		\
+	catalogue.c
diff --git a/src/fontfile/catalogue.c b/src/fontfile/catalogue.c
new file mode 100644
index 0000000..aa88133
--- /dev/null
+++ b/src/fontfile/catalogue.c
@@ -0,0 +1,391 @@
+/*
+ * Copyright © 2007 Red Hat, Inc
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of Red Hat,
+ * Inc not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission.  Red Hat, Inc makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
+ * NO EVENT SHALL RED HAT, INC BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
+ * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fntfilst.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+
+static const char CataloguePrefix[] = "catalogue:";
+
+static int CatalogueFreeFPE (FontPathElementPtr fpe);
+
+static int
+CatalogueNameCheck (char *name)
+{
+    return strncmp(name, CataloguePrefix, sizeof(CataloguePrefix) - 1) == 0;
+}
+
+typedef struct _CatalogueRec {
+    int fpeCount, fpeAlloc;
+    FontPathElementPtr *fpeList;
+} CatalogueRec, *CataloguePtr;
+
+static int
+CatalogueAddFPE (CataloguePtr cat, FontPathElementPtr fpe)
+{
+    FontPathElementPtr *new;
+
+    if (cat->fpeCount >= cat->fpeAlloc)
+    {
+	if (cat->fpeAlloc == 0)
+	    cat->fpeAlloc = 16;
+	else
+	    cat->fpeAlloc *= 2;
+	
+	new = xrealloc(cat->fpeList,
+		       cat->fpeAlloc * sizeof(FontPathElementPtr));
+	if (new == NULL)
+	    return AllocError;
+
+	cat->fpeList = new;
+    }
+
+    cat->fpeList[cat->fpeCount++] = fpe;
+
+    return Successful;
+}
+
+static const char PriorityAttribute[] = "pri=";
+
+static int
+ComparePriority(const void *p1, const void *p2)
+{
+    FontDirectoryPtr dir1 = (*(FontPathElementPtr*) p1)->private;
+    FontDirectoryPtr dir2 = (*(FontPathElementPtr*) p2)->private;
+    const char *pri1 = strstr(dir1->attributes, PriorityAttribute);
+    const char *pri2 = strstr(dir2->attributes, PriorityAttribute);
+
+    if (pri1 == NULL && pri2 == NULL)
+	return 0;
+    else if (pri1 == NULL)
+	return 1;
+    else if (pri2 == NULL)
+	return -1;
+    else
+	return
+	    atoi(pri1 + strlen(PriorityAttribute)) -
+	    atoi(pri2 + strlen(PriorityAttribute));
+}
+
+static int
+CatalogueInitFPE (FontPathElementPtr fpe)
+{
+    int			len;
+    CataloguePtr	cat;
+    DIR			*dir;
+    struct dirent	*entry;
+    const char		*path;
+    char		link[MAXFONTFILENAMELEN];
+    char		dest[MAXFONTFILENAMELEN];
+    char		*attrib;
+    FontPathElementPtr	subfpe;
+
+    cat = (CataloguePtr) xalloc(sizeof *cat);
+    if (cat == NULL)
+	return AllocError;
+
+    path = fpe->name + strlen(CataloguePrefix);
+    dir = opendir(path);
+    if (dir == NULL)
+    {
+	xfree(cat);
+	return BadFontPath;
+    }
+
+    cat->fpeCount = 0;
+    cat->fpeAlloc = 0;
+    cat->fpeList = NULL;
+
+    while (entry = readdir(dir), entry != NULL)
+    {
+	snprintf(link, sizeof link, "%s/%s", path, entry->d_name);
+	len = readlink(link, dest, sizeof dest);
+	if (len < 0)
+	    continue;
+
+	attrib = strchr(link, ':');
+	if (attrib && len + strlen(attrib) < sizeof dest)
+	{
+	    memcpy(dest + len, attrib, strlen(attrib));
+	    len += strlen(attrib);
+	}
+
+	subfpe = xalloc(sizeof *subfpe + len + 1);
+	if (subfpe == NULL)
+	    continue;
+
+	/* The fonts returned by OpenFont will point back to the
+	 * subfpe they come from.  So set the type of the subfpe to
+	 * what the catalogue fpe was assigned, so calls to CloseFont
+	 * (which uses font->fpe->type) goes to CatalogueCloseFont. */
+	subfpe->type = fpe->type;
+	subfpe->name_length = len;
+	subfpe->name = (char *) (subfpe + 1);
+	memcpy(subfpe->name, dest, len);
+	subfpe->name[len] = '\0';
+
+	/* The X server will manipulate the subfpe ref counts
+	 * associated with the font in OpenFont and CloseFont, so we
+	 * have to make sure it's valid. */
+	subfpe->refcount = 1;
+
+	if (FontFileInitFPE (subfpe) != Successful)
+	{
+	    xfree(subfpe);
+	    continue;
+	}
+
+	if (CatalogueAddFPE(cat, subfpe) != Successful)
+	{
+	    FontFileFreeFPE (subfpe);
+	    xfree(subfpe);
+	    continue;
+	}
+    }
+
+    qsort(cat->fpeList,
+	  cat->fpeCount, sizeof cat->fpeList[0], ComparePriority);
+    fpe->private = (pointer) cat;
+
+    return Successful;
+}
+
+static int
+CatalogueResetFPE (FontPathElementPtr fpe)
+{
+    /* Always just tell the caller to close and re-open */
+    return FPEResetFailed;	
+}
+
+static int
+CatalogueFreeFPE (FontPathElementPtr fpe)
+{
+    CataloguePtr	cat = fpe->private;
+    int			i;
+
+    for (i = 0; i < cat->fpeCount; i++)
+	FontFileFreeFPE (cat->fpeList[i]);
+
+    xfree(cat->fpeList);
+    xfree(cat);
+
+    return Successful;
+}
+
+static int
+CatalogueOpenFont (pointer client, FontPathElementPtr fpe, Mask flags, 
+		   char *name, int namelen, 
+		   fsBitmapFormat format, fsBitmapFormatMask fmask,
+		   XID id, FontPtr *pFont, char **aliasName, 
+		   FontPtr non_cachable_font)
+{
+    CataloguePtr cat = fpe->private;
+    FontPathElementPtr subfpe;
+    FontDirectoryPtr dir;
+    int i, status;
+
+    for (i = 0; i < cat->fpeCount; i++)
+    {
+	subfpe = cat->fpeList[i];
+	dir = subfpe->private;
+	status = FontFileOpenFont(client, subfpe, flags,
+				  name, namelen, format, fmask, id,
+				  pFont, aliasName, non_cachable_font);
+	if (status == Successful || status == FontNameAlias)
+	    return status;
+    }
+	    
+    return BadFontName;
+}
+
+static void
+CatalogueCloseFont (FontPathElementPtr fpe, FontPtr pFont)
+{
+    /* Note: this gets called with the actual subfpe where we found
+     * the font, not the catalogue fpe. */
+
+    FontFileCloseFont(fpe, pFont);
+}
+
+static int
+CatalogueListFonts (pointer client, FontPathElementPtr fpe, char *pat, 
+		    int len, int max, FontNamesPtr names)
+{
+    CataloguePtr cat = fpe->private;
+    FontPathElementPtr subfpe;
+    FontDirectoryPtr dir;
+    int i;
+
+    for (i = 0; i < cat->fpeCount; i++)
+    {
+	subfpe = cat->fpeList[i];
+	dir = subfpe->private;
+	FontFileListFonts(client, subfpe, pat, len, max, names);
+    }
+
+    return Successful;
+}
+
+int
+FontFileStartListFonts(pointer client, FontPathElementPtr fpe, 
+		       char *pat, int len, int max, 
+		       pointer *privatep, int mark_aliases);
+
+typedef struct _LFWIData {
+    pointer		*privates;
+    int			current;
+} LFWIDataRec, *LFWIDataPtr;
+
+static int
+CatalogueStartListFonts(pointer client, FontPathElementPtr fpe, 
+			char *pat, int len, int max, pointer *privatep,
+			int mark_aliases)
+{
+    CataloguePtr	cat = fpe->private;
+    LFWIDataPtr		data;
+    int			ret, i, j;
+
+    data = (LFWIDataPtr) xalloc (sizeof *data +
+				 sizeof data->privates[0] * cat->fpeCount);
+    if (!data)
+	return AllocError;
+    data->privates = (pointer *) (data + 1);
+
+    for (i = 0; i < cat->fpeCount; i++)
+    {
+	ret = FontFileStartListFonts(client, cat->fpeList[i], pat, len,
+				     max, &data->privates[i], mark_aliases);
+	if (ret != Successful)
+	    goto bail;
+    }
+
+    data->current = 0;
+    *privatep = (pointer) data;
+    return Successful;
+
+ bail:
+    for (j = 0; j < i; j++)
+	/* FIXME: we have no way to free the per-fpe privates. */;
+    xfree (data);
+
+    return AllocError;
+}
+
+static int
+CatalogueStartListFontsWithInfo(pointer client, FontPathElementPtr fpe, 
+				char *pat, int len, int max, 
+				pointer *privatep)
+{
+    return CatalogueStartListFonts(client, fpe, pat, len, max, privatep, 0);
+}
+
+static int
+CatalogueListNextFontWithInfo(pointer client, FontPathElementPtr fpe, 
+			      char **namep, int *namelenp, 
+			      FontInfoPtr *pFontInfo,
+			      int *numFonts, pointer private)
+{
+    LFWIDataPtr		data = private;
+    CataloguePtr	cat = fpe->private;
+    int			ret;
+
+    if (data->current == cat->fpeCount)
+    {
+	xfree(data);
+	return BadFontName;
+    }
+
+    ret = FontFileListNextFontWithInfo(client, cat->fpeList[data->current],
+				       namep, namelenp,
+				       pFontInfo, numFonts,
+				       data->privates[data->current]);
+    if (ret == BadFontName)
+    {
+	data->current++;
+	return CatalogueListNextFontWithInfo(client, fpe, namep, namelenp,
+					     pFontInfo, numFonts, private);
+    }
+
+    return ret;
+}
+
+static int
+CatalogueStartListFontsAndAliases(pointer client, FontPathElementPtr fpe, 
+				  char *pat, int len, int max, 
+				  pointer *privatep)
+{
+    return CatalogueStartListFonts(client, fpe, pat, len, max, privatep, 1);
+}
+
+static int
+CatalogueListNextFontOrAlias(pointer client, FontPathElementPtr fpe, 
+			     char **namep, int *namelenp, char **resolvedp,
+			     int *resolvedlenp, pointer private)
+{
+    LFWIDataPtr		data = private;
+    CataloguePtr	cat = fpe->private;
+    int			ret;
+
+    if (data->current == cat->fpeCount)
+    {
+	xfree(data);
+	return BadFontName;
+    }
+
+    ret = FontFileListNextFontOrAlias(client, cat->fpeList[data->current],
+				      namep, namelenp,
+				      resolvedp, resolvedlenp,
+				      data->privates[data->current]);
+    if (ret == BadFontName)
+    {
+	data->current++;
+	return CatalogueListNextFontOrAlias(client, fpe, namep, namelenp,
+					    resolvedp, resolvedlenp, private);
+    }
+
+    return ret;
+}
+
+void
+CatalogueRegisterLocalFpeFunctions (void)
+{
+    RegisterFPEFunctions(CatalogueNameCheck,
+			 CatalogueInitFPE,
+			 CatalogueFreeFPE,
+			 CatalogueResetFPE,
+			 CatalogueOpenFont,
+			 CatalogueCloseFont,
+			 CatalogueListFonts,
+			 CatalogueStartListFontsWithInfo,
+			 CatalogueListNextFontWithInfo,
+			 NULL,
+			 NULL,
+			 NULL,
+			 CatalogueStartListFontsAndAliases,
+			 CatalogueListNextFontOrAlias,
+			 FontFileEmptyBitmapSource);
+}
diff --git a/src/fontfile/fontfile.c b/src/fontfile/fontfile.c
index 914f8cd..f900f75 100644
--- a/src/fontfile/fontfile.c
+++ b/src/fontfile/fontfile.c
@@ -795,9 +795,9 @@ FontFileListFonts (pointer client, FontPathElementPtr fpe, char *pat,
 }
 
 int
-FontFileStartListFontsWithInfo(pointer client, FontPathElementPtr fpe, 
-			       char *pat, int len, int max, 
-			       pointer *privatep)
+FontFileStartListFonts(pointer client, FontPathElementPtr fpe, 
+		       char *pat, int len, int max, 
+		       pointer *privatep, int mark_aliases)
 {
     LFWIDataPtr	data;
     int		ret;
@@ -811,7 +811,8 @@ FontFileStartListFontsWithInfo(pointer client, FontPathElementPtr fpe,
 	xfree (data);
 	return AllocError;
     }
-    ret = FontFileListFonts (client, fpe, pat, len, max, data->names);
+    ret = _FontFileListFonts (client, fpe, pat, len,
+			      max, data->names, mark_aliases);
     if (ret != Successful)
     {
 	FreeFontNames (data->names);
@@ -823,6 +824,15 @@ FontFileStartListFontsWithInfo(pointer client, FontPathElementPtr fpe,
     return Successful;
 }
 
+
+int
+FontFileStartListFontsWithInfo(pointer client, FontPathElementPtr fpe, 
+			       char *pat, int len, int max, 
+			       pointer *privatep)
+{
+    return FontFileStartListFonts(client, fpe, pat, len, max, privatep, 0);
+}
+
 /* ARGSUSED */
 static int
 FontFileListOneFontWithInfo (pointer client, FontPathElementPtr fpe, 
@@ -1076,28 +1086,7 @@ FontFileStartListFontsAndAliases(pointer client, FontPathElementPtr fpe,
 				 char *pat, int len, int max, 
 				 pointer *privatep)
 {
-    LFWIDataPtr	data;
-    int		ret;
-
-    data = (LFWIDataPtr) xalloc (sizeof *data);
-    if (!data)
-	return AllocError;
-    data->names = MakeFontNamesRecord (0);
-    if (!data->names)
-    {
-	xfree (data);
-	return AllocError;
-    }
-    ret = _FontFileListFonts (client, fpe, pat, len, max, data->names, 1);
-    if (ret != Successful)
-    {
-	FreeFontNames (data->names);
-	xfree (data);
-	return ret;
-    }
-    data->current = 0;
-    *privatep = (pointer) data;
-    return Successful;
+    return FontFileStartListFonts(client, fpe, pat, len, max, privatep, 1);
 }
 
 int
diff --git a/src/fontfile/register.c b/src/fontfile/register.c
index 53016b2..7969dde 100644
--- a/src/fontfile/register.c
+++ b/src/fontfile/register.c
@@ -99,5 +99,6 @@ FontFileRegisterFpeFunctions(void)
 #endif
     
     FontFileRegisterLocalFpeFunctions ();
+    CatalogueRegisterLocalFpeFunctions ();
 }
 
-- 
1.5.2.GIT




More information about the xorg mailing list