summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/fontconfig-user.sgml15
-rw-r--r--fonts.dtd11
-rw-r--r--src/fcxml.c279
3 files changed, 184 insertions, 121 deletions
diff --git a/doc/fontconfig-user.sgml b/doc/fontconfig-user.sgml
index 92e3e5a..f083394 100644
--- a/doc/fontconfig-user.sgml
+++ b/doc/fontconfig-user.sgml
@@ -310,15 +310,9 @@ following structure:
This is the top level element for a font configuration and can contain
<literal>&lt;dir&gt;</literal>, <literal>&lt;cachedir&gt;</literal>, <literal>&lt;include&gt;</literal>, <literal>&lt;match&gt;</literal> and <literal>&lt;alias&gt;</literal> elements in any order.
</para></refsect2>
- <refsect2><title><literal>&lt;dir prefix="default" map=""&gt;</literal></title><para>
+ <refsect2><title><literal>&lt;dir prefix="default"&gt;</literal></title><para>
This element contains a directory name which will be scanned for font files
to include in the set of available fonts. If 'prefix' is set to "default" or "cwd", the current working directory will be added as the path prefix prior to the value. If 'prefix' is set to "xdg", the value in the XDG_DATA_HOME environment variable will be added as the path prefix. please see XDG Base Directory Specification for more details. If 'prefix' is set to "relative", the path of current file will be added prior to the value.
-</para><para>
-If a 'map' attribute is specified, its value will replace the
-directory path when matching cached information for fonts contained in
-this directory. This is useful if the directory name is an alias
-(via a bind mount or symlink) to another directory in the system for
-which cached font information is likely to exist.
</para></refsect2>
<refsect2><title><literal>&lt;cachedir prefix="default"&gt;</literal></title><para>
This element contains a directory name that is supposed to be stored or read
@@ -358,6 +352,13 @@ Unicode characters which is supposed to be blank in an <literal>&lt;int&gt;</lit
Characters outside of this set which are drawn as blank will be elided from
the set of characters supported by the font.
</para></refsect2>
+ <refsect2><title><literal>&lt;remap-dir prefix="default" as-path=""&lt;</literal></title><para>
+This element contains a directory name where will be mapped
+as the path 'as-path' in cached information.
+This is useful if the directory name is an alias
+(via a bind mount or symlink) to another directory in the system for
+which cached font information is likely to exist.
+ </para></refsect2>
<refsect2><title><literal>&lt;rescan&gt;</literal></title><para>
The <literal>&lt;rescan&gt;</literal> element holds an <literal>&lt;int&gt;</literal> element which indicates the default
interval between automatic checks for font configuration changes.
diff --git a/fonts.dtd b/fonts.dtd
index 8a95fa5..2323c46 100644
--- a/fonts.dtd
+++ b/fonts.dtd
@@ -7,6 +7,7 @@
dir |
include |
match |
+ remap-dir |
selectfont)* >
<!--
@@ -14,7 +15,6 @@
-->
<!ELEMENT dir (#PCDATA)>
<!ATTLIST dir
- map CDATA #IMPLIED
prefix (default|xdg|relative|cwd) "default"
xml:space (default|preserve) 'preserve'>
@@ -110,6 +110,15 @@
</edit>
</match>
-->
+
+<!--
+ Map a font path as the path "as-path"
+-->
+<!ELEMENT remap-dir
+ as-path CDATA #REQUIRED
+ prefix (default|xdg|relative|cwd) "default"
+ xml:space (default|preserve) "preserve">
+
<!--
Periodically rescan the font configuration and
directories to synch internal state with filesystem
diff --git a/src/fcxml.c b/src/fcxml.c
index c2ad723..856400f 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -358,6 +358,7 @@ typedef enum _FcElement {
FcElementMatch,
FcElementAlias,
FcElementDescription,
+ FcElementRemapDir,
FcElementRescan,
@@ -421,6 +422,7 @@ static const struct {
{ "match", FcElementMatch },
{ "alias", FcElementAlias },
{ "description", FcElementDescription },
+ { "remap-dir", FcElementRemapDir },
{ "rescan", FcElementRescan },
@@ -490,6 +492,19 @@ FcElementMap (const XML_Char *name)
return FcElementUnknown;
}
+static const char *
+FcElementReverseMap (FcElement e)
+{
+ int i;
+
+ for (i = 0; i < NUM_ELEMENT_MAPS; i++)
+ if (fcElementMap[i].element == e)
+ return fcElementMap[i].name;
+
+ return NULL;
+}
+
+
typedef struct _FcPStack {
struct _FcPStack *prev;
FcElement element;
@@ -1265,6 +1280,112 @@ FcConfigGetAttribute (FcConfigParse *parse, const char *attr)
return 0;
}
+static FcChar8 *
+_get_real_path_from_prefix(FcConfigParse *parse, const FcChar8 *path, const FcChar8 *prefix)
+{
+#ifdef _WIN32
+ const FcChar8 *data;
+ FcChar8 buffer[1000];
+#endif
+ FcChar8 *parent = NULL, *retval = NULL;
+
+ if (prefix)
+ {
+ if (FcStrCmp (prefix, (const FcChar8 *) "xdg") == 0)
+ {
+ parent = FcConfigXdgDataHome ();
+ if (!parent)
+ {
+ /* Home directory might be disabled */
+ return NULL;
+ }
+ }
+ else if (FcStrCmp (prefix, (const FcChar8 *) "default") == 0 ||
+ FcStrCmp (prefix, (const FcChar8 *) "cwd") == 0)
+ {
+ /* Nothing to do */
+ }
+ else if (FcStrCmp (prefix, (const FcChar8 *) "relative") == 0)
+ {
+ parent = FcStrDirname (parse->name);
+ if (!parent)
+ return NULL;
+ }
+ }
+#ifndef _WIN32
+ /* For Win32, check this later for dealing with special cases */
+ else
+ {
+ if (!FcStrIsAbsoluteFilename (path) && path[0] != '~')
+ FcConfigMessage (parse, FcSevereWarning, "Use of ambiguous path in <%s> element. please add prefix=\"cwd\" if current behavior is desired.", FcElementReverseMap (parse->pstack->element));
+ }
+#endif
+ if (parent)
+ {
+ retval = FcStrBuildFilename (parent, path, NULL);
+ }
+ else
+ {
+ retval = FcStrdup (path);
+ }
+#ifdef _WIN32
+ if (strcmp ((const char *) path, "CUSTOMFONTDIR") == 0)
+ {
+ FcChar8 *p;
+ data = buffer;
+ if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
+ {
+ FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
+ goto bail;
+ }
+ /*
+ * Must use the multi-byte aware function to search
+ * for backslash because East Asian double-byte code
+ * pages have characters with backslash as the second
+ * byte.
+ */
+ p = _mbsrchr (data, '\\');
+ if (p) *p = '\0';
+ strcat ((char *) data, "\\fonts");
+ }
+ else if (strcmp ((const char *) path, "APPSHAREFONTDIR") == 0)
+ {
+ FcChar8 *p;
+ data = buffer;
+ if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
+ {
+ FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
+ goto bail;
+ }
+ p = _mbsrchr (data, '\\');
+ if (p) *p = '\0';
+ strcat ((char *) data, "\\..\\share\\fonts");
+ }
+ else if (strcmp ((const char *) path, "WINDOWSFONTDIR") == 0)
+ {
+ int rc;
+ data = buffer;
+ rc = pGetSystemWindowsDirectory ((LPSTR) buffer, sizeof (buffer) - 20);
+ if (rc == 0 || rc > sizeof (buffer) - 20)
+ {
+ FcConfigMessage (parse, FcSevereError, "GetSystemWindowsDirectory failed");
+ goto bail;
+ }
+ if (data [strlen ((const char *) data) - 1] != '\\')
+ strcat ((char *) data, "\\");
+ strcat ((char *) data, "fonts");
+ }
+ else if (!prefix)
+ {
+ if (!FcStrIsAbsoluteFilename (path) && path[0] != '~')
+ FcConfigMessage (parse, FcSevereWarning, "Use of ambiguous path in <%s> element. please add prefix=\"cwd\" if current behavior is desired.", FcElementReverseMap (parse->pstack->element));
+ }
+ retval = FcStrdup (data);
+#endif
+
+ return retval;
+}
+
static void
FcStartElement(void *userData, const XML_Char *name, const XML_Char **attr)
{
@@ -1931,6 +2052,39 @@ FcParseDescription (FcConfigParse *parse)
FcStrFree (desc);
}
+static void
+FcParseRemapDir (FcConfigParse *parse)
+{
+ const FcChar8 *path, *attr, *data;
+ FcChar8 *prefix = NULL;
+
+ data = FcStrBufDoneStatic (&parse->pstack->str);
+ if (!data)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ return;
+ }
+ path = FcConfigGetAttribute (parse, "as-path");
+ if (!path)
+ {
+ FcConfigMessage (parse, FcSevereWarning, "Missing as-path in remap-dir");
+ return;
+ }
+ attr = FcConfigGetAttribute (parse, "prefix");
+ prefix = _get_real_path_from_prefix (parse, data, attr);
+ if (!prefix || prefix[0] == 0)
+ FcConfigMessage (parse, FcSevereWarning, "empty font directory name for remap ignored");
+ else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
+ {
+ if (!FcConfigAddFontDir (parse->config, prefix, path))
+ FcConfigMessage (parse, FcSevereError, "out of memory; cannot create remap data for %s as %s", prefix, path);
+ }
+ FcStrBufDestroy (&parse->pstack->str);
+
+ if (prefix)
+ FcStrFree (prefix);
+}
+
static FcExpr *
FcPopExpr (FcConfigParse *parse)
{
@@ -2071,130 +2225,26 @@ FcParseUnary (FcConfigParse *parse, FcOp op)
static void
FcParseDir (FcConfigParse *parse)
{
- const FcChar8 *attr, *data, *map;
- FcChar8 *prefix = NULL, *p;
-#ifdef _WIN32
- FcChar8 buffer[1000];
-#endif
+ const FcChar8 *attr, *data;
+ FcChar8 *prefix = NULL;
- attr = FcConfigGetAttribute (parse, "prefix");
- map = FcConfigGetAttribute (parse, "map");
data = FcStrBufDoneStatic (&parse->pstack->str);
- if (attr)
- {
- if (FcStrCmp (attr, (const FcChar8 *)"xdg") == 0)
- {
- prefix = FcConfigXdgDataHome ();
- /* home directory might be disabled.
- * simply ignore this element.
- */
- if (!prefix)
- goto bail;
- }
- else if (FcStrCmp (attr, (const FcChar8 *)"default") == 0 || FcStrCmp (attr, (const FcChar8 *)"cwd") == 0)
- {
- }
- else if (FcStrCmp (attr, (const FcChar8 *)"relative") == 0)
- {
- prefix = FcStrDirname (parse->name);
- if (!prefix)
- goto bail;
- }
- }
-#ifndef _WIN32
- /* For Win32, check this later for dealing with special cases */
- else
- {
- if (!FcStrIsAbsoluteFilename (data) && data[0] != '~')
- FcConfigMessage (parse, FcSevereWarning, "Use of ambiguous <dir> element. please add prefix=\"cwd\" if current behavior is desired.");
- }
-#endif
if (!data)
{
FcConfigMessage (parse, FcSevereError, "out of memory");
- data = prefix;
- goto bail;
- }
- if (prefix)
- {
- size_t plen = strlen ((const char *)prefix);
- size_t dlen = strlen ((const char *)data);
-
- p = realloc (prefix, plen + 1 + dlen + 1);
- if (!p)
- {
- FcConfigMessage (parse, FcSevereError, "out of memory");
- goto bail;
- }
- prefix = p;
- prefix[plen] = FC_DIR_SEPARATOR;
- memcpy (&prefix[plen + 1], data, dlen);
- prefix[plen + 1 + dlen] = 0;
- data = prefix;
- }
-#ifdef _WIN32
- if (strcmp ((const char *) data, "CUSTOMFONTDIR") == 0)
- {
- FcChar8 *p;
- data = buffer;
- if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
- {
- FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
- goto bail;
- }
- /*
- * Must use the multi-byte aware function to search
- * for backslash because East Asian double-byte code
- * pages have characters with backslash as the second
- * byte.
- */
- p = _mbsrchr (data, '\\');
- if (p) *p = '\0';
- strcat ((char *) data, "\\fonts");
- }
- else if (strcmp ((const char *) data, "APPSHAREFONTDIR") == 0)
- {
- FcChar8 *p;
- data = buffer;
- if (!GetModuleFileName (NULL, (LPCH) buffer, sizeof (buffer) - 20))
- {
- FcConfigMessage (parse, FcSevereError, "GetModuleFileName failed");
- goto bail;
- }
- p = _mbsrchr (data, '\\');
- if (p) *p = '\0';
- strcat ((char *) data, "\\..\\share\\fonts");
- }
- else if (strcmp ((const char *) data, "WINDOWSFONTDIR") == 0)
- {
- int rc;
- data = buffer;
- rc = pGetSystemWindowsDirectory ((LPSTR) buffer, sizeof (buffer) - 20);
- if (rc == 0 || rc > sizeof (buffer) - 20)
- {
- FcConfigMessage (parse, FcSevereError, "GetSystemWindowsDirectory failed");
- goto bail;
- }
- if (data [strlen ((const char *) data) - 1] != '\\')
- strcat ((char *) data, "\\");
- strcat ((char *) data, "fonts");
- }
- else if (!attr)
- {
- if (!FcStrIsAbsoluteFilename (data) && data[0] != '~')
- FcConfigMessage (parse, FcSevereWarning, "Use of ambiguous <dir> element. please add prefix=\"cwd\" if current behavior is desired.");
+ return;
}
-#endif
- if (strlen ((char *) data) == 0)
+ attr = FcConfigGetAttribute (parse, "prefix");
+ prefix = _get_real_path_from_prefix (parse, data, attr);
+ if (!prefix || prefix[0] == 0)
FcConfigMessage (parse, FcSevereWarning, "empty font directory name ignored");
- else if (!parse->scanOnly && (!FcStrUsesHome (data) || FcConfigHome ()))
+ else if (!parse->scanOnly && (!FcStrUsesHome (prefix) || FcConfigHome ()))
{
- if (!FcConfigAddFontDir (parse->config, data, map))
- FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", data);
+ if (!FcConfigAddFontDir (parse->config, prefix, NULL))
+ FcConfigMessage (parse, FcSevereError, "out of memory; cannot add directory %s", prefix);
}
FcStrBufDestroy (&parse->pstack->str);
- bail:
if (prefix)
FcStrFree (prefix);
}
@@ -3012,6 +3062,9 @@ FcEndElement(void *userData, const XML_Char *name FC_UNUSED)
case FcElementDescription:
FcParseDescription (parse);
break;
+ case FcElementRemapDir:
+ FcParseRemapDir (parse);
+ break;
case FcElementRescan:
FcParseRescan (parse);