summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkira TAGOH <akira@tagoh.org>2015-11-18 16:09:43 +0900
committerAkira TAGOH <akira@tagoh.org>2018-01-18 21:48:22 +0900
commitf50a964a9f48fd2722648f39af23a2a6644e819b (patch)
tree960afb5f3a5bc848edb4ca1a28ec680d71d9d95b
parent73cc842d1dd866e4a6fda4aa422cb4a9c7a9832f (diff)
initial work to support BCP47langtag-support
-rw-r--r--Makefile.am2
-rw-r--r--Tools.mk2
-rw-r--r--configure.ac17
-rw-r--r--fc-validate/fc-validate.c60
-rw-r--r--fontconfig/fontconfig.h20
-rw-r--r--src/Makefile.am17
-rw-r--r--src/fccache.c12
-rw-r--r--src/fccfg.c8
-rw-r--r--src/fcdbg.c14
-rw-r--r--src/fcdefault.c222
-rw-r--r--src/fcdir.c12
-rw-r--r--src/fcfreetype.c4
-rw-r--r--src/fcinit.c4
-rw-r--r--src/fcint.h191
-rw-r--r--src/fclang.c29
-rw-r--r--src/fcscript.c247
-rw-r--r--src/fcstr.c168
-rw-r--r--src/fcxml.c12
18 files changed, 850 insertions, 191 deletions
diff --git a/Makefile.am b/Makefile.am
index cc3024e6..be38a658 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -21,7 +21,7 @@
# TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
-SUBDIRS=fontconfig fc-case fc-lang src \
+SUBDIRS=fontconfig fc-case fc-lang fc-script src \
fc-cache fc-cat fc-conflist fc-list fc-match \
fc-pattern fc-query fc-scan fc-validate conf.d \
its po po-conf test
diff --git a/Tools.mk b/Tools.mk
index f0fa0ec5..ed583335 100644
--- a/Tools.mk
+++ b/Tools.mk
@@ -43,7 +43,7 @@ AM_CPPFLAGS = \
$(WARN_CFLAGS)
$(TOOL): $(TSRC) $(ALIAS_FILES)
- $(AM_V_GEN) $(CC_FOR_BUILD) -o $(TOOL) $< $(AM_CPPFLAGS)
+ $(AM_V_GEN) $(CC_FOR_BUILD) $(CFLAGS) -o $(TOOL) $< $(AM_CPPFLAGS) $(LIBS)
$(TARG): $(TMPL) $(TSRC) $(DEPS)
$(AM_V_GEN) $(MAKE) $(TOOL) && \
diff --git a/configure.ac b/configure.ac
index 51b64c47..8c9729a1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -473,6 +473,22 @@ none|slight|medium|full)
esac
#
+# Check liblangtag
+#
+AC_ARG_ENABLE(liblangtag,
+ [AC_HELP_STRING([--enable-liblangtag],
+ [Use liblangtag])])
+
+if test "$enable_liblangtag" = "yes"; then
+ PKG_CHECK_MODULES([LIBLANGTAG], [liblangtag >= 0.5])
+ PKGCONFIG_REQUIRES_PRIVATELY="$PKGCONFIG_REQUIRES_PRIVATELY liblangtag"
+ AC_DEFINE_UNQUOTED(ENABLE_LIBLANGTAG, 1, [Use liblangtag])
+
+ AC_SUBST(LIBLANGTAG_CFLAGS)
+ AC_SUBST(LIBLANGTAG_LIBS)
+fi
+
+#
# Set default font directory
#
@@ -779,6 +795,7 @@ fc-match/Makefile
fc-pattern/Makefile
fc-query/Makefile
fc-scan/Makefile
+fc-script/Makefile
fc-validate/Makefile
doc/Makefile
doc/version.sgml
diff --git a/fc-validate/fc-validate.c b/fc-validate/fc-validate.c
index 2ceee202..76814085 100644
--- a/fc-validate/fc-validate.c
+++ b/fc-validate/fc-validate.c
@@ -63,6 +63,7 @@
static const struct option longopts[] = {
{"index", 1, 0, 'i'},
{"lang", 1, 0, 'l'},
+ {"script", 1, 0, 's'},
{"verbose", 0, 0, 'v'},
{"version", 0, 0, 'V'},
{"help", 0, 0, 'h'},
@@ -80,10 +81,10 @@ usage (char *program, int error)
{
FILE *file = error ? stderr : stdout;
#if HAVE_GETOPT_LONG
- fprintf (file, _("usage: %s [-Vhv] [-i index] [-l LANG] [--index index] [--lang LANG] [--verbose] [--version] [--help] font-file...\n"),
+ fprintf (file, _("usage: %s [-Vhv] [-i index] [-l LANG] [-s SCRIPT] [--index index] [--lang LANG] [--script SCRIPT] [--verbose] [--version] [--help] font-file...\n"),
program);
#else
- fprintf (file, _("usage: %s [-Vhv] [-i index] [-l LANG] font-file...\n"),
+ fprintf (file, _("usage: %s [-Vhv] [-i index] [-l LANG] [-s SCRIPT] font-file...\n"),
program);
#endif
fprintf (file, _("Validate font files and print result\n"));
@@ -91,12 +92,14 @@ usage (char *program, int error)
#if HAVE_GETOPT_LONG
fprintf (file, _(" -i, --index INDEX display the INDEX face of each font file only\n"));
fprintf (file, _(" -l, --lang=LANG set LANG instead of current locale\n"));
+ fprintf (file, _(" -s, --script=SCRIPT set SCRIPT instead of current locale\n"));
fprintf (file, _(" -v, --verbose show more detailed information\n"));
fprintf (file, _(" -V, --version display font config version and exit\n"));
fprintf (file, _(" -h, --help display this help and exit\n"));
#else
fprintf (file, _(" -i INDEX (index) display the INDEX face of each font file only\n"));
fprintf (file, _(" -l LANG (lang) set LANG instead of current locale\n"));
+ fprintf (file, _(" -s SCRIPT (script) set SCRIPT instead of current script\n"));
fprintf (file, _(" -v (verbose) show more detailed information\n"));
fprintf (file, _(" -V (version) display font config version and exit\n"));
fprintf (file, _(" -h (help) display this help and exit\n"));
@@ -110,7 +113,8 @@ main (int argc, char **argv)
int index_set = 0;
int set_index = 0;
FcChar8 *lang = NULL;
- const FcCharSet *fcs_lang = NULL;
+ FcChar8 *script = NULL;
+ const FcCharSet *fcs_lang = NULL, *fcs_script = NULL;
int err = 0;
int i;
FT_Library ftlib;
@@ -121,9 +125,9 @@ main (int argc, char **argv)
setlocale (LC_ALL, "");
#if HAVE_GETOPT_LONG
- while ((c = getopt_long (argc, argv, "i:l:mVhv", longopts, NULL)) != -1)
+ while ((c = getopt_long (argc, argv, "i:l:ms:Vhv", longopts, NULL)) != -1)
#else
- while ((c = getopt (argc, argv, "i:l:mVhv")) != -1)
+ while ((c = getopt (argc, argv, "i:l:ms:Vhv")) != -1)
#endif
{
switch (c) {
@@ -134,6 +138,9 @@ main (int argc, char **argv)
case 'l':
lang = (FcChar8 *) FcLangNormalize ((const FcChar8 *) optarg);
break;
+ case 's':
+ script = (FcChar8 *) optarg;
+ break;
case 'v':
verbose = FcTrue;
break;
@@ -156,12 +163,16 @@ main (int argc, char **argv)
if (i == argc)
usage (argv[0], 1);
- if (!lang)
+ if (!lang && !script)
lang = FcLangNormalize ((const FcChar8 *) setlocale (LC_CTYPE, NULL));
if (lang)
fcs_lang = FcLangGetCharSet (lang);
+ if (script)
+ fcs_script = FcScriptGetCharSet (script);
+
+ printf("%p:%p\n", fcs_lang, fcs_script);
if (FT_Init_FreeType (&ftlib))
{
fprintf (stderr, _("Can't initalize FreeType library\n"));
@@ -187,18 +198,40 @@ main (int argc, char **argv)
}
else
{
- FcChar32 count;
+ FcChar32 count, c;
+ FcBool eval;
fcs = FcFreeTypeCharSet (face, NULL);
- fcs_sub = FcCharSetSubtract (fcs_lang, fcs);
+ if (lang)
+ {
+ fcs_sub = FcCharSetSubtract (fcs_lang, fcs);
+ }
+ else
+ {
+ fcs_sub = FcCharSetSubtract (fcs_script, fcs);
+ }
count = FcCharSetCount (fcs_sub);
- if (count > 0)
+ if (lang)
+ eval = count > 0;
+ else
+ {
+ FcChar32 x;
+
+ c = FcCharSetCount (fcs_script);
+ x = (c - count) * 100 / c;
+ eval = x < 60;
+ }
+ if (eval)
{
FcChar32 ucs4, pos, map[FC_CHARSET_MAP_SIZE];
- printf (_("%s:%d Missing %d glyph(s) to satisfy the coverage for %s language\n"),
- argv[i], index, count, lang);
+ if (lang)
+ printf (_("%s:%d Missing %d glyph(s) to satisfy the coverage for %s language\n"),
+ argv[i], index, count, lang);
+ else
+ printf (_("%s:%d Missing %d glyph(s)[/%d] to satisfy the coverage for %s script\n",
+ argv[i], index, count, c, script);
if (verbose)
{
@@ -227,7 +260,10 @@ main (int argc, char **argv)
}
else
{
- printf (_("%s:%d Satisfy the coverage for %s language\n"), argv[i], index, lang);
+ if (lang)
+ printf (_("%s:%d Satisfy the coverage for %s language\n"), argv[i], index, lang);
+ else
+ printf (_("%s:%d Satisfy the coverage for %s script\n"), argv[i], index, script);
}
FcCharSetDestroy (fcs);
diff --git a/fontconfig/fontconfig.h b/fontconfig/fontconfig.h
index b70ce9e8..00e4fe09 100644
--- a/fontconfig/fontconfig.h
+++ b/fontconfig/fontconfig.h
@@ -252,6 +252,8 @@ typedef struct _FcLangSet FcLangSet;
typedef struct _FcRange FcRange;
+typedef struct _FcScriptSet FcScriptSet;
+
typedef struct _FcValue {
FcType type;
union {
@@ -321,6 +323,10 @@ typedef struct _FcGlobalCache FcFileCache;
typedef struct _FcBlanks FcBlanks;
+typedef struct _FcPtrList FcPtrList;
+
+typedef struct _FcPtrSet FcPtrSet;
+
typedef struct _FcStrList FcStrList;
typedef struct _FcStrSet FcStrSet;
@@ -560,6 +566,9 @@ FcPublic void
FcFontSetPrint (const FcFontSet *s);
/* fcdefault.c */
+FcPublic FcPtrSet *
+FcGetDefaultLangtags (void);
+
FcPublic FcStrSet *
FcGetDefaultLangs (void);
@@ -975,6 +984,17 @@ FcWeightToOpenType (int fc_weight);
FcPublic double
FcWeightToOpenTypeDouble (double fc_weight);
+/* fcscript.c */
+
+FcPublic const FcCharSet *
+FcScriptGetCharSet (const FcChar8 *script);
+
+FcPublic FcScriptSet *
+FcScriptSetCreate (void);
+
+FcPublic void
+FcScriptSetDestroy (FcScriptSet *ss);
+
/* fcstr.c */
FcPublic FcChar8 *
diff --git a/src/Makefile.am b/src/Makefile.am
index 80780b62..6dc3d235 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -22,6 +22,7 @@
# PERFORMANCE OF THIS SOFTWARE.
EXTRA_DIST =
+NULL =
if OS_WIN32
@@ -73,8 +74,10 @@ endif
AM_CPPFLAGS = \
-I$(top_srcdir) \
-I$(top_srcdir)/src \
+ $(EXPAT_CFLAGS) \
$(FREETYPE_CFLAGS) \
$(ICONV_CFLAGS) \
+ $(LIBLANGTAG_CFLAGS) \
$(LIBXML2_CFLAGS) \
$(EXPAT_CFLAGS) \
$(UUID_CFLAGS) \
@@ -92,6 +95,7 @@ ALIAS_FILES = fcalias.h fcaliastail.h fcftalias.h fcftaliastail.h
BUILT_SOURCES = $(ALIAS_FILES) \
../fc-case/fccase.h \
../fc-lang/fclang.h \
+ ../fc-script/fcscript.h \
stamp-fcstdint \
fcobjshash.h \
fcobjshash.gperf
@@ -102,6 +106,8 @@ noinst_PROGRAMS = fcarch
cd ../fc-case && $(MAKE) $(AM_MAKEFLAGS) fccase.h
../fc-lang/fclang.h:
cd ../fc-lang && $(MAKE) $(AM_MAKEFLAGS) fclang.h
+../fc-script/fcscript.h:
+ cd ../fc-script && $(MAKE) $(AM_MAKEFLAGS) fcscript.h
fcobjshash.gperf: Makefile stamp-fcobjshash.gperf
-@$(RM) stamp-fcobjshash.gperf
@@ -152,7 +158,9 @@ libfontconfig_la_SOURCES = \
fcobjs.h \
fcobjshash.h \
fcpat.c \
+ fcptr.c \
fcrange.c \
+ fcscript.c \
fcserialize.c \
fcstat.c \
fcstr.c \
@@ -167,7 +175,14 @@ lib_LTLIBRARIES = libfontconfig.la
libfontconfig_la_LDFLAGS = \
-version-info @LIBT_VERSION_INFO@ -no-undefined $(export_symbols)
-libfontconfig_la_LIBADD = $(ICONV_LIBS) $(FREETYPE_LIBS) $(LIBXML2_LIBS) $(EXPAT_LIBS) $(UUID_LIBS)
+libfontconfig_la_LIBADD = \
+ $(EXPAT_LIBS) \
+ $(FREETYPE_LIBS) \
+ $(ICONV_LIBS) \
+ $(LIBLANGTAG_LIBS) \
+ $(LIBXML2_LIBS) \
+ $(UUID_LIBS) \
+ $(NULL)
libfontconfig_la_DEPENDENCIES = $(fontconfig_def_dependency)
diff --git a/src/fccache.c b/src/fccache.c
index 7abb7507..7c320c58 100644
--- a/src/fccache.c
+++ b/src/fccache.c
@@ -1063,9 +1063,9 @@ FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, struct stat *dir_stat, FcSt
/*
* Subdirs
*/
- FcSerializeAlloc (serialize, dirs, dirs->num * sizeof (FcChar8 *));
- for (i = 0; i < dirs->num; i++)
- if (!FcStrSerializeAlloc (serialize, dirs->strs[i]))
+ FcSerializeAlloc (serialize, dirs, FcStrSetGetSize (dirs) * sizeof (FcChar8 *));
+ for (i = 0; i < FcStrSetGetSize (dirs); i++)
+ if (!FcStrSerializeAlloc (serialize, FcStrSetIndex (dirs, i)))
goto bail1;
/*
@@ -1106,10 +1106,10 @@ FcDirCacheBuild (FcFontSet *set, const FcChar8 *dir, struct stat *dir_stat, FcSt
if (!dirs_serialize)
goto bail2;
cache->dirs = FcPtrToOffset (cache, dirs_serialize);
- cache->dirs_count = dirs->num;
- for (i = 0; i < dirs->num; i++)
+ cache->dirs_count = FcStrSetGetSize (dirs);
+ for (i = 0; i < FcStrSetGetSize (dirs); i++)
{
- FcChar8 *d_serialize = FcStrSerialize (serialize, dirs->strs[i]);
+ FcChar8 *d_serialize = FcStrSerialize (serialize, FcStrSetIndex (dirs, i));
if (!d_serialize)
goto bail2;
dirs_serialize[i] = FcPtrToOffset (dirs_serialize, d_serialize);
diff --git a/src/fccfg.c b/src/fccfg.c
index 2351ac23..0127d3f7 100644
--- a/src/fccfg.c
+++ b/src/fccfg.c
@@ -2258,7 +2258,7 @@ FcConfigAppFontAddFile (FcConfig *config,
return FcFalse;
}
- subdirs = FcStrSetCreateEx (FCSS_GROW_BY_64);
+ subdirs = FcStrSetCreateEx (FC_SET_GROW_BY_64);
if (!subdirs)
return FcFalse;
@@ -2305,7 +2305,7 @@ FcConfigAppFontAddDir (FcConfig *config,
return FcFalse;
}
- dirs = FcStrSetCreateEx (FCSS_GROW_BY_64);
+ dirs = FcStrSetCreateEx (FC_SET_GROW_BY_64);
if (!dirs)
return FcFalse;
@@ -2365,8 +2365,8 @@ FcConfigGlobsMatch (const FcStrSet *globs,
{
int i;
- for (i = 0; i < globs->num; i++)
- if (FcStrGlobMatch (globs->strs[i], string))
+ for (i = 0; i < FcStrSetGetSize (globs); i++)
+ if (FcStrGlobMatch (FcStrSetIndex (globs, i), string))
return FcTrue;
return FcFalse;
}
diff --git a/src/fcdbg.c b/src/fcdbg.c
index 2e16a312..fec8e436 100644
--- a/src/fcdbg.c
+++ b/src/fcdbg.c
@@ -151,6 +151,20 @@ FcLangSetPrint (const FcLangSet *ls)
}
void
+FcScriptSetPrint (const FcScriptSet *ss)
+{
+ FcStrBuf buf;
+ FcChar8 init_buf[1024];
+
+ FcStrBufInit (&buf, init_buf, sizeof (init_buf));
+ if (FcNameUnparseScriptSet (&buf, ss) && FcStrBufChar (&buf, '\0'))
+ printf ("%s", buf.buf);
+ else
+ printf ("scriptset (alloc error)");
+ FcStrBufDestroy (&buf);
+}
+
+void
FcCharSetPrint (const FcCharSet *c)
{
int i, j;
diff --git a/src/fcdefault.c b/src/fcdefault.c
index 35973d79..85ef7226 100644
--- a/src/fcdefault.c
+++ b/src/fcdefault.c
@@ -25,6 +25,9 @@
#include "fcint.h"
#include <limits.h>
#include <string.h>
+#ifdef ENABLE_LIBLANGTAG
+#include <liblangtag/langtag.h>
+#endif
/* MT-safe */
@@ -44,7 +47,164 @@ static const struct {
#define NUM_FC_BOOL_DEFAULTS (int) (sizeof FcBoolDefaults / sizeof FcBoolDefaults[0])
+#ifdef ENABLE_LIBLANGTAG
+FcPtrSet *default_langtags;
+lt_tag_t *default_langtag;
+
+static int
+_tagcmp(const void *a, const void *b)
+{
+ return !lt_tag_compare (a, b);
+}
+
+FcPtrSet *
+FcGetDefaultLangtags (void)
+{
+ FcPtrSet *result;
+
+retry:
+ result = (FcPtrSet *) fc_atomic_ptr_get (&default_langtags);
+ if (!result)
+ {
+ char *langs;
+ static char *posix = "POSIX";
+ const char *p, *next;
+ char *s = NULL;
+ size_t len;
+ lt_tag_t *tag = NULL;
+ lt_error_t *error = NULL;
+
+ result = FcPtrSetCreate ((FcPtrSetDestroyFunc) lt_tag_unref, _tagcmp);
+
+ langs = getenv ("FC_LANG");
+ if (!langs || !langs[0])
+ langs = getenv ("LC_ALL");
+ if (!langs || !langs[0])
+ langs = getenv ("LC_CTYPE");
+ if (!langs || !langs[0])
+ langs = getenv ("LANG");
+ if (!langs || !langs[0])
+ langs = posix;
+
+ p = langs;
+ while ((next = strchr (p, ':')))
+ {
+ len = next - p;
+ s = malloc (sizeof (char) * (len + 1));
+ if (!s)
+ goto bail0;
+ memcpy (s, p, len);
+ s[len] = 0;
+ if (*s)
+ {
+ if (strchr (s, '@') || strchr (s, '_') || !strchr(s, '-'))
+ {
+ /* it may follows usual locale syntax */
+ tag = lt_tag_convert_from_locale_string (s, &error);
+ if (!tag)
+ {
+ /* fallback to langtag */
+ goto parse_tag;
+ }
+ }
+ else
+ {
+ parse_tag:
+ tag = lt_tag_new ();
+ if (!lt_tag_parse (tag, s, &error))
+ {
+ lt_tag_unref (tag);
+ goto bail;
+ }
+ }
+ if (!FcPtrSetAdd (result, tag))
+ goto bail;
+ }
+ free (s);
+ }
+ if (*p)
+ {
+ if (strchr (p, '@') || strchr (p, '_') || !strchr(p, '-'))
+ {
+ /* it may follows usual locale syntax */
+ tag = lt_tag_convert_from_locale_string (p, &error);
+ if (!tag)
+ {
+ /* fallback to langtag */
+ goto parse_tag2;
+ }
+ }
+ else
+ {
+ parse_tag2:
+ tag = lt_tag_new ();
+ if (!lt_tag_parse (tag, p, &error))
+ {
+ lt_tag_unref (tag);
+ goto bail;
+ }
+ }
+ if (!FcPtrSetAdd (result, tag))
+ goto bail;
+ }
+ bail:
+ if (lt_error_is_set (error, LT_ERR_ANY))
+ {
+ lt_error_unref (error);
+ bail0:
+ FcPtrSetDestroy (result);
+ result = NULL;
+ }
+ else
+ {
+ FcPtrSetConst (result);
+ if (!fc_atomic_ptr_cmpexch (&default_langtags, NULL, result))
+ {
+ FcPtrSetRefReset (result);
+ FcPtrSetDestroy (result);
+ goto retry;
+ }
+ }
+ }
+
+ return result;
+}
+
+lt_tag_t *
+FcGetDefaultLangtag (void)
+{
+ lt_tag_t *tag;
+retry:
+ tag = fc_atomic_ptr_get (&default_langtag);
+ if (!tag)
+ {
+ FcPtrSet *tags = FcGetDefaultLangtags ();
+
+ tag = FcPtrSetIndex (tags, 0);
+ if (!fc_atomic_ptr_cmpexch (&default_langtag, NULL, tag)) {
+ goto retry;
+ }
+ }
+
+ return tag;
+}
+#else
+FcPtrSet *
+FcGetDefaultLangtags (void)
+{
+ return NULL;
+}
+
+lt_tag_t *
+FcGetDefaultLangtag (void)
+{
+ return NULL;
+}
+
+#endif
+
FcStrSet *default_langs;
+static FcChar8 *default_lang; /* MT-safe */
FcStrSet *
FcGetDefaultLangs (void)
@@ -54,6 +214,28 @@ retry:
result = (FcStrSet *) fc_atomic_ptr_get (&default_langs);
if (!result)
{
+#ifdef ENABLE_LIBLANGTAG
+ FcPtrSet *tags = FcGetDefaultLangtags ();
+ FcPtrList *list = FcPtrListCreate (tags);
+ lt_tag_t *tag;
+
+ result = FcStrSetCreate ();
+
+ while ((tag = FcPtrListNext (list)))
+ {
+ lt_error_t *error = NULL;
+ char *lang = lt_tag_convert_to_locale (tag, &error);
+
+ if (lt_error_is_set (error, LT_ERR_ANY))
+ FcStrSetAdd (result, (const FcChar8 *) "en");
+ else
+ if (!FcStrSetAddLangs (result, lang))
+ FcStrSetAdd (result, (const FcChar8 *) "en");
+ if (lang)
+ free (lang);
+ }
+ FcPtrListDone (list);
+#else
char *langs;
result = FcStrSetCreate ();
@@ -72,10 +254,11 @@ retry:
}
else
FcStrSetAdd (result, (const FcChar8 *) "en");
+#endif
- FcRefSetConst (&result->ref);
+ FcStrSetConst (result);
if (!fc_atomic_ptr_cmpexch (&default_langs, NULL, result)) {
- FcRefInit (&result->ref, 1);
+ FcStrSetRefReset (result);
FcStrSetDestroy (result);
goto retry;
}
@@ -84,8 +267,6 @@ retry:
return result;
}
-static FcChar8 *default_lang; /* MT-safe */
-
FcChar8 *
FcGetDefaultLang (void)
{
@@ -94,8 +275,23 @@ retry:
lang = fc_atomic_ptr_get (&default_lang);
if (!lang)
{
+#ifdef ENABLE_LIBLANGTAG
+ lt_tag_t *tag = FcGetDefaultLangtag ();
+
+ if (tag)
+ {
+ char *l = lt_tag_convert_to_locale (tag, NULL);
+
+ if (l)
+ {
+ lang = FcLangNormalize ((const FcChar8 *) l);
+ free (l);
+ }
+ }
+#else
FcStrSet *langs = FcGetDefaultLangs ();
- lang = FcStrdup (langs->strs[0]);
+ lang = FcStrdup (FcStrSetIndex (langs, 0));
+#endif
if (!fc_atomic_ptr_cmpexch (&default_lang, NULL, lang)) {
free (lang);
@@ -214,19 +410,33 @@ retry:
void
FcDefaultFini (void)
{
+#ifdef ENABLE_LIBLANGTAG
+ lt_tag_t *lang;
+ FcPtrSet *langs;
+#else
FcChar8 *lang;
FcStrSet *langs;
+#endif
FcChar8 *prgname;
lang = fc_atomic_ptr_get (&default_lang);
if (lang && fc_atomic_ptr_cmpexch (&default_lang, lang, NULL)) {
+#ifdef ENABLE_LIBLANGTAG
+ lt_tag_unref (lang);
+#else
free (lang);
+#endif
}
langs = fc_atomic_ptr_get (&default_langs);
if (langs && fc_atomic_ptr_cmpexch (&default_langs, langs, NULL)) {
- FcRefInit (&langs->ref, 1);
+#ifdef ENABLE_LIBLANGTAG
+ FcPtrSetRefReset (langs);
+ FcPtrSetDestroy (langs);
+#else
+ FcStrSetRefReset (langs);
FcStrSetDestroy (langs);
+#endif
}
prgname = fc_atomic_ptr_get (&default_prgname);
diff --git a/src/fcdir.c b/src/fcdir.c
index bfcdf956..c57b0af5 100644
--- a/src/fcdir.c
+++ b/src/fcdir.c
@@ -223,7 +223,7 @@ FcDirScanConfig (FcFontSet *set,
goto bail;
}
- files = FcStrSetCreateEx (FCSS_ALLOW_DUPLICATES | FCSS_GROW_BY_64);
+ files = FcStrSetCreateEx (FC_SET_ALLOW_DUPLICATES | FC_SET_GROW_BY_64);
if (!files)
{
ret = FcFalse;
@@ -244,13 +244,13 @@ FcDirScanConfig (FcFontSet *set,
/*
* Sort files to make things prettier
*/
- qsort(files->strs, files->num, sizeof(FcChar8 *), cmpstringp);
+ FcStrSetSort (files, cmpstringp);
/*
* Scan file files to build font patterns
*/
- for (i = 0; i < files->num; i++)
- FcFileScanConfig (set, dirs, files->strs[i], config);
+ for (i = 0; i < FcStrSetGetSize (files); i++)
+ FcFileScanConfig (set, dirs, FcStrSetIndex (files, i), config);
bail2:
FcStrSetDestroy (files);
@@ -308,7 +308,7 @@ FcDirCacheScan (const FcChar8 *dir, FcConfig *config)
if (!set)
goto bail;
- dirs = FcStrSetCreateEx (FCSS_GROW_BY_64);
+ dirs = FcStrSetCreateEx (FC_SET_GROW_BY_64);
if (!dirs)
goto bail1;
@@ -369,7 +369,7 @@ FcDirCacheRescan (const FcChar8 *dir, FcConfig *config)
d = FcStrdup (dir);
if (FcStatChecksum (d, &dir_stat) < 0)
goto bail;
- dirs = FcStrSetCreateEx (FCSS_GROW_BY_64);
+ dirs = FcStrSetCreateEx (FC_SET_GROW_BY_64);
if (!dirs)
goto bail;
diff --git a/src/fcfreetype.c b/src/fcfreetype.c
index 49fb39f2..db888c89 100644
--- a/src/fcfreetype.c
+++ b/src/fcfreetype.c
@@ -1180,6 +1180,7 @@ FcFreeTypeQueryFaceInternal (const FT_Face face,
FcBool variable_size = FcFalse;
FcCharSet *cs;
FcLangSet *ls;
+ FcScriptSet *ss;
#if 0
FcChar8 *family = 0;
#endif
@@ -1952,6 +1953,9 @@ FcFreeTypeQueryFaceInternal (const FT_Face face,
if (!symbol)
{
+ ss = FcFreeTypeScriptSet (cs);
+ if (!ss)
+ goto bail2;
if (ls_share && *ls_share)
ls = FcLangSetCopy (*ls_share);
else
diff --git a/src/fcinit.c b/src/fcinit.c
index 8bb0fd4f..105bfa02 100644
--- a/src/fcinit.c
+++ b/src/fcinit.c
@@ -76,6 +76,7 @@ FcInitLoadOwnConfig (FcConfig *config)
}
FcInitDebug ();
+ FcLangInit ();
if (!FcConfigParseAndLoad (config, 0, FcTrue))
{
@@ -88,7 +89,7 @@ FcInitLoadOwnConfig (FcConfig *config)
}
(void) FcConfigParseOnly (config, (const FcChar8 *)FC_TEMPLATEDIR, FcFalse);
- if (config->cacheDirs && config->cacheDirs->num == 0)
+ if (config->cacheDirs && FcStrSetGetSize (config->cacheDirs) == 0)
{
FcChar8 *prefix, *p;
size_t plen;
@@ -195,6 +196,7 @@ FcFini (void)
FcDefaultFini ();
FcObjectFini ();
FcConfigPathFini ();
+ FcLangFini ();
}
/*
diff --git a/src/fcint.h b/src/fcint.h
index 537023fc..acb583bb 100644
--- a/src/fcint.h
+++ b/src/fcint.h
@@ -50,6 +50,9 @@
#include "fcdeprecate.h"
#include "fcmutex.h"
#include "fcatomic.h"
+#ifdef ENABLE_LIBLANGTAG
+#include <liblangtag/langtag.h>
+#endif
#ifndef FC_CONFIG_PATH
#define FC_CONFIG_PATH "fonts.conf"
@@ -82,18 +85,19 @@ extern pfnSHGetFolderPathA pSHGetFolderPathA;
#define FC_UNUSED
#endif
-#define FC_DBG_MATCH 1
-#define FC_DBG_MATCHV 2
-#define FC_DBG_EDIT 4
-#define FC_DBG_FONTSET 8
-#define FC_DBG_CACHE 16
-#define FC_DBG_CACHEV 32
-#define FC_DBG_PARSE 64
-#define FC_DBG_SCAN 128
-#define FC_DBG_SCANV 256
-#define FC_DBG_CONFIG 1024
-#define FC_DBG_LANGSET 2048
-#define FC_DBG_MATCH2 4096
+#define FC_DBG_MATCH 1
+#define FC_DBG_MATCHV 2
+#define FC_DBG_EDIT 4
+#define FC_DBG_FONTSET 8
+#define FC_DBG_CACHE 16
+#define FC_DBG_CACHEV 32
+#define FC_DBG_PARSE 64
+#define FC_DBG_SCAN 128
+#define FC_DBG_SCANV 256
+#define FC_DBG_CONFIG 1024
+#define FC_DBG_LANGSET 2048
+#define FC_DBG_MATCH2 4096
+#define FC_DBG_SCRIPTSET 8192
#define _FC_ASSERT_STATIC1(_line, _cond) typedef int _static_assert_on_line_##_line##_failed[(_cond)?1:-1] FC_UNUSED
#define _FC_ASSERT_STATIC0(_line, _cond) _FC_ASSERT_STATIC1 (_line, (_cond))
@@ -363,24 +367,37 @@ struct _FcCharSet {
FcCharLeaf))
#define FcCharSetNumbers(c) FcOffsetMember(c,numbers_offset,FcChar16)
-#define FCSS_DEFAULT 0 /* default behavior */
-#define FCSS_ALLOW_DUPLICATES 1 /* allows for duplicate strings in the set */
-#define FCSS_GROW_BY_64 2 /* grows buffer by 64 elements instead of 1 */
+#define FC_SET_DEFAULT 0 /* default behavior */
+#define FC_SET_ALLOW_DUPLICATES 1 /* allows for duplicate strings in the set */
+#define FC_SET_GROW_BY_64 2 /* grows buffer by 64 elements instead of 1 */
+
+#define FcPtrSetHasControlBit(s,c) (s->control & c)
+#define FcPtrSetHasControlBits(s,c) ( (c) == (s->control & (c)) )
+
+typedef void (* FcPtrSetDestroyFunc) (void *p);
+typedef int (* FcPtrSetCompareFunc) (const void *a, const void *b);
+
+struct _FcPtrSet {
+ FcRef ref; /* reference count */
+ int num;
+ int size;
+ void **ptrs;
+ FcPtrSetDestroyFunc destroy_func;
+ FcPtrSetCompareFunc compare_func;
+ unsigned int control; /* control bits for set behavior */
+};
-#define FcStrSetHasControlBit(s,c) (s->control & c)
-#define FcStrSetHasControlBits(s,c) ( (c) == (s->control & (c)) )
+struct _FcPtrList {
+ FcPtrSet *set;
+ int n;
+};
struct _FcStrSet {
- FcRef ref; /* reference count */
- int num;
- int size;
- FcChar8 **strs;
- unsigned int control; /* control bits for set behavior */
+ FcPtrSet ptrset;
};
struct _FcStrList {
- FcStrSet *set;
- int n;
+ FcPtrList ptrlist;
};
typedef struct _FcStrBuf {
@@ -873,6 +890,13 @@ FcPrivate void
FcInitDebug (void);
/* fcdefault.c */
+#ifndef ENABLE_LIBLANGTAG
+typedef lt_tag_t void
+#endif
+
+FcPrivate lt_tag_t *
+FcGetDefaultLangtag (void);
+
FcPrivate FcChar8 *
FcGetDefaultLang (void);
@@ -975,6 +999,13 @@ void
FcRuleDestroy (FcRule *rule);
/* fclang.c */
+
+FcPrivate void
+FcLangInit (void);
+
+FcPrivate void
+FcLangFini (void);
+
FcPrivate FcLangSet *
FcFreeTypeLangSet (const FcCharSet *charset,
const FcChar8 *exclusiveLang);
@@ -1169,6 +1200,87 @@ FcValueListSerializeAlloc (FcSerialize *serialize, const FcValueList *pat);
FcPrivate FcValueList *
FcValueListSerialize (FcSerialize *serialize, const FcValueList *pat);
+/* fcptr.c */
+
+FcPrivate FcPtrSet *
+FcPtrSetInit (FcPtrSet *set,
+ unsigned int control,
+ FcPtrSetDestroyFunc destroy_func,
+ FcPtrSetCompareFunc compare_func);
+
+FcPrivate FcPtrSet *
+FcPtrSetCreate (FcPtrSetDestroyFunc destroy_func,
+ FcPtrSetCompareFunc compare_func);
+
+FcPrivate FcPtrSet *
+FcPtrSetCreateEx (unsigned int control,
+ FcPtrSetDestroyFunc destroy_func,
+ FcPtrSetCompareFunc compare_func);
+
+FcPrivate FcPtrSet *
+FcPtrSetReference (FcPtrSet *set);
+
+FcPrivate void
+FcPtrSetConst (FcPtrSet *set);
+
+FcPrivate void
+FcPtrSetRefReset (FcPtrSet *set);
+
+FcPrivate FcBool
+FcPtrSetFini (FcPtrSet *set);
+
+FcPrivate void
+FcPtrSetDestroy (FcPtrSet *set);
+
+FcPrivate int
+FcPtrSetGetSize (const FcPtrSet *set);
+
+FcPrivate void *
+FcPtrSetIndex (const FcPtrSet *set,
+ int idx);
+
+FcPrivate int
+FcPtrSetGetAllocatedSize (const FcPtrSet *set);
+
+FcPrivate void
+FcPtrSetSort (FcPtrSet *set,
+ FcPtrSetCompareFunc func);
+
+FcPrivate FcBool
+FcPtrSetAdd (FcPtrSet *set,
+ void *p);
+
+FcPrivate FcBool
+FcPtrSetDel (FcPtrSet *set,
+ const void *p);
+
+FcPrivate FcBool
+FcPtrSetMember (FcPtrSet *set,
+ const void *p);
+
+FcPrivate FcBool
+FcPtrSetEqual (FcPtrSet *sa,
+ FcPtrSet *sb);
+
+FcPrivate FcPtrList *
+FcPtrListInit (FcPtrList *list,
+ FcPtrSet *set);
+
+FcPrivate FcPtrList *
+FcPtrListCreate (FcPtrSet *set);
+
+FcPrivate void
+FcPtrListFirst (FcPtrList *list);
+
+FcPrivate void *
+FcPtrListNext (FcPtrList *list);
+
+FcPrivate void
+FcPtrListFini (FcPtrList *list);
+
+FcPrivate void
+FcPtrListDone (FcPtrList *list);
+
/* fcrender.c */
/* fcmatrix.c */
@@ -1198,6 +1310,14 @@ FcRangeSerializeAlloc (FcSerialize *serialize, const FcRange *r);
FcPrivate FcRange *
FcRangeSerialize (FcSerialize *serialize, const FcRange *r);
+/* fcscript.c */
+
+FcPrivate FcScriptSet *
+FcFreeTypeScriptSet (const FcCharSet *charset);
+
+FcPrivate FcBool
+FcNameUnparseScriptSet (FcStrBuf *buf, const FcScriptSet *ss);
+
/* fcstat.c */
FcPrivate int
@@ -1216,11 +1336,28 @@ FcIsFsMtimeBroken (const FcChar8 *dir);
FcPrivate FcStrSet *
FcStrSetCreateEx (unsigned int control);
-FcPrivate FcBool
-FcStrSetAddLangs (FcStrSet *strs, const char *languages);
+FcPrivate int
+FcStrSetGetSize (const FcStrSet *set);
+
+FcPrivate int
+FcStrSetGetAllocatedSize (const FcStrSet *set);
+
+FcPrivate const FcChar8 *
+FcStrSetIndex (const FcStrSet *set,
+ int idx);
FcPrivate void
-FcStrSetSort (FcStrSet * set);
+FcStrSetConst (FcStrSet *set);
+
+FcPrivate void
+FcStrSetRefReset (FcStrSet *set);
+
+FcPrivate void
+FcStrSetSort (FcStrSet *set,
+ FcPtrSetCompareFunc func);
+
+FcPrivate FcBool
+FcStrSetAddLangs (FcStrSet *strs, const char *languages);
FcPrivate void
FcStrBufInit (FcStrBuf *buf, FcChar8 *init, int size);
diff --git a/src/fclang.c b/src/fclang.c
index eadf34bf..a36821ed 100644
--- a/src/fclang.c
+++ b/src/fclang.c
@@ -24,6 +24,9 @@
#include "fcint.h"
#include "fcftint.h"
+#ifdef ENABLE_LIBLANGTAG
+#include <liblangtag/langtag.h>
+#endif
/* Objects MT-safe for readonly access. */
@@ -468,6 +471,22 @@ FcGetLangs (void)
return langs;
}
+void
+FcLangInit (void)
+{
+#ifdef ENABLE_LIBLANGTAG
+ lt_db_initialize ();
+#endif
+}
+
+void
+FcLangFini (void)
+{
+#ifdef ENABLE_LIBLANGTAG
+ lt_db_finalize ();
+#endif
+}
+
FcLangSet *
FcLangSetCreate (void)
{
@@ -778,10 +797,10 @@ FcLangSetPromote (const FcChar8 *lang, FcValuePromotionBuffer *vbuf)
else
{
buf->ls.extra = &buf->strs;
- buf->strs.num = 1;
- buf->strs.size = 1;
- buf->strs.strs = &buf->str;
- FcRefInit (&buf->strs.ref, 1);
+ buf->strs.ptrset.num = 1;
+ buf->strs.ptrset.size = 1;
+ buf->strs.ptrset.ptrs = (void **)&buf->str;
+ FcRefInit (&buf->strs.ptrset.ref, 1);
buf->str = (FcChar8 *) lang;
}
}
@@ -798,7 +817,7 @@ FcLangSetHash (const FcLangSet *ls)
for (i = 0; i < count; i++)
h ^= ls->map[i];
if (ls->extra)
- h ^= ls->extra->num;
+ h ^= FcStrSetGetSize (ls->extra);
return h;
}
diff --git a/src/fcscript.c b/src/fcscript.c
new file mode 100644
index 00000000..cb630cb5
--- /dev/null
+++ b/src/fcscript.c
@@ -0,0 +1,247 @@
+/*
+ * fontconfig/src/fcscript.c
+ *
+ * Copyright © 2002 Keith Packard
+ *
+ * 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 the author(s) not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The authors make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "fcint.h"
+#include "fcftint.h"
+
+/* Objects MT-safe for readonly access. */
+
+typedef struct {
+ const FcChar8 script[8];
+ const FcCharSet charset;
+} FcScriptCharSet;
+
+#include "../fc-script/fcscript.h"
+
+struct _FcScriptSet {
+ FcChar32 map_size;
+ FcChar32 map[NUM_SCRIPT_SET_MAP];
+};
+
+static void
+FcScriptSetBitSet (FcScriptSet *ss,
+ unsigned int id)
+{
+ unsigned int bucket;
+
+ id = fcScriptCharSetIndices[id];
+ bucket = id >> 5;
+ if (bucket >= ss->map_size)
+ return; /* shouldn't happen really */
+
+ ss->map[bucket] |= ((FcChar32) 1 << (id & 0x1f));
+}
+
+static FcBool
+FcScriptSetBitGet (const FcScriptSet *ss,
+ unsigned int id)
+{
+ unsigned int bucket;
+
+ id = fcScriptCharSetIndices[id];
+ bucket = id >> 5;
+ if (bucket >= ss->map_size)
+ return FcFalse;
+
+ return ((ss->map[bucket] >> (id & 0x1f)) & 1) ? FcTrue : FcFalse;
+}
+
+static void
+FcScriptSetBitReset (FcScriptSet *ss,
+ unsigned int id)
+{
+ unsigned int bucket;
+
+ id = fcScriptCharSetIndices[id];
+ bucket = id >> 5;
+ if (bucket >= ss->map_size)
+ return; /* shouldn't happen really */
+
+ ss->map[bucket] &= ~((FcChar32) 1 << (id & 0x1f));
+}
+
+FcScriptSet *
+FcFreeTypeScriptSet (const FcCharSet *charset)
+{
+ static const int threshold = 60;
+ int i, j, avail;
+ FcChar32 missing, count;
+ FcScriptSet *ss;
+
+ ss = FcScriptSetCreate ();
+ if (!ss)
+ return 0;
+ if (FcDebug() & FC_DBG_SCRIPTSET)
+ {
+ printf ("font scriptset");
+ FcCharSetPrint (charset);
+ printf ("\n");
+ }
+ for (i = 0; i < NUM_SCRIPT_CHAR_SET; i++)
+ {
+ if (FcDebug() & FC_DBG_SCRIPTSET)
+ {
+ printf ("%s charset", fcScriptCharSets[i].script);
+ FcCharSetPrint (&fcScriptCharSets[i].charset);
+ printf ("\n");
+ }
+
+#if 0
+ /*
+ * Check for Han charsets to make fonts
+ * which advertise support for a single language
+ * not support other Han languages
+ */
+ if (exclusiveCharset &&
+ FcFreeTypeIsExclusiveLang (fcLangCharSets[i].lang))
+ {
+ if (fcLangCharSets[i].charset.num != exclusiveCharset->num)
+ continue;
+
+ for (j = 0; j < fcLangCharSets[i].charset.num; j++)
+ if (FcCharSetLeaf(&fcLangCharSets[i].charset, j) !=
+ FcCharSetLeaf(exclusiveCharset, j))
+ continue;
+ }
+#endif
+ count = FcCharSetCount (&fcScriptCharSets[i].charset);
+ missing = FcCharSetSubtractCount (&fcScriptCharSets[i].charset, charset);
+ avail = (count - missing) * 100 / count;
+ if (FcDebug() & FC_DBG_SCANV)
+ {
+ if (avail < threshold && missing < 10)
+ {
+ FcCharSet *missed = FcCharSetSubtract (&fcScriptCharSets[i].charset,
+ charset);
+ FcChar32 ucs4;
+ FcChar32 map[FC_CHARSET_MAP_SIZE];
+ FcChar32 next;
+
+ printf ("\n%s(%u) ", fcScriptCharSets[i].script, missing);
+ printf ("{");
+ for (ucs4 = FcCharSetFirstPage (missed, map, &next);
+ ucs4 != FC_CHARSET_DONE;
+ ucs4 = FcCharSetNextPage (missed, map, &next))
+ {
+ int i, j;
+ for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
+ if (map[i])
+ {
+ for (j = 0; j < 32; j++)
+ if (map[i] & (1 << j))
+ printf (" %04x", ucs4 + i * 32 + j);
+ }
+ }
+ printf (" }\n\t");
+ FcCharSetDestroy (missed);
+ }
+ else
+ printf ("%s(%u) ", fcScriptCharSets[i].script, missing);
+ }
+ if (avail >= threshold)
+ FcScriptSetBitSet (ss, i);
+ }
+
+ if (FcDebug() & FC_DBG_SCANV)
+ printf ("\n");
+
+ printf ("scriptset:\n");
+ FcScriptSetPrint (ss);
+ printf ("\n");
+
+ return ss;
+}
+
+const FcCharSet *
+FcScriptGetCharSet (const FcChar8 *script)
+{
+ int i;
+
+ for (i = 0; i < NUM_SCRIPT_CHAR_SET; i++)
+ {
+ if (FcStrCmpIgnoreCase (script, fcScriptCharSets[i].script) == 0)
+ {
+ volatile FcCharSet *cs = &fcScriptCharSets[i].charset;
+ printf("%p\n", cs);
+// __asm__ volatile("int $03");
+ return cs;
+// return &fcScriptCharSets[i].charset;
+ }
+ }
+
+ return NULL;
+}
+
+FcScriptSet *
+FcScriptSetCreate (void)
+{
+ FcScriptSet *ss;
+
+ ss = malloc (sizeof (FcScriptSet));
+ if (!ss)
+ return NULL;
+ memset (ss->map, '\0', sizeof (ss->map));
+ ss->map_size = NUM_SCRIPT_SET_MAP;
+
+ return ss;
+}
+
+void
+FcScriptSetDestroy (FcScriptSet *ss)
+{
+ free (ss);
+}
+
+FcBool
+FcNameUnparseScriptSet (FcStrBuf *buf, const FcScriptSet *ss)
+{
+ int i, bit, count;
+ FcChar32 bits;
+ FcBool first = FcTrue;
+
+ count = FC_MIN (ss->map_size, NUM_SCRIPT_SET_MAP);
+ for (i = 0; i < count; i++)
+ {
+ if ((bits = ss->map[i]))
+ {
+ for (bit = 0; bit <= 31; bit++)
+ if (bits & (1 << bit))
+ {
+ int id = (i << 5) | bit;
+ if (!first)
+ if (!FcStrBufChar (buf, '|'))
+ return FcFalse;
+ if (!FcStrBufString (buf, fcScriptCharSets[fcScriptCharSetIndicesInv[id]].script))
+ return FcFalse;
+ first = FcFalse;
+ }
+ }
+ }
+ return FcTrue;
+}
+
+#define __fcscript__
+#include "fcaliastail.h"
+#include "fcftaliastail.h"
+#undef __fcscript__
diff --git a/src/fcstr.c b/src/fcstr.c
index b65492d8..8c64ac93 100644
--- a/src/fcstr.c
+++ b/src/fcstr.c
@@ -880,7 +880,7 @@ FcStrBuildFilename (const FcChar8 *path,
if (!path)
return NULL;
- sset = FcStrSetCreateEx (FCSS_ALLOW_DUPLICATES | FCSS_GROW_BY_64);
+ sset = FcStrSetCreateEx (FC_SET_ALLOW_DUPLICATES | FC_SET_GROW_BY_64);
if (!sset)
return NULL;
@@ -901,7 +901,7 @@ FcStrBuildFilename (const FcChar8 *path,
{
len += strlen ((const char *)s) + 1;
}
- list->n = 0;
+ FcStrListFirst (list);
ret = malloc (sizeof (FcChar8) * (len + 1));
if (!ret)
goto bail2;
@@ -1130,96 +1130,56 @@ FcStrCanonFilename (const FcChar8 *s)
FcStrSet *
FcStrSetCreate (void)
{
- return FcStrSetCreateEx (FCSS_DEFAULT);
+ return FcStrSetCreateEx (FC_SET_DEFAULT);
}
FcStrSet *
FcStrSetCreateEx (unsigned int control)
{
- FcStrSet *set = malloc (sizeof (FcStrSet));
- if (!set)
- return 0;
- FcRefInit (&set->ref, 1);
- set->num = 0;
- set->size = 0;
- set->strs = 0;
- set->control = control;
- return set;
+ FcStrSet *set = malloc (sizeof (FcStrSet));
+
+ return (FcStrSet *) FcPtrSetInit (&set->ptrset, control,
+ (FcPtrSetDestroyFunc)FcStrFree,
+ (FcPtrSetCompareFunc)FcStrCmp);
}
-static FcBool
-_FcStrSetGrow (FcStrSet *set, int growElements)
+int
+FcStrSetGetSize (const FcStrSet *set)
{
- /* accommodate an additional NULL entry at the end of the array */
- FcChar8 **strs = malloc ((set->size + growElements + 1) * sizeof (FcChar8 *));
- if (!strs)
- return FcFalse;
- if (set->num)
- memcpy (strs, set->strs, set->num * sizeof (FcChar8 *));
- if (set->strs)
- free (set->strs);
- set->size = set->size + growElements;
- set->strs = strs;
- return FcTrue;
+ return FcPtrSetGetSize (&set->ptrset);
}
-static FcBool
-_FcStrSetAppend (FcStrSet *set, FcChar8 *s)
+int
+FcStrSetGetAllocatedSize (const FcStrSet *set)
{
- if (!FcStrSetHasControlBit (set, FCSS_ALLOW_DUPLICATES))
- {
- if (FcStrSetMember (set, s))
- {
- FcStrFree (s);
- return FcTrue;
- }
- }
- if (set->num == set->size)
- {
- int growElements = FcStrSetHasControlBit (set, FCSS_GROW_BY_64) ? 64 : 1;
- if (!_FcStrSetGrow(set, growElements))
- return FcFalse;
- }
- set->strs[set->num++] = s;
- set->strs[set->num] = 0;
- return FcTrue;
+ return FcPtrSetGetAllocatedSize (&set->ptrset);
+}
+
+const FcChar8 *
+FcStrSetIndex (const FcStrSet *set,
+ int idx)
+{
+ return FcPtrSetIndex (&set->ptrset, idx);
}
FcBool
FcStrSetMember (FcStrSet *set, const FcChar8 *s)
{
- int i;
-
- for (i = 0; i < set->num; i++)
- if (!FcStrCmp (set->strs[i], s))
- return FcTrue;
- return FcFalse;
+ return FcPtrSetMember (&set->ptrset, s);
}
FcBool
FcStrSetEqual (FcStrSet *sa, FcStrSet *sb)
{
- int i;
- if (sa->num != sb->num)
- return FcFalse;
- for (i = 0; i < sa->num; i++)
- if (!FcStrSetMember (sb, sa->strs[i]))
- return FcFalse;
- return FcTrue;
+ return FcPtrSetEqual (&sa->ptrset, &sb->ptrset);
}
FcBool
FcStrSetAdd (FcStrSet *set, const FcChar8 *s)
{
FcChar8 *new = FcStrCopy (s);
- if (!new)
- return FcFalse;
- if (!_FcStrSetAppend (set, new))
- {
- FcStrFree (new);
- return FcFalse;
- }
- return FcTrue;
+
+ return FcPtrSetAdd (&set->ptrset, new);
}
FcBool
@@ -1228,12 +1188,8 @@ FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
FcChar8 *new = FcStrCopyFilename (s);
if (!new)
return FcFalse;
- if (!_FcStrSetAppend (set, new))
- {
- FcStrFree (new);
- return FcFalse;
- }
- return FcTrue;
+
+ return FcPtrSetAdd (&set->ptrset, new);
}
FcBool
@@ -1283,52 +1239,40 @@ FcStrSetAddLangs (FcStrSet *strs, const char *languages)
FcBool
FcStrSetDel (FcStrSet *set, const FcChar8 *s)
{
- int i;
-
- for (i = 0; i < set->num; i++)
- if (!FcStrCmp (set->strs[i], s))
- {
- FcStrFree (set->strs[i]);
- /*
- * copy remaining string pointers and trailing
- * NULL
- */
- memmove (&set->strs[i], &set->strs[i+1],
- (set->num - i) * sizeof (FcChar8 *));
- set->num--;
- return FcTrue;
- }
- return FcFalse;
+ return FcPtrSetDel (&set->ptrset, s);
}
/* TODO Make public */
static FcStrSet *
FcStrSetReference (FcStrSet *set)
{
- if (FcRefIsConst (&set->ref))
- return set;
-
- FcRefInc (&set->ref);
- return set;
+ return (FcStrSet *) FcPtrSetReference (&set->ptrset);
}
void
-FcStrSetDestroy (FcStrSet *set)
+FcStrSetConst (FcStrSet *set)
{
- int i;
+ FcPtrSetConst (&set->ptrset);
+}
- /* We rely on this in FcGetDefaultLangs for caching. */
- if (FcRefIsConst (&set->ref))
- return;
+void
+FcStrSetRefReset (FcStrSet *set)
+{
+ FcPtrSetRefReset (&set->ptrset);
+}
- if (FcRefDec (&set->ref) != 1)
- return;
+void
+FcStrSetDestroy (FcStrSet *set)
+{
+ if (FcPtrSetFini (&set->ptrset))
+ free (set);
+}
- for (i = 0; i < set->num; i++)
- FcStrFree (set->strs[i]);
- if (set->strs)
- free (set->strs);
- free (set);
+void
+FcStrSetSort (FcStrSet *set,
+ FcPtrSetCompareFunc func)
+{
+ FcPtrSetSort (&set->ptrset, func);
}
FcStrList *
@@ -1337,32 +1281,26 @@ FcStrListCreate (FcStrSet *set)
FcStrList *list;
list = malloc (sizeof (FcStrList));
- if (!list)
- return 0;
- list->set = set;
- FcStrSetReference (set);
- list->n = 0;
- return list;
+
+ return (FcStrList *) FcPtrListInit (&list->ptrlist, &set->ptrset);
}
void
FcStrListFirst (FcStrList *list)
{
- list->n = 0;
+ FcPtrListFirst (&list->ptrlist);
}
FcChar8 *
FcStrListNext (FcStrList *list)
{
- if (list->n >= list->set->num)
- return 0;
- return list->set->strs[list->n++];
+ return FcPtrListNext (&list->ptrlist);
}
void
FcStrListDone (FcStrList *list)
{
- FcStrSetDestroy (list->set);
+ FcPtrListFini (&list->ptrlist);
free (list);
}
diff --git a/src/fcxml.c b/src/fcxml.c
index 22b3211e..f0856f01 100644
--- a/src/fcxml.c
+++ b/src/fcxml.c
@@ -3190,7 +3190,7 @@ FcConfigParseAndLoadDir (FcConfig *config,
strcat ((char *) file, "/");
base = file + strlen ((char *) file);
- files = FcStrSetCreateEx (FCSS_GROW_BY_64);
+ files = FcStrSetCreateEx (FC_SET_GROW_BY_64);
if (!files)
{
ret = FcFalse;
@@ -3224,13 +3224,13 @@ FcConfigParseAndLoadDir (FcConfig *config,
if (ret)
{
int i;
- qsort (files->strs, files->num, sizeof (FcChar8 *),
- (int (*)(const void *, const void *)) FcSortCmpStr);
- for (i = 0; ret && i < files->num; i++)
+
+ FcStrSetSort (files, FcSortCmpStr);
+ for (i = 0; ret && i < FcStrSetGetSize (files); i++)
if (load)
- ret = FcConfigParseAndLoad (config, files->strs[i], complain);
+ ret = FcConfigParseAndLoad (config, FcStrSetIndex (files, i), complain);
else
- ret = FcConfigParseOnly (config, files->strs[i], complain);
+ ret = FcConfigParseOnly (config, FcStrSetIndex (files, i), complain);
}
bail3:
FcStrSetDestroy (files);