summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2007-06-19 10:38:02 -0400
committerKristian Høgsberg <krh@redhat.com>2007-06-21 17:41:42 -0400
commitc5ab59762c4ad5def68436d55937a2bd558d5c99 (patch)
tree254f549fa0bd8c62de119e58b94ee00e93acb917
parent1a690feaf7c416da9b01861af381d15a661e5f52 (diff)
Add a new 'catalogue' FPE, which takes font paths from symlinks in a dir.
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.
-rw-r--r--include/X11/fonts/fntfil.h4
-rw-r--r--src/fontfile/Makefile.am3
-rw-r--r--src/fontfile/catalogue.c457
-rw-r--r--src/fontfile/fontfile.c41
-rw-r--r--src/fontfile/register.c1
5 files changed, 479 insertions, 27 deletions
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..6d364a5
--- /dev/null
+++ b/src/fontfile/catalogue.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright © 2007 Red Hat, Inc
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Author:
+ * Kristian Høgsberg <krh@redhat.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <X11/fonts/fntfilst.h>
+#include <sys/types.h>
+#include <sys/stat.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 {
+ time_t mtime;
+ 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 void
+CatalogueUnrefFPEs (FontPathElementPtr fpe)
+{
+ CataloguePtr cat = fpe->private;
+ FontPathElementPtr subfpe;
+ int i;
+
+ for (i = 0; i < cat->fpeCount; i++)
+ {
+ subfpe = cat->fpeList[i];
+ subfpe->refcount--;
+ if (subfpe->refcount == 0)
+ {
+ FontFileFreeFPE (subfpe);
+ xfree(subfpe->name);
+ xfree(subfpe);
+ }
+ }
+
+ cat->fpeCount = 0;
+}
+
+static int
+CatalogueRescan (FontPathElementPtr fpe)
+{
+ CataloguePtr cat = fpe->private;
+ char link[MAXFONTFILENAMELEN];
+ char dest[MAXFONTFILENAMELEN];
+ char *attrib;
+ FontPathElementPtr subfpe;
+ struct stat statbuf;
+ const char *path;
+ DIR *dir;
+ struct dirent *entry;
+ int len;
+
+ path = fpe->name + strlen(CataloguePrefix);
+ if (stat(path, &statbuf) < 0 || !S_ISDIR(statbuf.st_mode))
+ return BadFontPath;
+
+ if (statbuf.st_mtime <= cat->mtime)
+ return Successful;
+
+ dir = opendir(path);
+ if (dir == NULL)
+ {
+ xfree(cat);
+ return BadFontPath;
+ }
+
+ CatalogueUnrefFPEs (fpe);
+ 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);
+ 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 = xalloc (len + 1);
+ if (subfpe == NULL)
+ {
+ xfree(subfpe);
+ continue;
+ }
+
+ 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->name);
+ xfree(subfpe);
+ continue;
+ }
+
+ if (CatalogueAddFPE(cat, subfpe) != Successful)
+ {
+ FontFileFreeFPE (subfpe);
+ xfree(subfpe);
+ continue;
+ }
+ }
+
+ qsort(cat->fpeList,
+ cat->fpeCount, sizeof cat->fpeList[0], ComparePriority);
+
+ cat->mtime = statbuf.st_mtime;
+
+ return Successful;
+}
+
+static int
+CatalogueInitFPE (FontPathElementPtr fpe)
+{
+ CataloguePtr cat;
+
+ cat = (CataloguePtr) xalloc(sizeof *cat);
+ if (cat == NULL)
+ return AllocError;
+
+ fpe->private = (pointer) cat;
+ cat->fpeCount = 0;
+ cat->fpeAlloc = 0;
+ cat->fpeList = NULL;
+ cat->mtime = 0;
+
+ return CatalogueRescan (fpe);
+}
+
+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;
+
+ /* If the catalogue is modified while the xserver has fonts open
+ * from the previous subfpes, we'll unref the old subfpes when we
+ * reload the catalogue, and the xserver will the call FreeFPE on
+ * them once it drops its last reference. Thus, the FreeFPE call
+ * for the subfpe ends up here and we just forward it to
+ * FontFileFreeFPE. */
+
+ if (!CatalogueNameCheck (fpe->name))
+ return FontFileFreeFPE (fpe);
+
+ CatalogueUnrefFPEs (fpe);
+ 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;
+
+ CatalogueRescan (fpe);
+
+ 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;
+
+ CatalogueRescan (fpe);
+
+ 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;
+
+ CatalogueRescan (fpe);
+
+ 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 a591838..3dc7ef0 100644
--- a/src/fontfile/register.c
+++ b/src/fontfile/register.c
@@ -119,5 +119,6 @@ FontFileRegisterFpeFunctions(void)
}
FontFileRegisterLocalFpeFunctions ();
+ CatalogueRegisterLocalFpeFunctions ();
}