2002-02-15 00:34:13 +01:00
|
|
|
/*
|
2008-08-12 22:34:24 +02:00
|
|
|
* fontconfig/src/fccfg.c
|
2002-02-15 00:34:13 +01:00
|
|
|
*
|
2004-12-07 02:14:46 +01:00
|
|
|
* Copyright © 2000 Keith Packard
|
2002-02-15 00:34:13 +01:00
|
|
|
*
|
|
|
|
* 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 Keith Packard not be used in
|
|
|
|
* advertising or publicity pertaining to distribution of the software without
|
|
|
|
* specific, written prior permission. Keith Packard makes no
|
|
|
|
* representations about the suitability of this software for any purpose. It
|
|
|
|
* is provided "as is" without express or implied warranty.
|
|
|
|
*
|
2009-03-12 21:00:08 +01:00
|
|
|
* THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
2002-02-15 00:34:13 +01:00
|
|
|
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
2009-03-12 21:00:08 +01:00
|
|
|
* EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
2002-02-15 00:34:13 +01:00
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2006-04-25 07:57:41 +02:00
|
|
|
#include "fcint.h"
|
2006-01-26 17:09:12 +01:00
|
|
|
#include <dirent.h>
|
|
|
|
#include <sys/types.h>
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2003-06-16 00:45:12 +02:00
|
|
|
#if defined (_WIN32) && (defined (PIC) || defined (DLL_EXPORT))
|
2003-03-22 22:25:34 +01:00
|
|
|
#define STRICT
|
|
|
|
#include <windows.h>
|
|
|
|
#undef STRICT
|
|
|
|
#endif
|
|
|
|
|
2003-06-14 01:04:35 +02:00
|
|
|
#if defined (_WIN32) && !defined (R_OK)
|
|
|
|
#define R_OK 4
|
|
|
|
#endif
|
|
|
|
|
2002-02-19 09:33:23 +01:00
|
|
|
FcConfig *_fcConfig;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
|
|
FcConfig *
|
|
|
|
FcConfigCreate (void)
|
|
|
|
{
|
|
|
|
FcSetName set;
|
|
|
|
FcConfig *config;
|
|
|
|
|
|
|
|
config = malloc (sizeof (FcConfig));
|
|
|
|
if (!config)
|
|
|
|
goto bail0;
|
2002-05-21 19:06:22 +02:00
|
|
|
FcMemAlloc (FC_MEM_CONFIG, sizeof (FcConfig));
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
config->configDirs = FcStrSetCreate ();
|
|
|
|
if (!config->configDirs)
|
2002-02-15 00:34:13 +01:00
|
|
|
goto bail1;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
config->configFiles = FcStrSetCreate ();
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!config->configFiles)
|
|
|
|
goto bail2;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
config->fontDirs = FcStrSetCreate ();
|
|
|
|
if (!config->fontDirs)
|
|
|
|
goto bail3;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2003-05-07 18:13:24 +02:00
|
|
|
config->acceptGlobs = FcStrSetCreate ();
|
|
|
|
if (!config->acceptGlobs)
|
|
|
|
goto bail4;
|
|
|
|
|
|
|
|
config->rejectGlobs = FcStrSetCreate ();
|
|
|
|
if (!config->rejectGlobs)
|
|
|
|
goto bail5;
|
|
|
|
|
2004-12-04 20:41:10 +01:00
|
|
|
config->acceptPatterns = FcFontSetCreate ();
|
|
|
|
if (!config->acceptPatterns)
|
|
|
|
goto bail6;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2004-12-04 20:41:10 +01:00
|
|
|
config->rejectPatterns = FcFontSetCreate ();
|
|
|
|
if (!config->rejectPatterns)
|
|
|
|
goto bail7;
|
|
|
|
|
2006-08-04 18:13:00 +02:00
|
|
|
config->cacheDirs = FcStrSetCreate ();
|
|
|
|
if (!config->cacheDirs)
|
2006-08-31 06:59:53 +02:00
|
|
|
goto bail8;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
config->blanks = 0;
|
|
|
|
|
|
|
|
config->substPattern = 0;
|
|
|
|
config->substFont = 0;
|
2006-09-03 05:07:29 +02:00
|
|
|
config->substScan = 0;
|
2002-02-15 00:34:13 +01:00
|
|
|
config->maxObjects = 0;
|
|
|
|
for (set = FcSetSystem; set <= FcSetApplication; set++)
|
|
|
|
config->fonts[set] = 0;
|
2002-05-21 19:06:22 +02:00
|
|
|
|
|
|
|
config->rescanTime = time(0);
|
2010-04-12 18:18:50 +02:00
|
|
|
config->rescanInterval = 30;
|
2008-08-23 00:08:07 +02:00
|
|
|
|
2009-06-06 04:32:31 +02:00
|
|
|
config->expr_pool = NULL;
|
|
|
|
|
2008-08-23 00:08:07 +02:00
|
|
|
config->ref = 1;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
return config;
|
|
|
|
|
2004-12-04 20:41:10 +01:00
|
|
|
bail8:
|
|
|
|
FcFontSetDestroy (config->rejectPatterns);
|
|
|
|
bail7:
|
|
|
|
FcFontSetDestroy (config->acceptPatterns);
|
2003-05-07 18:13:24 +02:00
|
|
|
bail6:
|
|
|
|
FcStrSetDestroy (config->rejectGlobs);
|
|
|
|
bail5:
|
|
|
|
FcStrSetDestroy (config->acceptGlobs);
|
2002-05-21 19:06:22 +02:00
|
|
|
bail4:
|
|
|
|
FcStrSetDestroy (config->fontDirs);
|
2002-02-15 00:34:13 +01:00
|
|
|
bail3:
|
2002-05-21 19:06:22 +02:00
|
|
|
FcStrSetDestroy (config->configFiles);
|
2002-02-15 00:34:13 +01:00
|
|
|
bail2:
|
2002-05-21 19:06:22 +02:00
|
|
|
FcStrSetDestroy (config->configDirs);
|
2002-02-15 00:34:13 +01:00
|
|
|
bail1:
|
|
|
|
free (config);
|
2002-05-21 19:06:22 +02:00
|
|
|
FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
|
2002-02-15 00:34:13 +01:00
|
|
|
bail0:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-06-21 08:14:45 +02:00
|
|
|
static FcFileTime
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigNewestFile (FcStrSet *files)
|
|
|
|
{
|
|
|
|
FcStrList *list = FcStrListCreate (files);
|
2002-06-21 08:14:45 +02:00
|
|
|
FcFileTime newest = { 0, FcFalse };
|
2002-05-21 19:06:22 +02:00
|
|
|
FcChar8 *file;
|
|
|
|
struct stat statb;
|
|
|
|
|
|
|
|
if (list)
|
|
|
|
{
|
|
|
|
while ((file = FcStrListNext (list)))
|
2008-12-28 10:06:01 +01:00
|
|
|
if (FcStat ((char *) file, &statb) == 0)
|
2002-06-21 08:14:45 +02:00
|
|
|
if (!newest.set || statb.st_mtime - newest.time > 0)
|
2004-02-07 08:13:48 +01:00
|
|
|
{
|
|
|
|
newest.set = FcTrue;
|
2002-06-21 08:14:45 +02:00
|
|
|
newest.time = statb.st_mtime;
|
2004-02-07 08:13:48 +01:00
|
|
|
}
|
2002-05-21 19:06:22 +02:00
|
|
|
FcStrListDone (list);
|
|
|
|
}
|
|
|
|
return newest;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcConfigUptoDate (FcConfig *config)
|
|
|
|
{
|
2007-10-26 06:23:36 +02:00
|
|
|
FcFileTime config_time, config_dir_time, font_time;
|
2002-06-21 08:14:45 +02:00
|
|
|
time_t now = time(0);
|
2002-05-21 19:06:22 +02:00
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
config_time = FcConfigNewestFile (config->configFiles);
|
2007-10-26 06:23:36 +02:00
|
|
|
config_dir_time = FcConfigNewestFile (config->configDirs);
|
2004-06-30 20:41:52 +02:00
|
|
|
font_time = FcConfigNewestFile (config->fontDirs);
|
2002-06-21 08:14:45 +02:00
|
|
|
if ((config_time.set && config_time.time - config->rescanTime > 0) ||
|
2007-10-26 06:23:36 +02:00
|
|
|
(config_dir_time.set && (config_dir_time.time - config->rescanTime) > 0) ||
|
2004-06-30 20:41:52 +02:00
|
|
|
(font_time.set && (font_time.time - config->rescanTime) > 0))
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
2008-05-25 01:15:27 +02:00
|
|
|
/* We need to check for potential clock problems here (OLPC ticket #6046) */
|
|
|
|
if ((config_time.set && (config_time.time - now) > 0) ||
|
|
|
|
(config_dir_time.set && (config_dir_time.time - now) > 0) ||
|
|
|
|
(font_time.set && (font_time.time - now) > 0))
|
|
|
|
{
|
|
|
|
fprintf (stderr,
|
|
|
|
"Fontconfig warning: Directory/file mtime in the future. New fonts may not be detected\n");
|
|
|
|
config->rescanTime = now;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return FcFalse;
|
2002-05-21 19:06:22 +02:00
|
|
|
}
|
|
|
|
config->rescanTime = now;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
static void
|
|
|
|
FcSubstDestroy (FcSubst *s)
|
|
|
|
{
|
|
|
|
FcSubst *n;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
while (s)
|
|
|
|
{
|
|
|
|
n = s->next;
|
2003-03-20 03:00:15 +01:00
|
|
|
if (s->test)
|
|
|
|
FcTestDestroy (s->test);
|
|
|
|
if (s->edit)
|
|
|
|
FcEditDestroy (s->edit);
|
2003-08-15 21:45:20 +02:00
|
|
|
free (s);
|
|
|
|
FcMemFree (FC_MEM_SUBST, sizeof (FcSubst));
|
2002-02-15 00:34:13 +01:00
|
|
|
s = n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExpr *
|
|
|
|
FcConfigAllocExpr (FcConfig *config)
|
|
|
|
{
|
|
|
|
if (!config->expr_pool || config->expr_pool->next == config->expr_pool->end)
|
|
|
|
{
|
|
|
|
FcExprPage *new_page;
|
|
|
|
|
|
|
|
new_page = malloc (sizeof (FcExprPage));
|
|
|
|
if (!new_page)
|
|
|
|
return 0;
|
|
|
|
FcMemAlloc (FC_MEM_EXPR, sizeof (FcExprPage));
|
|
|
|
|
|
|
|
new_page->next_page = config->expr_pool;
|
|
|
|
new_page->next = new_page->exprs;
|
|
|
|
config->expr_pool = new_page;
|
|
|
|
}
|
|
|
|
|
|
|
|
return config->expr_pool->next++;
|
|
|
|
}
|
|
|
|
|
2008-08-23 00:08:07 +02:00
|
|
|
FcConfig *
|
|
|
|
FcConfigReference (FcConfig *config)
|
|
|
|
{
|
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
config->ref++;
|
|
|
|
|
|
|
|
return config;
|
|
|
|
}
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
void
|
|
|
|
FcConfigDestroy (FcConfig *config)
|
|
|
|
{
|
|
|
|
FcSetName set;
|
2009-06-06 04:32:31 +02:00
|
|
|
FcExprPage *page;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2008-08-23 00:08:07 +02:00
|
|
|
if (--config->ref > 0)
|
|
|
|
return;
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
if (config == _fcConfig)
|
|
|
|
_fcConfig = 0;
|
|
|
|
|
|
|
|
FcStrSetDestroy (config->configDirs);
|
|
|
|
FcStrSetDestroy (config->fontDirs);
|
2006-08-04 18:13:00 +02:00
|
|
|
FcStrSetDestroy (config->cacheDirs);
|
2002-05-21 19:06:22 +02:00
|
|
|
FcStrSetDestroy (config->configFiles);
|
2003-05-07 18:13:24 +02:00
|
|
|
FcStrSetDestroy (config->acceptGlobs);
|
|
|
|
FcStrSetDestroy (config->rejectGlobs);
|
2004-12-04 20:41:10 +01:00
|
|
|
FcFontSetDestroy (config->acceptPatterns);
|
|
|
|
FcFontSetDestroy (config->rejectPatterns);
|
2002-05-21 19:06:22 +02:00
|
|
|
|
2003-08-15 21:45:20 +02:00
|
|
|
if (config->blanks)
|
|
|
|
FcBlanksDestroy (config->blanks);
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
FcSubstDestroy (config->substPattern);
|
|
|
|
FcSubstDestroy (config->substFont);
|
2006-09-03 05:07:29 +02:00
|
|
|
FcSubstDestroy (config->substScan);
|
2002-02-15 00:34:13 +01:00
|
|
|
for (set = FcSetSystem; set <= FcSetApplication; set++)
|
|
|
|
if (config->fonts[set])
|
|
|
|
FcFontSetDestroy (config->fonts[set]);
|
2003-08-15 21:45:20 +02:00
|
|
|
|
2009-06-06 04:32:31 +02:00
|
|
|
page = config->expr_pool;
|
|
|
|
while (page)
|
|
|
|
{
|
|
|
|
FcExprPage *next = page->next_page;
|
|
|
|
FcMemFree (FC_MEM_EXPR, sizeof (FcExprPage));
|
|
|
|
free (page);
|
|
|
|
page = next;
|
|
|
|
}
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
free (config);
|
|
|
|
FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2006-09-01 10:15:14 +02:00
|
|
|
* Add cache to configuration, adding fonts and directories
|
2002-02-15 00:34:13 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
FcBool
|
2010-04-12 18:18:50 +02:00
|
|
|
FcConfigAddCache (FcConfig *config, FcCache *cache,
|
2006-09-15 09:23:40 +02:00
|
|
|
FcSetName set, FcStrSet *dirSet)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2006-09-01 10:15:14 +02:00
|
|
|
FcFontSet *fs;
|
|
|
|
intptr_t *dirs;
|
|
|
|
int i;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2006-09-01 10:15:14 +02:00
|
|
|
/*
|
|
|
|
* Add fonts
|
|
|
|
*/
|
|
|
|
fs = FcCacheSet (cache);
|
|
|
|
if (fs)
|
2005-08-24 08:21:30 +02:00
|
|
|
{
|
2006-09-05 07:26:24 +02:00
|
|
|
int nref = 0;
|
|
|
|
|
2006-09-01 10:15:14 +02:00
|
|
|
for (i = 0; i < fs->nfont; i++)
|
2005-08-24 08:21:30 +02:00
|
|
|
{
|
2006-09-01 10:15:14 +02:00
|
|
|
FcPattern *font = FcFontSetFont (fs, i);
|
|
|
|
FcChar8 *font_file;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check to see if font is banned by filename
|
|
|
|
*/
|
|
|
|
if (FcPatternObjectGetString (font, FC_FILE_OBJECT,
|
|
|
|
0, &font_file) == FcResultMatch &&
|
|
|
|
!FcConfigAcceptFilename (config, font_file))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check to see if font is banned by pattern
|
|
|
|
*/
|
|
|
|
if (!FcConfigAcceptFont (config, font))
|
|
|
|
continue;
|
|
|
|
|
2006-09-05 07:26:24 +02:00
|
|
|
nref++;
|
2006-09-15 09:23:40 +02:00
|
|
|
FcFontSetAdd (config->fonts[set], font);
|
2005-08-24 08:21:30 +02:00
|
|
|
}
|
2006-09-05 07:26:24 +02:00
|
|
|
FcDirCacheReference (cache, nref);
|
2005-08-24 08:21:30 +02:00
|
|
|
}
|
2006-09-01 10:15:14 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Add directories
|
|
|
|
*/
|
|
|
|
dirs = FcCacheDirs (cache);
|
|
|
|
if (dirs)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2006-09-01 10:15:14 +02:00
|
|
|
for (i = 0; i < cache->dirs_count; i++)
|
|
|
|
{
|
|
|
|
FcChar8 *dir = FcOffsetToPtr (dirs, dirs[i], FcChar8);
|
|
|
|
if (FcConfigAcceptFilename (config, dir))
|
2006-09-15 09:23:40 +02:00
|
|
|
FcStrSetAddFilename (dirSet, dir);
|
2005-09-03 06:56:56 +02:00
|
|
|
}
|
2006-09-01 10:15:14 +02:00
|
|
|
}
|
|
|
|
return FcTrue;
|
|
|
|
}
|
2005-09-03 06:56:56 +02:00
|
|
|
|
2006-09-15 09:23:40 +02:00
|
|
|
static FcBool
|
|
|
|
FcConfigAddDirList (FcConfig *config, FcSetName set, FcStrSet *dirSet)
|
|
|
|
{
|
|
|
|
FcStrList *dirlist;
|
|
|
|
FcChar8 *dir;
|
|
|
|
FcCache *cache;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2006-09-15 09:23:40 +02:00
|
|
|
dirlist = FcStrListCreate (dirSet);
|
|
|
|
if (!dirlist)
|
|
|
|
return FcFalse;
|
|
|
|
|
|
|
|
while ((dir = FcStrListNext (dirlist)))
|
|
|
|
{
|
|
|
|
if (FcDebug () & FC_DBG_FONTSET)
|
|
|
|
printf ("adding fonts from%s\n", dir);
|
|
|
|
cache = FcDirCacheRead (dir, FcFalse, config);
|
|
|
|
if (!cache)
|
|
|
|
continue;
|
|
|
|
FcConfigAddCache (config, cache, set, dirSet);
|
|
|
|
FcDirCacheUnload (cache);
|
|
|
|
}
|
|
|
|
FcStrListDone (dirlist);
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2006-09-01 10:15:14 +02:00
|
|
|
/*
|
|
|
|
* Scan the current list of directories in the configuration
|
|
|
|
* and build the set of available fonts.
|
|
|
|
*/
|
2005-11-29 01:21:05 +01:00
|
|
|
|
2006-09-01 10:15:14 +02:00
|
|
|
FcBool
|
|
|
|
FcConfigBuildFonts (FcConfig *config)
|
|
|
|
{
|
|
|
|
FcFontSet *fonts;
|
2005-08-25 09:38:02 +02:00
|
|
|
|
2006-09-01 10:15:14 +02:00
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return FcFalse;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2006-09-01 10:15:14 +02:00
|
|
|
|
|
|
|
fonts = FcFontSetCreate ();
|
|
|
|
if (!fonts)
|
2006-09-15 09:23:40 +02:00
|
|
|
return FcFalse;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2006-09-01 10:15:14 +02:00
|
|
|
FcConfigSetFonts (config, fonts, FcSetSystem);
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2006-09-15 09:23:40 +02:00
|
|
|
if (!FcConfigAddDirList (config, FcSetSystem, config->fontDirs))
|
|
|
|
return FcFalse;
|
2002-02-15 00:34:13 +01:00
|
|
|
if (FcDebug () & FC_DBG_FONTSET)
|
|
|
|
FcFontSetPrint (fonts);
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcConfigSetCurrent (FcConfig *config)
|
|
|
|
{
|
2007-11-04 06:45:31 +01:00
|
|
|
if (config == _fcConfig)
|
|
|
|
return FcTrue;
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!config->fonts)
|
|
|
|
if (!FcConfigBuildFonts (config))
|
|
|
|
return FcFalse;
|
|
|
|
|
2002-02-19 09:33:23 +01:00
|
|
|
if (_fcConfig)
|
|
|
|
FcConfigDestroy (_fcConfig);
|
|
|
|
_fcConfig = config;
|
2002-02-15 00:34:13 +01:00
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcConfig *
|
|
|
|
FcConfigGetCurrent (void)
|
|
|
|
{
|
2002-02-19 09:33:23 +01:00
|
|
|
if (!_fcConfig)
|
|
|
|
if (!FcInit ())
|
|
|
|
return 0;
|
|
|
|
return _fcConfig;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigAddConfigDir (FcConfig *config,
|
|
|
|
const FcChar8 *d)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
return FcStrSetAddFilename (config->configDirs, d);
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
FcStrList *
|
|
|
|
FcConfigGetConfigDirs (FcConfig *config)
|
|
|
|
{
|
|
|
|
if (!config)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return 0;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-05-21 19:06:22 +02:00
|
|
|
return FcStrListCreate (config->configDirs);
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcConfigAddFontDir (FcConfig *config,
|
|
|
|
const FcChar8 *d)
|
|
|
|
{
|
|
|
|
return FcStrSetAddFilename (config->fontDirs, d);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
FcBool
|
|
|
|
FcConfigAddDir (FcConfig *config,
|
|
|
|
const FcChar8 *d)
|
|
|
|
{
|
2010-04-12 18:18:50 +02:00
|
|
|
return (FcConfigAddConfigDir (config, d) &&
|
2002-05-21 19:06:22 +02:00
|
|
|
FcConfigAddFontDir (config, d));
|
|
|
|
}
|
|
|
|
|
|
|
|
FcStrList *
|
|
|
|
FcConfigGetFontDirs (FcConfig *config)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return 0;
|
|
|
|
}
|
2002-05-21 19:06:22 +02:00
|
|
|
return FcStrListCreate (config->fontDirs);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2006-08-04 18:13:00 +02:00
|
|
|
FcBool
|
|
|
|
FcConfigAddCacheDir (FcConfig *config,
|
|
|
|
const FcChar8 *d)
|
|
|
|
{
|
|
|
|
return FcStrSetAddFilename (config->cacheDirs, d);
|
|
|
|
}
|
|
|
|
|
|
|
|
FcStrList *
|
|
|
|
FcConfigGetCacheDirs (FcConfig *config)
|
|
|
|
{
|
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return FcStrListCreate (config->cacheDirs);
|
|
|
|
}
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
FcBool
|
|
|
|
FcConfigAddConfigFile (FcConfig *config,
|
2002-02-15 07:01:28 +01:00
|
|
|
const FcChar8 *f)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcBool ret;
|
|
|
|
FcChar8 *file = FcConfigFilename (f);
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!file)
|
|
|
|
return FcFalse;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
ret = FcStrSetAdd (config->configFiles, file);
|
|
|
|
FcStrFree (file);
|
|
|
|
return ret;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
FcStrList *
|
2002-02-15 00:34:13 +01:00
|
|
|
FcConfigGetConfigFiles (FcConfig *config)
|
|
|
|
{
|
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return 0;
|
|
|
|
}
|
2002-05-21 19:06:22 +02:00
|
|
|
return FcStrListCreate (config->configFiles);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
FcChar8 *
|
2002-02-15 00:34:13 +01:00
|
|
|
FcConfigGetCache (FcConfig *config)
|
|
|
|
{
|
2006-08-31 06:59:53 +02:00
|
|
|
return NULL;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FcFontSet *
|
|
|
|
FcConfigGetFonts (FcConfig *config,
|
|
|
|
FcSetName set)
|
|
|
|
{
|
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return config->fonts[set];
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FcConfigSetFonts (FcConfig *config,
|
|
|
|
FcFontSet *fonts,
|
|
|
|
FcSetName set)
|
|
|
|
{
|
|
|
|
if (config->fonts[set])
|
|
|
|
FcFontSetDestroy (config->fonts[set]);
|
|
|
|
config->fonts[set] = fonts;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBlanks *
|
|
|
|
FcConfigGetBlanks (FcConfig *config)
|
|
|
|
{
|
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return config->blanks;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcConfigAddBlank (FcConfig *config,
|
|
|
|
FcChar32 blank)
|
|
|
|
{
|
2006-04-11 18:54:24 +02:00
|
|
|
FcBlanks *b, *freeme = 0;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
b = config->blanks;
|
|
|
|
if (!b)
|
|
|
|
{
|
2006-04-11 18:54:24 +02:00
|
|
|
freeme = b = FcBlanksCreate ();
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!b)
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
if (!FcBlanksAdd (b, blank))
|
2006-04-11 18:54:24 +02:00
|
|
|
{
|
|
|
|
if (freeme)
|
|
|
|
FcBlanksDestroy (freeme);
|
2002-02-15 00:34:13 +01:00
|
|
|
return FcFalse;
|
2006-04-11 18:54:24 +02:00
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
config->blanks = b;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
int
|
2007-11-04 05:56:36 +01:00
|
|
|
FcConfigGetRescanInterval (FcConfig *config)
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return config->rescanInterval;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
2007-11-04 05:56:36 +01:00
|
|
|
FcConfigSetRescanInterval (FcConfig *config, int rescanInterval)
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
config->rescanInterval = rescanInterval;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2007-11-04 21:20:45 +01:00
|
|
|
/*
|
|
|
|
* A couple of typos escaped into the library
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
FcConfigGetRescanInverval (FcConfig *config)
|
|
|
|
{
|
|
|
|
return FcConfigGetRescanInterval (config);
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcConfigSetRescanInverval (FcConfig *config, int rescanInterval)
|
|
|
|
{
|
|
|
|
return FcConfigSetRescanInterval (config, rescanInterval);
|
|
|
|
}
|
|
|
|
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
FcBool
|
|
|
|
FcConfigAddEdit (FcConfig *config,
|
|
|
|
FcTest *test,
|
|
|
|
FcEdit *edit,
|
|
|
|
FcMatchKind kind)
|
|
|
|
{
|
|
|
|
FcSubst *subst, **prev;
|
|
|
|
FcTest *t;
|
|
|
|
int num;
|
|
|
|
|
2006-09-03 02:52:12 +02:00
|
|
|
switch (kind) {
|
|
|
|
case FcMatchPattern:
|
|
|
|
prev = &config->substPattern;
|
|
|
|
break;
|
|
|
|
case FcMatchFont:
|
|
|
|
prev = &config->substFont;
|
|
|
|
break;
|
|
|
|
case FcMatchScan:
|
|
|
|
prev = &config->substScan;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return FcFalse;
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
subst = (FcSubst *) malloc (sizeof (FcSubst));
|
|
|
|
if (!subst)
|
|
|
|
return FcFalse;
|
2002-09-01 00:17:32 +02:00
|
|
|
FcMemAlloc (FC_MEM_SUBST, sizeof (FcSubst));
|
2002-02-15 00:34:13 +01:00
|
|
|
for (; *prev; prev = &(*prev)->next);
|
|
|
|
*prev = subst;
|
|
|
|
subst->next = 0;
|
|
|
|
subst->test = test;
|
|
|
|
subst->edit = edit;
|
|
|
|
num = 0;
|
|
|
|
for (t = test; t; t = t->next)
|
2002-08-11 20:11:04 +02:00
|
|
|
{
|
|
|
|
if (t->kind == FcMatchDefault)
|
|
|
|
t->kind = kind;
|
2002-02-15 00:34:13 +01:00
|
|
|
num++;
|
2002-08-11 20:11:04 +02:00
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
if (config->maxObjects < num)
|
|
|
|
config->maxObjects = num;
|
2002-08-11 20:11:04 +02:00
|
|
|
if (FcDebug () & FC_DBG_EDIT)
|
|
|
|
{
|
|
|
|
printf ("Add Subst ");
|
|
|
|
FcSubstPrint (subst);
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
typedef struct _FcSubState {
|
|
|
|
FcPatternElt *elt;
|
|
|
|
FcValueList *value;
|
|
|
|
} FcSubState;
|
|
|
|
|
|
|
|
static FcValue
|
|
|
|
FcConfigPromote (FcValue v, FcValue u)
|
|
|
|
{
|
|
|
|
if (v.type == FcTypeInteger)
|
|
|
|
{
|
|
|
|
v.type = FcTypeDouble;
|
|
|
|
v.u.d = (double) v.u.i;
|
|
|
|
}
|
|
|
|
else if (v.type == FcTypeVoid && u.type == FcTypeMatrix)
|
|
|
|
{
|
2005-08-24 08:21:30 +02:00
|
|
|
v.u.m = &FcIdentityMatrix;
|
2002-07-28 12:50:59 +02:00
|
|
|
v.type = FcTypeMatrix;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-08-22 09:36:45 +02:00
|
|
|
else if (v.type == FcTypeString && u.type == FcTypeLangSet)
|
|
|
|
{
|
2005-08-24 08:21:30 +02:00
|
|
|
v.u.l = FcLangSetPromote (v.u.s);
|
2002-08-22 09:36:45 +02:00
|
|
|
v.type = FcTypeLangSet;
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
2005-08-24 08:21:30 +02:00
|
|
|
FcConfigCompareValue (const FcValue *left_o,
|
2003-02-06 20:22:43 +01:00
|
|
|
FcOp op,
|
2005-08-24 08:21:30 +02:00
|
|
|
const FcValue *right_o)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2005-08-24 08:21:30 +02:00
|
|
|
FcValue left = FcValueCanonicalize(left_o);
|
|
|
|
FcValue right = FcValueCanonicalize(right_o);
|
2003-02-06 20:22:43 +01:00
|
|
|
FcBool ret = FcFalse;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2003-07-20 18:06:18 +02:00
|
|
|
left = FcConfigPromote (left, right);
|
|
|
|
right = FcConfigPromote (right, left);
|
2010-04-12 18:18:50 +02:00
|
|
|
if (left.type == right.type)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2003-07-20 18:06:18 +02:00
|
|
|
switch (left.type) {
|
2002-02-15 00:34:13 +01:00
|
|
|
case FcTypeInteger:
|
|
|
|
break; /* FcConfigPromote prevents this from happening */
|
|
|
|
case FcTypeDouble:
|
|
|
|
switch (op) {
|
|
|
|
case FcOpEqual:
|
|
|
|
case FcOpContains:
|
2003-07-20 18:06:18 +02:00
|
|
|
case FcOpListing:
|
|
|
|
ret = left.u.d == right.u.d;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
2002-08-22 20:53:22 +02:00
|
|
|
case FcOpNotEqual:
|
|
|
|
case FcOpNotContains:
|
2003-07-20 18:06:18 +02:00
|
|
|
ret = left.u.d != right.u.d;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
2010-04-12 18:18:50 +02:00
|
|
|
case FcOpLess:
|
2003-07-20 18:06:18 +02:00
|
|
|
ret = left.u.d < right.u.d;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
2010-04-12 18:18:50 +02:00
|
|
|
case FcOpLessEqual:
|
2003-07-20 18:06:18 +02:00
|
|
|
ret = left.u.d <= right.u.d;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
2010-04-12 18:18:50 +02:00
|
|
|
case FcOpMore:
|
2003-07-20 18:06:18 +02:00
|
|
|
ret = left.u.d > right.u.d;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
2010-04-12 18:18:50 +02:00
|
|
|
case FcOpMoreEqual:
|
2003-07-20 18:06:18 +02:00
|
|
|
ret = left.u.d >= right.u.d;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FcTypeBool:
|
|
|
|
switch (op) {
|
2010-04-12 18:18:50 +02:00
|
|
|
case FcOpEqual:
|
2002-02-15 00:34:13 +01:00
|
|
|
case FcOpContains:
|
2003-07-20 18:06:18 +02:00
|
|
|
case FcOpListing:
|
|
|
|
ret = left.u.b == right.u.b;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
2002-08-22 20:53:22 +02:00
|
|
|
case FcOpNotEqual:
|
|
|
|
case FcOpNotContains:
|
2003-07-20 18:06:18 +02:00
|
|
|
ret = left.u.b != right.u.b;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FcTypeString:
|
|
|
|
switch (op) {
|
2010-04-12 18:18:50 +02:00
|
|
|
case FcOpEqual:
|
2003-07-20 18:06:18 +02:00
|
|
|
case FcOpListing:
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
2003-05-28 03:34:38 +02:00
|
|
|
case FcOpContains:
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0;
|
2003-05-28 03:34:38 +02:00
|
|
|
break;
|
2002-08-22 20:53:22 +02:00
|
|
|
case FcOpNotEqual:
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0;
|
2003-05-28 03:34:38 +02:00
|
|
|
break;
|
2005-06-17 05:01:43 +02:00
|
|
|
case FcOpNotContains:
|
2007-12-13 06:47:33 +01:00
|
|
|
ret = FcStrStrIgnoreCase (left.u.s, right.u.s) == 0;
|
2005-06-17 05:01:43 +02:00
|
|
|
break;
|
2002-02-15 00:34:13 +01:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FcTypeMatrix:
|
|
|
|
switch (op) {
|
|
|
|
case FcOpEqual:
|
|
|
|
case FcOpContains:
|
2003-07-20 18:06:18 +02:00
|
|
|
case FcOpListing:
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = FcMatrixEqual (left.u.m, right.u.m);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
case FcOpNotEqual:
|
2002-08-22 20:53:22 +02:00
|
|
|
case FcOpNotContains:
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = !FcMatrixEqual (left.u.m, right.u.m);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FcTypeCharSet:
|
|
|
|
switch (op) {
|
|
|
|
case FcOpContains:
|
2003-07-20 18:06:18 +02:00
|
|
|
case FcOpListing:
|
|
|
|
/* left contains right if right is a subset of left */
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = FcCharSetIsSubset (right.u.c, left.u.c);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
2002-08-22 20:53:22 +02:00
|
|
|
case FcOpNotContains:
|
2003-07-20 18:06:18 +02:00
|
|
|
/* left contains right if right is a subset of left */
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = !FcCharSetIsSubset (right.u.c, left.u.c);
|
2002-08-22 20:53:22 +02:00
|
|
|
break;
|
2002-02-15 00:34:13 +01:00
|
|
|
case FcOpEqual:
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = FcCharSetEqual (left.u.c, right.u.c);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
case FcOpNotEqual:
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = !FcCharSetEqual (left.u.c, right.u.c);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2002-08-22 09:36:45 +02:00
|
|
|
case FcTypeLangSet:
|
|
|
|
switch (op) {
|
|
|
|
case FcOpContains:
|
2003-07-20 18:06:18 +02:00
|
|
|
case FcOpListing:
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = FcLangSetContains (left.u.l, right.u.l);
|
2002-08-22 09:36:45 +02:00
|
|
|
break;
|
2002-08-22 20:53:22 +02:00
|
|
|
case FcOpNotContains:
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = !FcLangSetContains (left.u.l, right.u.l);
|
2002-08-22 20:53:22 +02:00
|
|
|
break;
|
2002-08-22 09:36:45 +02:00
|
|
|
case FcOpEqual:
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = FcLangSetEqual (left.u.l, right.u.l);
|
2002-08-22 09:36:45 +02:00
|
|
|
break;
|
|
|
|
case FcOpNotEqual:
|
2005-08-24 08:21:30 +02:00
|
|
|
ret = !FcLangSetEqual (left.u.l, right.u.l);
|
2002-08-22 09:36:45 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2002-02-15 00:34:13 +01:00
|
|
|
case FcTypeVoid:
|
|
|
|
switch (op) {
|
|
|
|
case FcOpEqual:
|
|
|
|
case FcOpContains:
|
2003-07-20 18:06:18 +02:00
|
|
|
case FcOpListing:
|
2002-02-15 00:34:13 +01:00
|
|
|
ret = FcTrue;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2002-06-02 21:51:36 +02:00
|
|
|
case FcTypeFTFace:
|
|
|
|
switch (op) {
|
|
|
|
case FcOpEqual:
|
2002-08-22 20:53:22 +02:00
|
|
|
case FcOpContains:
|
2003-07-20 18:06:18 +02:00
|
|
|
case FcOpListing:
|
|
|
|
ret = left.u.f == right.u.f;
|
2002-06-02 21:51:36 +02:00
|
|
|
break;
|
|
|
|
case FcOpNotEqual:
|
2002-08-22 20:53:22 +02:00
|
|
|
case FcOpNotContains:
|
2003-07-20 18:06:18 +02:00
|
|
|
ret = left.u.f != right.u.f;
|
2002-06-02 21:51:36 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2002-08-11 20:11:04 +02:00
|
|
|
break;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-08-22 20:53:22 +02:00
|
|
|
if (op == FcOpNotEqual || op == FcOpNotContains)
|
2002-02-15 00:34:13 +01:00
|
|
|
ret = FcTrue;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-16 01:38:06 +02:00
|
|
|
#define _FcDoubleFloor(d) ((int) (d))
|
|
|
|
#define _FcDoubleCeil(d) ((double) (int) (d) == (d) ? (int) (d) : (int) ((d) + 1))
|
|
|
|
#define FcDoubleFloor(d) ((d) >= 0 ? _FcDoubleFloor(d) : -_FcDoubleCeil(-(d)))
|
|
|
|
#define FcDoubleCeil(d) ((d) >= 0 ? _FcDoubleCeil(d) : -_FcDoubleFloor(-(d)))
|
|
|
|
#define FcDoubleRound(d) FcDoubleFloor ((d) + 0.5)
|
|
|
|
#define FcDoubleTrunc(d) ((d) >= 0 ? _FcDoubleFloor (d) : -_FcDoubleFloor (-(d)))
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
static FcValue
|
|
|
|
FcConfigEvaluate (FcPattern *p, FcExpr *e)
|
|
|
|
{
|
|
|
|
FcValue v, vl, vr;
|
|
|
|
FcResult r;
|
|
|
|
FcMatrix *m;
|
2006-04-10 21:33:03 +02:00
|
|
|
FcChar8 *str;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
switch (e->op) {
|
|
|
|
case FcOpInteger:
|
|
|
|
v.type = FcTypeInteger;
|
|
|
|
v.u.i = e->u.ival;
|
|
|
|
break;
|
|
|
|
case FcOpDouble:
|
|
|
|
v.type = FcTypeDouble;
|
|
|
|
v.u.d = e->u.dval;
|
|
|
|
break;
|
|
|
|
case FcOpString:
|
|
|
|
v.type = FcTypeString;
|
2009-06-05 22:49:07 +02:00
|
|
|
v.u.s = e->u.sval;
|
|
|
|
v = FcValueSave (v);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
case FcOpMatrix:
|
|
|
|
v.type = FcTypeMatrix;
|
2005-08-24 08:21:30 +02:00
|
|
|
v.u.m = e->u.mval;
|
2002-02-15 00:34:13 +01:00
|
|
|
v = FcValueSave (v);
|
|
|
|
break;
|
|
|
|
case FcOpCharSet:
|
|
|
|
v.type = FcTypeCharSet;
|
2005-08-24 08:21:30 +02:00
|
|
|
v.u.c = e->u.cval;
|
2002-02-15 00:34:13 +01:00
|
|
|
v = FcValueSave (v);
|
|
|
|
break;
|
|
|
|
case FcOpBool:
|
|
|
|
v.type = FcTypeBool;
|
|
|
|
v.u.b = e->u.bval;
|
|
|
|
break;
|
|
|
|
case FcOpField:
|
2006-08-30 13:16:22 +02:00
|
|
|
r = FcPatternObjectGet (p, e->u.object, 0, &v);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (r != FcResultMatch)
|
|
|
|
v.type = FcTypeVoid;
|
2006-01-25 15:52:49 +01:00
|
|
|
v = FcValueSave (v);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
case FcOpConst:
|
|
|
|
if (FcNameConstant (e->u.constant, &v.u.i))
|
|
|
|
v.type = FcTypeInteger;
|
|
|
|
else
|
|
|
|
v.type = FcTypeVoid;
|
|
|
|
break;
|
|
|
|
case FcOpQuest:
|
|
|
|
vl = FcConfigEvaluate (p, e->u.tree.left);
|
|
|
|
if (vl.type == FcTypeBool)
|
|
|
|
{
|
|
|
|
if (vl.u.b)
|
|
|
|
v = FcConfigEvaluate (p, e->u.tree.right->u.tree.left);
|
|
|
|
else
|
|
|
|
v = FcConfigEvaluate (p, e->u.tree.right->u.tree.right);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
v.type = FcTypeVoid;
|
|
|
|
FcValueDestroy (vl);
|
|
|
|
break;
|
2002-08-22 20:53:22 +02:00
|
|
|
case FcOpEqual:
|
2002-02-15 00:34:13 +01:00
|
|
|
case FcOpNotEqual:
|
|
|
|
case FcOpLess:
|
|
|
|
case FcOpLessEqual:
|
|
|
|
case FcOpMore:
|
|
|
|
case FcOpMoreEqual:
|
2002-08-22 20:53:22 +02:00
|
|
|
case FcOpContains:
|
|
|
|
case FcOpNotContains:
|
2003-07-20 18:06:18 +02:00
|
|
|
case FcOpListing:
|
2002-08-11 20:11:04 +02:00
|
|
|
vl = FcConfigEvaluate (p, e->u.tree.left);
|
|
|
|
vr = FcConfigEvaluate (p, e->u.tree.right);
|
|
|
|
v.type = FcTypeBool;
|
2005-08-24 08:21:30 +02:00
|
|
|
v.u.b = FcConfigCompareValue (&vl, e->op, &vr);
|
2002-08-11 20:11:04 +02:00
|
|
|
FcValueDestroy (vl);
|
|
|
|
FcValueDestroy (vr);
|
|
|
|
break;
|
|
|
|
case FcOpOr:
|
|
|
|
case FcOpAnd:
|
2002-02-15 00:34:13 +01:00
|
|
|
case FcOpPlus:
|
|
|
|
case FcOpMinus:
|
|
|
|
case FcOpTimes:
|
|
|
|
case FcOpDivide:
|
|
|
|
vl = FcConfigEvaluate (p, e->u.tree.left);
|
|
|
|
vr = FcConfigEvaluate (p, e->u.tree.right);
|
|
|
|
vl = FcConfigPromote (vl, vr);
|
|
|
|
vr = FcConfigPromote (vr, vl);
|
|
|
|
if (vl.type == vr.type)
|
|
|
|
{
|
|
|
|
switch (vl.type) {
|
|
|
|
case FcTypeDouble:
|
|
|
|
switch (e->op) {
|
2010-04-12 18:18:50 +02:00
|
|
|
case FcOpPlus:
|
2002-02-15 00:34:13 +01:00
|
|
|
v.type = FcTypeDouble;
|
2010-04-12 18:18:50 +02:00
|
|
|
v.u.d = vl.u.d + vr.u.d;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
case FcOpMinus:
|
|
|
|
v.type = FcTypeDouble;
|
2010-04-12 18:18:50 +02:00
|
|
|
v.u.d = vl.u.d - vr.u.d;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
case FcOpTimes:
|
|
|
|
v.type = FcTypeDouble;
|
2010-04-12 18:18:50 +02:00
|
|
|
v.u.d = vl.u.d * vr.u.d;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
case FcOpDivide:
|
|
|
|
v.type = FcTypeDouble;
|
2010-04-12 18:18:50 +02:00
|
|
|
v.u.d = vl.u.d / vr.u.d;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
default:
|
2010-04-12 18:18:50 +02:00
|
|
|
v.type = FcTypeVoid;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (v.type == FcTypeDouble &&
|
|
|
|
v.u.d == (double) (int) v.u.d)
|
|
|
|
{
|
|
|
|
v.type = FcTypeInteger;
|
|
|
|
v.u.i = (int) v.u.d;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FcTypeBool:
|
|
|
|
switch (e->op) {
|
|
|
|
case FcOpOr:
|
|
|
|
v.type = FcTypeBool;
|
|
|
|
v.u.b = vl.u.b || vr.u.b;
|
|
|
|
break;
|
|
|
|
case FcOpAnd:
|
|
|
|
v.type = FcTypeBool;
|
|
|
|
v.u.b = vl.u.b && vr.u.b;
|
|
|
|
break;
|
|
|
|
default:
|
2010-04-12 18:18:50 +02:00
|
|
|
v.type = FcTypeVoid;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FcTypeString:
|
|
|
|
switch (e->op) {
|
|
|
|
case FcOpPlus:
|
|
|
|
v.type = FcTypeString;
|
2006-04-10 21:33:03 +02:00
|
|
|
str = FcStrPlus (vl.u.s, vr.u.s);
|
|
|
|
v.u.s = FcStrStaticName (str);
|
|
|
|
FcStrFree (str);
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2005-08-24 08:21:30 +02:00
|
|
|
if (!v.u.s)
|
2002-02-15 00:34:13 +01:00
|
|
|
v.type = FcTypeVoid;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
v.type = FcTypeVoid;
|
|
|
|
break;
|
|
|
|
}
|
2002-06-20 05:43:09 +02:00
|
|
|
break;
|
2002-02-15 00:34:13 +01:00
|
|
|
case FcTypeMatrix:
|
|
|
|
switch (e->op) {
|
|
|
|
case FcOpTimes:
|
|
|
|
v.type = FcTypeMatrix;
|
|
|
|
m = malloc (sizeof (FcMatrix));
|
|
|
|
if (m)
|
|
|
|
{
|
|
|
|
FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix));
|
2005-08-24 08:21:30 +02:00
|
|
|
FcMatrixMultiply (m, vl.u.m, vr.u.m);
|
|
|
|
v.u.m = m;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
v.type = FcTypeVoid;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
v.type = FcTypeVoid;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
v.type = FcTypeVoid;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
v.type = FcTypeVoid;
|
|
|
|
FcValueDestroy (vl);
|
|
|
|
FcValueDestroy (vr);
|
|
|
|
break;
|
|
|
|
case FcOpNot:
|
|
|
|
vl = FcConfigEvaluate (p, e->u.tree.left);
|
|
|
|
switch (vl.type) {
|
|
|
|
case FcTypeBool:
|
|
|
|
v.type = FcTypeBool;
|
|
|
|
v.u.b = !vl.u.b;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
v.type = FcTypeVoid;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
FcValueDestroy (vl);
|
|
|
|
break;
|
2003-04-16 01:38:06 +02:00
|
|
|
case FcOpFloor:
|
|
|
|
vl = FcConfigEvaluate (p, e->u.tree.left);
|
|
|
|
switch (vl.type) {
|
|
|
|
case FcTypeInteger:
|
|
|
|
v = vl;
|
|
|
|
break;
|
|
|
|
case FcTypeDouble:
|
|
|
|
v.type = FcTypeInteger;
|
|
|
|
v.u.i = FcDoubleFloor (vl.u.d);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
v.type = FcTypeVoid;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
FcValueDestroy (vl);
|
|
|
|
break;
|
|
|
|
case FcOpCeil:
|
|
|
|
vl = FcConfigEvaluate (p, e->u.tree.left);
|
|
|
|
switch (vl.type) {
|
|
|
|
case FcTypeInteger:
|
|
|
|
v = vl;
|
|
|
|
break;
|
|
|
|
case FcTypeDouble:
|
|
|
|
v.type = FcTypeInteger;
|
|
|
|
v.u.i = FcDoubleCeil (vl.u.d);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
v.type = FcTypeVoid;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
FcValueDestroy (vl);
|
|
|
|
break;
|
|
|
|
case FcOpRound:
|
|
|
|
vl = FcConfigEvaluate (p, e->u.tree.left);
|
|
|
|
switch (vl.type) {
|
|
|
|
case FcTypeInteger:
|
|
|
|
v = vl;
|
|
|
|
break;
|
|
|
|
case FcTypeDouble:
|
|
|
|
v.type = FcTypeInteger;
|
|
|
|
v.u.i = FcDoubleRound (vl.u.d);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
v.type = FcTypeVoid;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
FcValueDestroy (vl);
|
|
|
|
break;
|
|
|
|
case FcOpTrunc:
|
|
|
|
vl = FcConfigEvaluate (p, e->u.tree.left);
|
|
|
|
switch (vl.type) {
|
|
|
|
case FcTypeInteger:
|
|
|
|
v = vl;
|
|
|
|
break;
|
|
|
|
case FcTypeDouble:
|
|
|
|
v.type = FcTypeInteger;
|
|
|
|
v.u.i = FcDoubleTrunc (vl.u.d);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
v.type = FcTypeVoid;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
FcValueDestroy (vl);
|
|
|
|
break;
|
2002-02-15 00:34:13 +01:00
|
|
|
default:
|
|
|
|
v.type = FcTypeVoid;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return v;
|
|
|
|
}
|
|
|
|
|
|
|
|
static FcValueList *
|
|
|
|
FcConfigMatchValueList (FcPattern *p,
|
|
|
|
FcTest *t,
|
2002-06-19 00:23:05 +02:00
|
|
|
FcValueList *values)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
FcValueList *ret = 0;
|
|
|
|
FcExpr *e = t->expr;
|
|
|
|
FcValue value;
|
2002-06-19 00:23:05 +02:00
|
|
|
FcValueList *v;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
while (e)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2003-07-20 18:06:18 +02:00
|
|
|
/* Compute the value of the match expression */
|
2002-05-21 19:06:22 +02:00
|
|
|
if (e->op == FcOpComma)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
value = FcConfigEvaluate (p, e->u.tree.left);
|
|
|
|
e = e->u.tree.right;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
value = FcConfigEvaluate (p, e);
|
|
|
|
e = 0;
|
|
|
|
}
|
|
|
|
|
2006-08-30 13:16:22 +02:00
|
|
|
for (v = values; v; v = FcValueListNext(v))
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
2003-07-20 18:06:18 +02:00
|
|
|
/* Compare the pattern value to the match expression value */
|
2005-08-24 08:21:30 +02:00
|
|
|
if (FcConfigCompareValue (&v->value, t->op, &value))
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-05-21 19:06:22 +02:00
|
|
|
if (!ret)
|
|
|
|
ret = v;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (t->qual == FcQualAll)
|
|
|
|
{
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
}
|
2002-06-08 19:32:05 +02:00
|
|
|
FcValueDestroy (value);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static FcValueList *
|
2002-07-31 03:36:37 +02:00
|
|
|
FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
|
|
|
FcValueList *l;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!e)
|
|
|
|
return 0;
|
|
|
|
l = (FcValueList *) malloc (sizeof (FcValueList));
|
|
|
|
if (!l)
|
|
|
|
return 0;
|
|
|
|
FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
|
|
|
|
if (e->op == FcOpComma)
|
|
|
|
{
|
|
|
|
l->value = FcConfigEvaluate (p, e->u.tree.left);
|
2006-08-30 13:16:22 +02:00
|
|
|
l->next = FcConfigValues (p, e->u.tree.right, binding);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
l->value = FcConfigEvaluate (p, e);
|
2006-08-30 13:16:22 +02:00
|
|
|
l->next = NULL;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-07-31 03:36:37 +02:00
|
|
|
l->binding = binding;
|
2005-11-18 05:21:10 +01:00
|
|
|
if (l->value.type == FcTypeVoid)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2006-08-30 13:16:22 +02:00
|
|
|
FcValueList *next = FcValueListNext(l);
|
2005-06-28 05:41:02 +02:00
|
|
|
|
2005-11-18 05:21:10 +01:00
|
|
|
FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
|
|
|
|
free (l);
|
|
|
|
l = next;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2005-11-18 05:21:10 +01:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
static FcBool
|
2005-06-28 05:41:02 +02:00
|
|
|
FcConfigAdd (FcValueListPtr *head,
|
2002-02-15 00:34:13 +01:00
|
|
|
FcValueList *position,
|
|
|
|
FcBool append,
|
|
|
|
FcValueList *new)
|
|
|
|
{
|
2005-06-28 05:41:02 +02:00
|
|
|
FcValueListPtr *prev, last, v;
|
2003-02-12 19:22:12 +01:00
|
|
|
FcValueBinding sameBinding;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2003-02-12 19:22:12 +01:00
|
|
|
if (position)
|
|
|
|
sameBinding = position->binding;
|
|
|
|
else
|
|
|
|
sameBinding = FcValueBindingWeak;
|
2006-08-30 13:16:22 +02:00
|
|
|
for (v = new; v != NULL; v = FcValueListNext(v))
|
|
|
|
if (v->binding == FcValueBindingSame)
|
|
|
|
v->binding = sameBinding;
|
2002-02-15 00:34:13 +01:00
|
|
|
if (append)
|
|
|
|
{
|
|
|
|
if (position)
|
|
|
|
prev = &position->next;
|
|
|
|
else
|
2010-04-12 18:18:50 +02:00
|
|
|
for (prev = head; *prev != NULL;
|
2006-08-30 13:16:22 +02:00
|
|
|
prev = &(*prev)->next)
|
2002-02-15 00:34:13 +01:00
|
|
|
;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (position)
|
|
|
|
{
|
2010-04-12 18:18:50 +02:00
|
|
|
for (prev = head; *prev != NULL;
|
2006-08-30 13:16:22 +02:00
|
|
|
prev = &(*prev)->next)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2006-08-30 13:16:22 +02:00
|
|
|
if (*prev == position)
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
prev = head;
|
|
|
|
|
|
|
|
if (FcDebug () & FC_DBG_EDIT)
|
|
|
|
{
|
2006-08-30 13:16:22 +02:00
|
|
|
if (*prev == NULL)
|
2002-02-15 00:34:13 +01:00
|
|
|
printf ("position not on list\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FcDebug () & FC_DBG_EDIT)
|
|
|
|
{
|
|
|
|
printf ("%s list before ", append ? "Append" : "Prepend");
|
|
|
|
FcValueListPrint (*head);
|
|
|
|
printf ("\n");
|
|
|
|
}
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
if (new)
|
|
|
|
{
|
2006-08-30 13:16:22 +02:00
|
|
|
last = new;
|
|
|
|
while (last->next != NULL)
|
|
|
|
last = last->next;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2006-08-30 13:16:22 +02:00
|
|
|
last->next = *prev;
|
|
|
|
*prev = new;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
if (FcDebug () & FC_DBG_EDIT)
|
|
|
|
{
|
|
|
|
printf ("%s list after ", append ? "Append" : "Prepend");
|
|
|
|
FcValueListPrint (*head);
|
|
|
|
printf ("\n");
|
|
|
|
}
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2005-06-28 05:41:02 +02:00
|
|
|
FcConfigDel (FcValueListPtr *head,
|
2002-02-15 00:34:13 +01:00
|
|
|
FcValueList *position)
|
|
|
|
{
|
2005-06-28 05:41:02 +02:00
|
|
|
FcValueListPtr *prev;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2006-08-30 13:16:22 +02:00
|
|
|
for (prev = head; *prev != NULL; prev = &(*prev)->next)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2006-08-30 13:16:22 +02:00
|
|
|
if (*prev == position)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
|
|
|
*prev = position->next;
|
2006-08-30 13:16:22 +02:00
|
|
|
position->next = NULL;
|
|
|
|
FcValueListDestroy (position);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcConfigPatternAdd (FcPattern *p,
|
2006-08-30 13:16:22 +02:00
|
|
|
FcObject object,
|
2002-02-15 00:34:13 +01:00
|
|
|
FcValueList *list,
|
|
|
|
FcBool append)
|
|
|
|
{
|
|
|
|
if (list)
|
|
|
|
{
|
2006-08-30 13:16:22 +02:00
|
|
|
FcPatternElt *e = FcPatternObjectInsertElt (p, object);
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!e)
|
|
|
|
return;
|
|
|
|
FcConfigAdd (&e->values, 0, append, list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Delete all values associated with a field
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
FcConfigPatternDel (FcPattern *p,
|
2006-08-30 13:16:22 +02:00
|
|
|
FcObject object)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2006-08-30 13:16:22 +02:00
|
|
|
FcPatternElt *e = FcPatternObjectFindElt (p, object);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!e)
|
|
|
|
return;
|
2006-08-30 13:16:22 +02:00
|
|
|
while (e->values != NULL)
|
|
|
|
FcConfigDel (&e->values, e->values);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
FcConfigPatternCanon (FcPattern *p,
|
2006-08-30 13:16:22 +02:00
|
|
|
FcObject object)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2006-08-30 13:16:22 +02:00
|
|
|
FcPatternElt *e = FcPatternObjectFindElt (p, object);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!e)
|
|
|
|
return;
|
2006-08-30 13:16:22 +02:00
|
|
|
if (e->values == NULL)
|
|
|
|
FcPatternObjectDel (p, object);
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
2002-08-19 21:32:05 +02:00
|
|
|
FcConfigSubstituteWithPat (FcConfig *config,
|
|
|
|
FcPattern *p,
|
|
|
|
FcPattern *p_pat,
|
|
|
|
FcMatchKind kind)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
|
|
|
FcSubst *s;
|
|
|
|
FcSubState *st;
|
|
|
|
int i;
|
|
|
|
FcTest *t;
|
|
|
|
FcEdit *e;
|
|
|
|
FcValueList *l;
|
2002-08-11 20:11:04 +02:00
|
|
|
FcPattern *m;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
|
2006-09-03 02:52:12 +02:00
|
|
|
switch (kind) {
|
|
|
|
case FcMatchPattern:
|
|
|
|
s = config->substPattern;
|
|
|
|
break;
|
|
|
|
case FcMatchFont:
|
|
|
|
s = config->substFont;
|
|
|
|
break;
|
|
|
|
case FcMatchScan:
|
|
|
|
s = config->substScan;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
st = (FcSubState *) malloc (config->maxObjects * sizeof (FcSubState));
|
|
|
|
if (!st && config->maxObjects)
|
|
|
|
return FcFalse;
|
|
|
|
FcMemAlloc (FC_MEM_SUBSTATE, config->maxObjects * sizeof (FcSubState));
|
|
|
|
|
|
|
|
if (FcDebug () & FC_DBG_EDIT)
|
|
|
|
{
|
|
|
|
printf ("FcConfigSubstitute ");
|
|
|
|
FcPatternPrint (p);
|
|
|
|
}
|
|
|
|
for (; s; s = s->next)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Check the tests to see if
|
|
|
|
* they all match the pattern
|
|
|
|
*/
|
|
|
|
for (t = s->test, i = 0; t; t = t->next, i++)
|
|
|
|
{
|
|
|
|
if (FcDebug () & FC_DBG_EDIT)
|
|
|
|
{
|
|
|
|
printf ("FcConfigSubstitute test ");
|
|
|
|
FcTestPrint (t);
|
|
|
|
}
|
2002-08-11 20:11:04 +02:00
|
|
|
st[i].elt = 0;
|
|
|
|
if (kind == FcMatchFont && t->kind == FcMatchPattern)
|
|
|
|
m = p_pat;
|
|
|
|
else
|
|
|
|
m = p;
|
|
|
|
if (m)
|
2006-08-30 13:16:22 +02:00
|
|
|
st[i].elt = FcPatternObjectFindElt (m, t->object);
|
2002-08-11 20:11:04 +02:00
|
|
|
else
|
|
|
|
st[i].elt = 0;
|
2002-02-15 00:34:13 +01:00
|
|
|
/*
|
|
|
|
* If there's no such field in the font,
|
|
|
|
* then FcQualAll matches while FcQualAny does not
|
|
|
|
*/
|
|
|
|
if (!st[i].elt)
|
|
|
|
{
|
|
|
|
if (t->qual == FcQualAll)
|
|
|
|
{
|
|
|
|
st[i].value = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Check to see if there is a match, mark the location
|
|
|
|
* to apply match-relative edits
|
|
|
|
*/
|
2006-08-30 13:16:22 +02:00
|
|
|
st[i].value = FcConfigMatchValueList (m, t, st[i].elt->values);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!st[i].value)
|
|
|
|
break;
|
2006-08-30 13:16:22 +02:00
|
|
|
if (t->qual == FcQualFirst && st[i].value != st[i].elt->values)
|
2002-06-19 22:08:22 +02:00
|
|
|
break;
|
2006-08-30 13:16:22 +02:00
|
|
|
if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values)
|
2002-06-19 22:08:22 +02:00
|
|
|
break;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
if (t)
|
|
|
|
{
|
|
|
|
if (FcDebug () & FC_DBG_EDIT)
|
|
|
|
printf ("No match\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (FcDebug () & FC_DBG_EDIT)
|
|
|
|
{
|
|
|
|
printf ("Substitute ");
|
|
|
|
FcSubstPrint (s);
|
|
|
|
}
|
|
|
|
for (e = s->edit; e; e = e->next)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Evaluate the list of expressions
|
|
|
|
*/
|
2002-07-31 03:36:37 +02:00
|
|
|
l = FcConfigValues (p, e->expr, e->binding);
|
2002-02-15 00:34:13 +01:00
|
|
|
/*
|
2002-08-11 20:11:04 +02:00
|
|
|
* Locate any test associated with this field, skipping
|
|
|
|
* tests associated with the pattern when substituting in
|
|
|
|
* the font
|
2002-02-15 00:34:13 +01:00
|
|
|
*/
|
|
|
|
for (t = s->test, i = 0; t; t = t->next, i++)
|
2002-08-11 20:11:04 +02:00
|
|
|
{
|
|
|
|
if ((t->kind == FcMatchFont || kind == FcMatchPattern) &&
|
2006-08-30 13:16:22 +02:00
|
|
|
t->object == e->object)
|
2002-12-21 03:31:53 +01:00
|
|
|
{
|
2010-04-12 18:18:50 +02:00
|
|
|
/*
|
2003-04-22 08:27:27 +02:00
|
|
|
* KLUDGE - the pattern may have been reallocated or
|
|
|
|
* things may have been inserted or deleted above
|
|
|
|
* this element by other edits. Go back and find
|
|
|
|
* the element again
|
|
|
|
*/
|
|
|
|
if (e != s->edit && st[i].elt)
|
2006-08-30 13:16:22 +02:00
|
|
|
st[i].elt = FcPatternObjectFindElt (p, t->object);
|
2002-12-21 03:31:53 +01:00
|
|
|
if (!st[i].elt)
|
|
|
|
t = 0;
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
2002-12-21 03:31:53 +01:00
|
|
|
}
|
2002-08-11 20:11:04 +02:00
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
switch (e->op) {
|
|
|
|
case FcOpAssign:
|
|
|
|
/*
|
|
|
|
* If there was a test, then replace the matched
|
|
|
|
* value with the new list of values
|
|
|
|
*/
|
2002-06-03 10:31:15 +02:00
|
|
|
if (t)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
|
|
|
FcValueList *thisValue = st[i].value;
|
2006-08-30 13:16:22 +02:00
|
|
|
FcValueList *nextValue = thisValue;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
/*
|
|
|
|
* Append the new list of values after the current value
|
|
|
|
*/
|
|
|
|
FcConfigAdd (&st[i].elt->values, thisValue, FcTrue, l);
|
2002-02-15 07:01:28 +01:00
|
|
|
/*
|
|
|
|
* Delete the marked value
|
|
|
|
*/
|
2006-04-12 16:36:36 +02:00
|
|
|
if (thisValue)
|
|
|
|
FcConfigDel (&st[i].elt->values, thisValue);
|
2002-02-15 00:34:13 +01:00
|
|
|
/*
|
|
|
|
* Adjust any pointers into the value list to ensure
|
|
|
|
* future edits occur at the same place
|
|
|
|
*/
|
|
|
|
for (t = s->test, i = 0; t; t = t->next, i++)
|
|
|
|
{
|
|
|
|
if (st[i].value == thisValue)
|
|
|
|
st[i].value = nextValue;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fall through ... */
|
|
|
|
case FcOpAssignReplace:
|
|
|
|
/*
|
|
|
|
* Delete all of the values and insert
|
|
|
|
* the new set
|
|
|
|
*/
|
2006-08-30 13:16:22 +02:00
|
|
|
FcConfigPatternDel (p, e->object);
|
|
|
|
FcConfigPatternAdd (p, e->object, l, FcTrue);
|
2002-02-15 00:34:13 +01:00
|
|
|
/*
|
|
|
|
* Adjust any pointers into the value list as they no
|
|
|
|
* longer point to anything valid
|
|
|
|
*/
|
|
|
|
if (t)
|
|
|
|
{
|
|
|
|
FcPatternElt *thisElt = st[i].elt;
|
|
|
|
for (t = s->test, i = 0; t; t = t->next, i++)
|
|
|
|
{
|
|
|
|
if (st[i].elt == thisElt)
|
|
|
|
st[i].value = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FcOpPrepend:
|
|
|
|
if (t)
|
|
|
|
{
|
|
|
|
FcConfigAdd (&st[i].elt->values, st[i].value, FcFalse, l);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fall through ... */
|
|
|
|
case FcOpPrependFirst:
|
2006-08-30 13:16:22 +02:00
|
|
|
FcConfigPatternAdd (p, e->object, l, FcFalse);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
case FcOpAppend:
|
|
|
|
if (t)
|
|
|
|
{
|
|
|
|
FcConfigAdd (&st[i].elt->values, st[i].value, FcTrue, l);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* fall through ... */
|
|
|
|
case FcOpAppendLast:
|
2006-08-30 13:16:22 +02:00
|
|
|
FcConfigPatternAdd (p, e->object, l, FcTrue);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
default:
|
2006-08-30 13:16:22 +02:00
|
|
|
FcValueListDestroy (l);
|
2002-02-15 00:34:13 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Now go through the pattern and eliminate
|
|
|
|
* any properties without data
|
|
|
|
*/
|
|
|
|
for (e = s->edit; e; e = e->next)
|
2006-08-30 13:16:22 +02:00
|
|
|
FcConfigPatternCanon (p, e->object);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
|
|
if (FcDebug () & FC_DBG_EDIT)
|
|
|
|
{
|
|
|
|
printf ("FcConfigSubstitute edit");
|
|
|
|
FcPatternPrint (p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FcMemFree (FC_MEM_SUBSTATE, config->maxObjects * sizeof (FcSubState));
|
|
|
|
free (st);
|
|
|
|
if (FcDebug () & FC_DBG_EDIT)
|
|
|
|
{
|
|
|
|
printf ("FcConfigSubstitute done");
|
|
|
|
FcPatternPrint (p);
|
|
|
|
}
|
|
|
|
return FcTrue;
|
|
|
|
}
|
|
|
|
|
2002-08-19 21:32:05 +02:00
|
|
|
FcBool
|
|
|
|
FcConfigSubstitute (FcConfig *config,
|
|
|
|
FcPattern *p,
|
|
|
|
FcMatchKind kind)
|
|
|
|
{
|
|
|
|
return FcConfigSubstituteWithPat (config, p, 0, kind);
|
|
|
|
}
|
|
|
|
|
2008-05-04 04:45:31 +02:00
|
|
|
#if defined (_WIN32)
|
|
|
|
|
|
|
|
# define WIN32_LEAN_AND_MEAN
|
|
|
|
# define WIN32_EXTRA_LEAN
|
|
|
|
# include <windows.h>
|
2003-03-22 22:25:34 +01:00
|
|
|
|
|
|
|
static FcChar8 fontconfig_path[1000] = "";
|
|
|
|
|
2008-05-04 04:45:31 +02:00
|
|
|
# if (defined (PIC) || defined (DLL_EXPORT))
|
|
|
|
|
2003-03-22 22:25:34 +01:00
|
|
|
BOOL WINAPI
|
|
|
|
DllMain (HINSTANCE hinstDLL,
|
|
|
|
DWORD fdwReason,
|
|
|
|
LPVOID lpvReserved)
|
|
|
|
{
|
|
|
|
FcChar8 *p;
|
|
|
|
|
|
|
|
switch (fdwReason) {
|
|
|
|
case DLL_PROCESS_ATTACH:
|
|
|
|
if (!GetModuleFileName ((HMODULE) hinstDLL, fontconfig_path,
|
|
|
|
sizeof (fontconfig_path)))
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* If the fontconfig DLL is in a "bin" or "lib" subfolder,
|
|
|
|
* assume it's a Unix-style installation tree, and use
|
|
|
|
* "etc/fonts" in there as FONTCONFIG_PATH. Otherwise use the
|
|
|
|
* folder where the DLL is as FONTCONFIG_PATH.
|
|
|
|
*/
|
|
|
|
p = strrchr (fontconfig_path, '\\');
|
|
|
|
if (p)
|
|
|
|
{
|
|
|
|
*p = '\0';
|
|
|
|
p = strrchr (fontconfig_path, '\\');
|
|
|
|
if (p && (FcStrCmpIgnoreCase (p + 1, "bin") == 0 ||
|
|
|
|
FcStrCmpIgnoreCase (p + 1, "lib") == 0))
|
|
|
|
*p = '\0';
|
|
|
|
strcat (fontconfig_path, "\\etc\\fonts");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
fontconfig_path[0] = '\0';
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2003-03-22 22:25:34 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-05-04 04:45:31 +02:00
|
|
|
# endif /* !PIC */
|
|
|
|
|
2003-03-22 22:25:34 +01:00
|
|
|
#undef FONTCONFIG_PATH
|
|
|
|
#define FONTCONFIG_PATH fontconfig_path
|
|
|
|
|
2008-05-04 04:45:31 +02:00
|
|
|
#endif /* !_WIN32 */
|
2003-03-22 22:25:34 +01:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
#ifndef FONTCONFIG_FILE
|
|
|
|
#define FONTCONFIG_FILE "fonts.conf"
|
|
|
|
#endif
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
static FcChar8 *
|
|
|
|
FcConfigFileExists (const FcChar8 *dir, const FcChar8 *file)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-15 07:01:28 +01:00
|
|
|
FcChar8 *path;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
|
|
if (!dir)
|
2002-02-15 07:01:28 +01:00
|
|
|
dir = (FcChar8 *) "";
|
|
|
|
path = malloc (strlen ((char *) dir) + 1 + strlen ((char *) file) + 1);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!path)
|
|
|
|
return 0;
|
|
|
|
|
2002-03-01 02:00:54 +01:00
|
|
|
strcpy ((char *) path, (const char *) dir);
|
2003-03-22 22:25:34 +01:00
|
|
|
/* make sure there's a single separator */
|
|
|
|
#ifdef _WIN32
|
|
|
|
if ((!path[0] || (path[strlen((char *) path)-1] != '/' &&
|
|
|
|
path[strlen((char *) path)-1] != '\\')) &&
|
2005-03-09 01:47:11 +01:00
|
|
|
!(file[0] == '/' ||
|
|
|
|
file[0] == '\\' ||
|
|
|
|
(isalpha (file[0]) && file[1] == ':' && (file[2] == '/' || file[2] == '\\'))))
|
2003-03-22 22:25:34 +01:00
|
|
|
strcat ((char *) path, "\\");
|
|
|
|
#else
|
2002-02-15 07:01:28 +01:00
|
|
|
if ((!path[0] || path[strlen((char *) path)-1] != '/') && file[0] != '/')
|
|
|
|
strcat ((char *) path, "/");
|
2003-03-22 22:25:34 +01:00
|
|
|
#endif
|
2002-02-15 07:01:28 +01:00
|
|
|
strcat ((char *) path, (char *) file);
|
2002-02-15 00:34:13 +01:00
|
|
|
|
2002-09-01 00:17:32 +02:00
|
|
|
FcMemAlloc (FC_MEM_STRING, strlen ((char *) path) + 1);
|
2002-02-15 07:01:28 +01:00
|
|
|
if (access ((char *) path, R_OK) == 0)
|
2002-02-15 00:34:13 +01:00
|
|
|
return path;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-09-01 00:17:32 +02:00
|
|
|
FcStrFree (path);
|
2002-02-15 00:34:13 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
static FcChar8 **
|
2002-02-15 00:34:13 +01:00
|
|
|
FcConfigGetPath (void)
|
|
|
|
{
|
2002-02-15 07:01:28 +01:00
|
|
|
FcChar8 **path;
|
|
|
|
FcChar8 *env, *e, *colon;
|
|
|
|
FcChar8 *dir;
|
2002-02-15 00:34:13 +01:00
|
|
|
int npath;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
npath = 2; /* default dir + null */
|
2002-02-15 07:01:28 +01:00
|
|
|
env = (FcChar8 *) getenv ("FONTCONFIG_PATH");
|
2002-02-15 00:34:13 +01:00
|
|
|
if (env)
|
|
|
|
{
|
|
|
|
e = env;
|
|
|
|
npath++;
|
|
|
|
while (*e)
|
2003-03-22 22:25:34 +01:00
|
|
|
if (*e++ == FC_SEARCH_PATH_SEPARATOR)
|
2002-02-15 00:34:13 +01:00
|
|
|
npath++;
|
|
|
|
}
|
2002-02-15 07:01:28 +01:00
|
|
|
path = calloc (npath, sizeof (FcChar8 *));
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!path)
|
|
|
|
goto bail0;
|
|
|
|
i = 0;
|
|
|
|
|
|
|
|
if (env)
|
|
|
|
{
|
|
|
|
e = env;
|
2010-04-12 18:18:50 +02:00
|
|
|
while (*e)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2003-03-22 22:25:34 +01:00
|
|
|
colon = (FcChar8 *) strchr ((char *) e, FC_SEARCH_PATH_SEPARATOR);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!colon)
|
2002-02-15 07:01:28 +01:00
|
|
|
colon = e + strlen ((char *) e);
|
2002-02-15 00:34:13 +01:00
|
|
|
path[i] = malloc (colon - e + 1);
|
|
|
|
if (!path[i])
|
|
|
|
goto bail1;
|
2002-03-01 02:00:54 +01:00
|
|
|
strncpy ((char *) path[i], (const char *) e, colon - e);
|
2002-02-15 00:34:13 +01:00
|
|
|
path[i][colon - e] = '\0';
|
|
|
|
if (*colon)
|
|
|
|
e = colon + 1;
|
|
|
|
else
|
|
|
|
e = colon;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2008-05-04 04:45:31 +02:00
|
|
|
#ifdef _WIN32
|
|
|
|
if (fontconfig_path[0] == '\0')
|
|
|
|
{
|
2008-08-12 20:10:03 +02:00
|
|
|
char *p;
|
2008-05-04 04:45:31 +02:00
|
|
|
if(!GetModuleFileName(NULL, fontconfig_path, sizeof(fontconfig_path)))
|
|
|
|
goto bail1;
|
2008-08-12 20:10:03 +02:00
|
|
|
p = strrchr (fontconfig_path, '\\');
|
2008-05-04 04:45:31 +02:00
|
|
|
if (p) *p = '\0';
|
|
|
|
strcat (fontconfig_path, "\\fonts");
|
|
|
|
}
|
|
|
|
#endif
|
2002-02-15 07:01:28 +01:00
|
|
|
dir = (FcChar8 *) FONTCONFIG_PATH;
|
|
|
|
path[i] = malloc (strlen ((char *) dir) + 1);
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!path[i])
|
|
|
|
goto bail1;
|
2002-03-01 02:00:54 +01:00
|
|
|
strcpy ((char *) path[i], (const char *) dir);
|
2002-02-15 00:34:13 +01:00
|
|
|
return path;
|
|
|
|
|
|
|
|
bail1:
|
|
|
|
for (i = 0; path[i]; i++)
|
|
|
|
free (path[i]);
|
|
|
|
free (path);
|
|
|
|
bail0:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2002-02-15 07:01:28 +01:00
|
|
|
FcConfigFreePath (FcChar8 **path)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-15 07:01:28 +01:00
|
|
|
FcChar8 **p;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
|
|
for (p = path; *p; p++)
|
|
|
|
free (*p);
|
|
|
|
free (path);
|
|
|
|
}
|
|
|
|
|
2003-03-02 20:12:23 +01:00
|
|
|
static FcBool _FcConfigHomeEnabled = FcTrue;
|
|
|
|
|
|
|
|
FcChar8 *
|
|
|
|
FcConfigHome (void)
|
|
|
|
{
|
|
|
|
if (_FcConfigHomeEnabled)
|
2003-03-22 22:25:34 +01:00
|
|
|
{
|
|
|
|
char *home = getenv ("HOME");
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
if (home == NULL)
|
|
|
|
home = getenv ("USERPROFILE");
|
|
|
|
#endif
|
|
|
|
|
2005-09-11 04:16:09 +02:00
|
|
|
return (FcChar8 *) home;
|
2003-03-22 22:25:34 +01:00
|
|
|
}
|
2003-03-02 20:12:23 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcConfigEnableHome (FcBool enable)
|
|
|
|
{
|
|
|
|
FcBool prev = _FcConfigHomeEnabled;
|
|
|
|
_FcConfigHomeEnabled = enable;
|
|
|
|
return prev;
|
|
|
|
}
|
|
|
|
|
2002-02-15 07:01:28 +01:00
|
|
|
FcChar8 *
|
|
|
|
FcConfigFilename (const FcChar8 *url)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
2002-02-15 07:01:28 +01:00
|
|
|
FcChar8 *file, *dir, **path, **p;
|
2008-05-04 04:45:31 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!url || !*url)
|
|
|
|
{
|
2002-02-15 07:01:28 +01:00
|
|
|
url = (FcChar8 *) getenv ("FONTCONFIG_FILE");
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!url)
|
2002-02-15 07:01:28 +01:00
|
|
|
url = (FcChar8 *) FONTCONFIG_FILE;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
2002-02-15 07:01:28 +01:00
|
|
|
file = 0;
|
2003-03-22 22:25:34 +01:00
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
if (isalpha (*url) &&
|
|
|
|
url[1] == ':' &&
|
|
|
|
(url[2] == '/' || url[2] == '\\'))
|
|
|
|
goto absolute_path;
|
|
|
|
#endif
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
switch (*url) {
|
|
|
|
case '~':
|
2003-03-02 20:12:23 +01:00
|
|
|
dir = FcConfigHome ();
|
2002-02-15 00:34:13 +01:00
|
|
|
if (dir)
|
|
|
|
file = FcConfigFileExists (dir, url + 1);
|
|
|
|
else
|
|
|
|
file = 0;
|
|
|
|
break;
|
2003-03-22 22:25:34 +01:00
|
|
|
#ifdef _WIN32
|
|
|
|
case '\\':
|
|
|
|
absolute_path:
|
|
|
|
#endif
|
2002-02-15 00:34:13 +01:00
|
|
|
case '/':
|
|
|
|
file = FcConfigFileExists (0, url);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
path = FcConfigGetPath ();
|
|
|
|
if (!path)
|
|
|
|
return 0;
|
|
|
|
for (p = path; *p; p++)
|
|
|
|
{
|
|
|
|
file = FcConfigFileExists (*p, url);
|
|
|
|
if (file)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
FcConfigFreePath (path);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return file;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Manage the application-specific fonts
|
|
|
|
*/
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcConfigAppFontAddFile (FcConfig *config,
|
2002-02-15 07:01:28 +01:00
|
|
|
const FcChar8 *file)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
|
|
|
FcFontSet *set;
|
2002-05-21 19:06:22 +02:00
|
|
|
FcStrSet *subdirs;
|
|
|
|
FcStrList *sublist;
|
|
|
|
FcChar8 *subdir;
|
2002-02-15 00:34:13 +01:00
|
|
|
|
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
|
2002-05-21 19:06:22 +02:00
|
|
|
subdirs = FcStrSetCreate ();
|
|
|
|
if (!subdirs)
|
|
|
|
return FcFalse;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
set = FcConfigGetFonts (config, FcSetApplication);
|
|
|
|
if (!set)
|
|
|
|
{
|
|
|
|
set = FcFontSetCreate ();
|
|
|
|
if (!set)
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
|
|
|
FcStrSetDestroy (subdirs);
|
2002-02-15 00:34:13 +01:00
|
|
|
return FcFalse;
|
2002-05-21 19:06:22 +02:00
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
FcConfigSetFonts (config, set, FcSetApplication);
|
|
|
|
}
|
2002-05-21 19:06:22 +02:00
|
|
|
|
2006-09-01 10:15:14 +02:00
|
|
|
if (!FcFileScanConfig (set, subdirs, config->blanks, file, config))
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
|
|
|
FcStrSetDestroy (subdirs);
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
if ((sublist = FcStrListCreate (subdirs)))
|
|
|
|
{
|
|
|
|
while ((subdir = FcStrListNext (sublist)))
|
|
|
|
{
|
|
|
|
FcConfigAppFontAddDir (config, subdir);
|
|
|
|
}
|
|
|
|
FcStrListDone (sublist);
|
|
|
|
}
|
2006-02-04 01:09:42 +01:00
|
|
|
FcStrSetDestroy (subdirs);
|
2002-05-21 19:06:22 +02:00
|
|
|
return FcTrue;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcConfigAppFontAddDir (FcConfig *config,
|
2002-02-15 07:01:28 +01:00
|
|
|
const FcChar8 *dir)
|
2002-02-15 00:34:13 +01:00
|
|
|
{
|
|
|
|
FcFontSet *set;
|
2006-09-15 09:23:40 +02:00
|
|
|
FcStrSet *dirs;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return FcFalse;
|
|
|
|
}
|
2006-09-15 09:23:40 +02:00
|
|
|
|
|
|
|
dirs = FcStrSetCreate ();
|
|
|
|
if (!dirs)
|
2002-05-21 19:06:22 +02:00
|
|
|
return FcFalse;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
set = FcConfigGetFonts (config, FcSetApplication);
|
|
|
|
if (!set)
|
|
|
|
{
|
|
|
|
set = FcFontSetCreate ();
|
|
|
|
if (!set)
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
2006-09-15 09:23:40 +02:00
|
|
|
FcStrSetDestroy (dirs);
|
2002-02-15 00:34:13 +01:00
|
|
|
return FcFalse;
|
2002-05-21 19:06:22 +02:00
|
|
|
}
|
2002-02-15 00:34:13 +01:00
|
|
|
FcConfigSetFonts (config, set, FcSetApplication);
|
|
|
|
}
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2006-09-15 09:23:40 +02:00
|
|
|
FcStrSetAddFilename (dirs, dir);
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2006-09-15 09:23:40 +02:00
|
|
|
if (!FcConfigAddDirList (config, FcSetApplication, dirs))
|
2002-05-21 19:06:22 +02:00
|
|
|
{
|
2006-09-15 09:23:40 +02:00
|
|
|
FcStrSetDestroy (dirs);
|
2002-05-21 19:06:22 +02:00
|
|
|
return FcFalse;
|
|
|
|
}
|
2006-09-15 09:23:40 +02:00
|
|
|
FcStrSetDestroy (dirs);
|
2002-05-21 19:06:22 +02:00
|
|
|
return FcTrue;
|
2002-02-15 00:34:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FcConfigAppFontClear (FcConfig *config)
|
|
|
|
{
|
2003-09-01 07:11:17 +02:00
|
|
|
if (!config)
|
|
|
|
{
|
|
|
|
config = FcConfigGetCurrent ();
|
|
|
|
if (!config)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-02-15 00:34:13 +01:00
|
|
|
FcConfigSetFonts (config, 0, FcSetApplication);
|
|
|
|
}
|
2003-05-07 18:13:24 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Manage filename-based font source selectors
|
|
|
|
*/
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcConfigGlobAdd (FcConfig *config,
|
|
|
|
const FcChar8 *glob,
|
|
|
|
FcBool accept)
|
|
|
|
{
|
|
|
|
FcStrSet *set = accept ? config->acceptGlobs : config->rejectGlobs;
|
|
|
|
|
|
|
|
return FcStrSetAdd (set, glob);
|
|
|
|
}
|
|
|
|
|
|
|
|
static FcBool
|
|
|
|
FcConfigGlobMatch (const FcChar8 *glob,
|
|
|
|
const FcChar8 *string)
|
|
|
|
{
|
|
|
|
FcChar8 c;
|
|
|
|
|
2010-04-12 18:18:50 +02:00
|
|
|
while ((c = *glob++))
|
2003-05-07 18:13:24 +02:00
|
|
|
{
|
|
|
|
switch (c) {
|
|
|
|
case '*':
|
|
|
|
/* short circuit common case */
|
|
|
|
if (!*glob)
|
|
|
|
return FcTrue;
|
|
|
|
/* short circuit another common case */
|
|
|
|
if (strchr ((char *) glob, '*') == 0)
|
|
|
|
string += strlen ((char *) string) - strlen ((char *) glob);
|
|
|
|
while (*string)
|
|
|
|
{
|
|
|
|
if (FcConfigGlobMatch (glob, string))
|
|
|
|
return FcTrue;
|
|
|
|
string++;
|
|
|
|
}
|
|
|
|
return FcFalse;
|
|
|
|
case '?':
|
|
|
|
if (*string++ == '\0')
|
|
|
|
return FcFalse;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (*string++ != c)
|
|
|
|
return FcFalse;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return *string == '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
static FcBool
|
|
|
|
FcConfigGlobsMatch (const FcStrSet *globs,
|
|
|
|
const FcChar8 *string)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < globs->num; i++)
|
2005-08-24 08:21:30 +02:00
|
|
|
if (FcConfigGlobMatch (globs->strs[i], string))
|
2003-05-07 18:13:24 +02:00
|
|
|
return FcTrue;
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcConfigAcceptFilename (FcConfig *config,
|
|
|
|
const FcChar8 *filename)
|
|
|
|
{
|
|
|
|
if (FcConfigGlobsMatch (config->acceptGlobs, filename))
|
|
|
|
return FcTrue;
|
|
|
|
if (FcConfigGlobsMatch (config->rejectGlobs, filename))
|
|
|
|
return FcFalse;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
2004-12-04 20:41:10 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Manage font-pattern based font source selectors
|
|
|
|
*/
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcConfigPatternsAdd (FcConfig *config,
|
|
|
|
FcPattern *pattern,
|
|
|
|
FcBool accept)
|
|
|
|
{
|
|
|
|
FcFontSet *set = accept ? config->acceptPatterns : config->rejectPatterns;
|
|
|
|
|
|
|
|
return FcFontSetAdd (set, pattern);
|
|
|
|
}
|
|
|
|
|
|
|
|
static FcBool
|
|
|
|
FcConfigPatternsMatch (const FcFontSet *patterns,
|
|
|
|
const FcPattern *font)
|
|
|
|
{
|
|
|
|
int i;
|
2010-04-12 18:18:50 +02:00
|
|
|
|
2004-12-04 20:41:10 +01:00
|
|
|
for (i = 0; i < patterns->nfont; i++)
|
|
|
|
if (FcListPatternMatchAny (patterns->fonts[i], font))
|
|
|
|
return FcTrue;
|
|
|
|
return FcFalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
FcBool
|
|
|
|
FcConfigAcceptFont (FcConfig *config,
|
|
|
|
const FcPattern *font)
|
|
|
|
{
|
|
|
|
if (FcConfigPatternsMatch (config->acceptPatterns, font))
|
|
|
|
return FcTrue;
|
|
|
|
if (FcConfigPatternsMatch (config->rejectPatterns, font))
|
|
|
|
return FcFalse;
|
|
|
|
return FcTrue;
|
|
|
|
}
|
2006-09-05 11:24:01 +02:00
|
|
|
#define __fccfg__
|
|
|
|
#include "fcaliastail.h"
|
|
|
|
#undef __fccfg__
|