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

Ademar de Souza Reis Jr. ademar at mandriva.com.br
Tue Jun 19 14:40:58 PDT 2007


Good work!

After an initial test/review everything looks fine. I'll add it
to our package to get additional tests. Do you know if someone is
working on adding support for catalogue's dir into chkfontpath?
:-)

Thanks,
  - Ademar

On Tue, Jun 19, 2007 at 11:00:05AM -0400, Kristian Høgsberg wrote:
> 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
> 

-- 
Ademar de Souza Reis Jr.
Mandriva - http://www.mandriva.com.br

^[:wq!



More information about the xorg mailing list