Add new element remap-dir instead of extending dir element

This commit is contained in:
Akira TAGOH 2019-01-28 09:59:29 +00:00
parent 9d3fb5b385
commit a563a1802e
3 changed files with 184 additions and 121 deletions

View File

@ -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
@ -357,6 +351,13 @@ drawn as blanks on the screen. Within the <literal>&lt;blank&gt;</literal> elem
Unicode characters which is supposed to be blank in an <literal>&lt;int&gt;</literal> element.
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

View File

@ -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

View File

@ -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;
return;
}
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.");
}
#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);