aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/extras/fontconfig/src
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/extras/fontconfig/src')
-rw-r--r--nx-X11/extras/fontconfig/src/Makefile.am110
-rw-r--r--nx-X11/extras/fontconfig/src/Makefile.in611
-rw-r--r--nx-X11/extras/fontconfig/src/fcatomic.c210
-rw-r--r--nx-X11/extras/fontconfig/src/fcblanks.c92
-rw-r--r--nx-X11/extras/fontconfig/src/fccache.c1168
-rw-r--r--nx-X11/extras/fontconfig/src/fccfg.c1892
-rw-r--r--nx-X11/extras/fontconfig/src/fccharset.c1231
-rw-r--r--nx-X11/extras/fontconfig/src/fcdbg.c363
-rw-r--r--nx-X11/extras/fontconfig/src/fcdefault.c152
-rw-r--r--nx-X11/extras/fontconfig/src/fcdir.c270
-rw-r--r--nx-X11/extras/fontconfig/src/fcfreetype.c2847
-rw-r--r--nx-X11/extras/fontconfig/src/fcfs.c82
-rw-r--r--nx-X11/extras/fontconfig/src/fcinit.c265
-rw-r--r--nx-X11/extras/fontconfig/src/fcint.h773
-rw-r--r--nx-X11/extras/fontconfig/src/fclang.c686
-rw-r--r--nx-X11/extras/fontconfig/src/fclist.c499
-rw-r--r--nx-X11/extras/fontconfig/src/fcmatch.c852
-rw-r--r--nx-X11/extras/fontconfig/src/fcmatrix.c117
-rw-r--r--nx-X11/extras/fontconfig/src/fcname.c611
-rw-r--r--nx-X11/extras/fontconfig/src/fcpat.c1202
-rw-r--r--nx-X11/extras/fontconfig/src/fcstr.c1000
-rw-r--r--nx-X11/extras/fontconfig/src/fcxml.c2388
-rwxr-xr-xnx-X11/extras/fontconfig/src/fontconfig.def.in163
23 files changed, 17584 insertions, 0 deletions
diff --git a/nx-X11/extras/fontconfig/src/Makefile.am b/nx-X11/extras/fontconfig/src/Makefile.am
new file mode 100644
index 000000000..f24f44e99
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/Makefile.am
@@ -0,0 +1,110 @@
+#
+# $Id: Makefile.am,v 1.3 2005/06/28 01:01:14 alanc Exp $
+#
+# Copyright © 2003 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 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.
+#
+# KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+# EVENT SHALL KEITH PACKARD 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.
+
+if OS_WIN32
+
+no_undefined = -no-undefined
+export_symbols = -export-symbols fontconfig.def
+
+# gcc import library install/uninstall
+
+install-libtool-import-lib:
+ $(INSTALL) .libs/libfontconfig.dll.a $(DESTDIR)$(libdir)
+ $(INSTALL) fontconfig.def $(DESTDIR)$(libdir)/fontconfig.def
+
+uninstall-libtool-import-lib:
+ -rm $(DESTDIR)$(libdir)/libfontconfig.dll.a $(DESTDIR)$(libdir)/fontconfig.def
+
+else
+
+install-libtool-import-lib:
+uninstall-libtool-import-lib:
+
+endif
+
+if MS_LIB_AVAILABLE
+
+# Microsoft import library install/uninstall
+
+noinst_DATA = fontconfig.lib
+
+fontconfig.lib : libfontconfig.la
+ lib -name:libfontconfig-$(lt_current_minus_age).dll -def:fontconfig.def -out:$@
+
+install-ms-import-lib:
+ $(INSTALL) fontconfig.lib $(DESTDIR)$(libdir)
+
+uninstall-ms-import-lib:
+ -rm $(DESTDIR)$(libdir)/fontconfig.lib
+
+else
+
+install-ms-import-lib:
+uninstall-ms-import-lib:
+
+endif
+
+INCLUDES = \
+ $(FREETYPE_CFLAGS) \
+ $(EXPAT_CFLAGS) \
+ $(WARN_CFLAGS) \
+ -DFONTCONFIG_PATH='"$(CONFDIR)"' \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/src
+
+EXTRA_DIST = fontconfig.def.in
+
+noinst_HEADERS=fcint.h
+
+libfontconfig_la_SOURCES = \
+ fcatomic.c \
+ fcblanks.c \
+ fccache.c \
+ fccfg.c \
+ fccharset.c \
+ fcdbg.c \
+ fcdefault.c \
+ fcdir.c \
+ fcfreetype.c \
+ fcfs.c \
+ fcinit.c \
+ fclang.c \
+ fclist.c \
+ fcmatch.c \
+ fcmatrix.c \
+ fcname.c \
+ fcpat.c \
+ fcstr.c \
+ fcxml.c
+
+lib_LTLIBRARIES = libfontconfig.la
+
+libfontconfig_la_LDFLAGS = \
+ -version-info @LT_VERSION_INFO@ $(no_undefined) $(export_symbols)
+
+libfontconfig_la_LIBADD = $(FREETYPE_LIBS) $(EXPAT_LIBS)
+
+install-data-local: install-ms-import-lib install-libtool-import-lib
+
+uninstall-local: uninstall-ms-import-lib uninstall-libtool-import-lib
+
diff --git a/nx-X11/extras/fontconfig/src/Makefile.in b/nx-X11/extras/fontconfig/src/Makefile.in
new file mode 100644
index 000000000..987f573dc
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/Makefile.in
@@ -0,0 +1,611 @@
+# Makefile.in generated by automake 1.7.9 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+#
+# $Id: Makefile.in,v 1.3 2005/06/28 01:01:14 alanc Exp $
+#
+# Copyright © 2003 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 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.
+#
+# KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+# EVENT SHALL KEITH PACKARD 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.
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_triplet = @host@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CONFDIR = @CONFDIR@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CROSS_COMPILING_FALSE = @CROSS_COMPILING_FALSE@
+CROSS_COMPILING_TRUE = @CROSS_COMPILING_TRUE@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOCDIR = @DOCDIR@
+DOCMAN3 = @DOCMAN3@
+DOCSRC = @DOCSRC@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLE_DOCS_FALSE = @ENABLE_DOCS_FALSE@
+ENABLE_DOCS_TRUE = @ENABLE_DOCS_TRUE@
+EXEEXT = @EXEEXT@
+EXEEXT_FOR_BUILD = @EXEEXT_FOR_BUILD@
+EXPAT_CFLAGS = @EXPAT_CFLAGS@
+EXPAT_LIBS = @EXPAT_LIBS@
+F77 = @F77@
+FC_ADD_FONTS = @FC_ADD_FONTS@
+FC_DEFAULT_FONTS = @FC_DEFAULT_FONTS@
+FC_FONTDATE = @FC_FONTDATE@
+FC_FONTPATH = @FC_FONTPATH@
+FFLAGS = @FFLAGS@
+FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
+FREETYPE_LIBS = @FREETYPE_LIBS@
+HASDOCBOOK = @HASDOCBOOK@
+HAVE_EXPAT = @HAVE_EXPAT@
+HAVE_XMLPARSE_H = @HAVE_XMLPARSE_H@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_CURRENT = @LT_CURRENT@
+LT_CURRENT_MINUS_AGE = @LT_CURRENT_MINUS_AGE@
+LT_REVISION = @LT_REVISION@
+LT_VERSION_INFO = @LT_VERSION_INFO@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MS_LIB_AVAILABLE_FALSE = @MS_LIB_AVAILABLE_FALSE@
+MS_LIB_AVAILABLE_TRUE = @MS_LIB_AVAILABLE_TRUE@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+ORTH_FILES = @ORTH_FILES@
+OS_WIN32_FALSE = @OS_WIN32_FALSE@
+OS_WIN32_TRUE = @OS_WIN32_TRUE@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+USEDOCBOOK_FALSE = @USEDOCBOOK_FALSE@
+USEDOCBOOK_TRUE = @USEDOCBOOK_TRUE@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_AS = @ac_ct_AS@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DLLTOOL = @ac_ct_DLLTOOL@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_OBJDUMP = @ac_ct_OBJDUMP@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+confdir = @confdir@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+ft_config = @ft_config@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+ms_librarian = @ms_librarian@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+
+@OS_WIN32_TRUE@no_undefined = -no-undefined
+@OS_WIN32_TRUE@export_symbols = -export-symbols fontconfig.def
+
+
+# Microsoft import library install/uninstall
+@MS_LIB_AVAILABLE_TRUE@noinst_DATA = fontconfig.lib
+
+INCLUDES = \
+ $(FREETYPE_CFLAGS) \
+ $(EXPAT_CFLAGS) \
+ $(WARN_CFLAGS) \
+ -DFONTCONFIG_PATH='"$(CONFDIR)"' \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/src
+
+
+EXTRA_DIST = fontconfig.def.in
+
+noinst_HEADERS = fcint.h
+
+libfontconfig_la_SOURCES = \
+ fcatomic.c \
+ fcblanks.c \
+ fccache.c \
+ fccfg.c \
+ fccharset.c \
+ fcdbg.c \
+ fcdefault.c \
+ fcdir.c \
+ fcfreetype.c \
+ fcfs.c \
+ fcinit.c \
+ fclang.c \
+ fclist.c \
+ fcmatch.c \
+ fcmatrix.c \
+ fcname.c \
+ fcpat.c \
+ fcstr.c \
+ fcxml.c
+
+
+lib_LTLIBRARIES = libfontconfig.la
+
+libfontconfig_la_LDFLAGS = \
+ -version-info @LT_VERSION_INFO@ $(no_undefined) $(export_symbols)
+
+
+libfontconfig_la_LIBADD = $(FREETYPE_LIBS) $(EXPAT_LIBS)
+subdir = src
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = fontconfig.def
+LTLIBRARIES = $(lib_LTLIBRARIES)
+
+libfontconfig_la_DEPENDENCIES =
+am_libfontconfig_la_OBJECTS = fcatomic.lo fcblanks.lo fccache.lo \
+ fccfg.lo fccharset.lo fcdbg.lo fcdefault.lo fcdir.lo \
+ fcfreetype.lo fcfs.lo fcinit.lo fclang.lo fclist.lo fcmatch.lo \
+ fcmatrix.lo fcname.lo fcpat.lo fcstr.lo fcxml.lo
+libfontconfig_la_OBJECTS = $(am_libfontconfig_la_OBJECTS)
+
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/fcatomic.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/fcblanks.Plo ./$(DEPDIR)/fccache.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/fccfg.Plo ./$(DEPDIR)/fccharset.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/fcdbg.Plo ./$(DEPDIR)/fcdefault.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/fcdir.Plo ./$(DEPDIR)/fcfreetype.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/fcfs.Plo ./$(DEPDIR)/fcinit.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/fclang.Plo ./$(DEPDIR)/fclist.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/fcmatch.Plo ./$(DEPDIR)/fcmatrix.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/fcname.Plo ./$(DEPDIR)/fcpat.Plo \
+@AMDEP_TRUE@ ./$(DEPDIR)/fcstr.Plo ./$(DEPDIR)/fcxml.Plo
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
+ $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+DIST_SOURCES = $(libfontconfig_la_SOURCES)
+DATA = $(noinst_DATA)
+
+HEADERS = $(noinst_HEADERS)
+
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.in Makefile.am \
+ fontconfig.def.in
+SOURCES = $(libfontconfig_la_SOURCES)
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+Makefile: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+fontconfig.def: $(top_builddir)/config.status fontconfig.def.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+libLTLIBRARIES_INSTALL = $(INSTALL)
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(libdir)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f="`echo $$p | sed -e 's|^.*/||'`"; \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) $$p $(DESTDIR)$(libdir)/$$f; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p="`echo $$p | sed -e 's|^.*/||'`"; \
+ echo " $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p"; \
+ $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$$p; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" = "$$p" && dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libfontconfig.la: $(libfontconfig_la_OBJECTS) $(libfontconfig_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libfontconfig_la_LDFLAGS) $(libfontconfig_la_OBJECTS) $(libfontconfig_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT) core *.core
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcatomic.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcblanks.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fccache.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fccfg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fccharset.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcdbg.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcdefault.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcdir.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcfreetype.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcfs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcinit.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fclang.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fclist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcmatch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcmatrix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcname.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcpat.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcstr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fcxml.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
+@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCC_TRUE@ fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
+
+.c.obj:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
+@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCC_TRUE@ fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`
+
+.c.lo:
+@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
+@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \
+@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+@am__fastdepCC_TRUE@ fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+ETAGS = etags
+ETAGSFLAGS =
+
+CTAGS = ctags
+CTAGSFLAGS =
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$tags$$unique" \
+ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique
+
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkinstalldirs) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(DATA) $(HEADERS)
+
+installdirs:
+ $(mkinstalldirs) $(DESTDIR)$(libdir)
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-libLTLIBRARIES uninstall-local
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am info info-am install \
+ install-am install-data install-data-am install-data-local \
+ install-exec install-exec-am install-info install-info-am \
+ install-libLTLIBRARIES install-man install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags uninstall uninstall-am uninstall-info-am \
+ uninstall-libLTLIBRARIES uninstall-local
+
+
+# gcc import library install/uninstall
+
+@OS_WIN32_TRUE@install-libtool-import-lib:
+@OS_WIN32_TRUE@ $(INSTALL) .libs/libfontconfig.dll.a $(DESTDIR)$(libdir)
+@OS_WIN32_TRUE@ $(INSTALL) fontconfig.def $(DESTDIR)$(libdir)/fontconfig.def
+
+@OS_WIN32_TRUE@uninstall-libtool-import-lib:
+@OS_WIN32_TRUE@ -rm $(DESTDIR)$(libdir)/libfontconfig.dll.a $(DESTDIR)$(libdir)/fontconfig.def
+
+@OS_WIN32_FALSE@install-libtool-import-lib:
+@OS_WIN32_FALSE@uninstall-libtool-import-lib:
+
+@MS_LIB_AVAILABLE_TRUE@fontconfig.lib : libfontconfig.la
+@MS_LIB_AVAILABLE_TRUE@ lib -name:libfontconfig-$(lt_current_minus_age).dll -def:fontconfig.def -out:$@
+
+@MS_LIB_AVAILABLE_TRUE@install-ms-import-lib:
+@MS_LIB_AVAILABLE_TRUE@ $(INSTALL) fontconfig.lib $(DESTDIR)$(libdir)
+
+@MS_LIB_AVAILABLE_TRUE@uninstall-ms-import-lib:
+@MS_LIB_AVAILABLE_TRUE@ -rm $(DESTDIR)$(libdir)/fontconfig.lib
+
+@MS_LIB_AVAILABLE_FALSE@install-ms-import-lib:
+@MS_LIB_AVAILABLE_FALSE@uninstall-ms-import-lib:
+
+install-data-local: install-ms-import-lib install-libtool-import-lib
+
+uninstall-local: uninstall-ms-import-lib uninstall-libtool-import-lib
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/nx-X11/extras/fontconfig/src/fcatomic.c b/nx-X11/extras/fontconfig/src/fcatomic.c
new file mode 100644
index 000000000..a8487f33f
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcatomic.c
@@ -0,0 +1,210 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fcatomic.c,v 1.2 2002/03/04 21:15:28 tsi Exp $
+ *
+ * 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+/*
+ * fcatomic.c
+ *
+ * Lock cache and configuration files for atomic update
+ *
+ * Uses only regular filesystem calls so it should
+ * work even in the absense of functioning file locking
+ *
+ * On Unix, four files are used:
+ * file - the data file accessed by other apps.
+ * new - a new version of the data file while it's being written
+ * lck - the lock file
+ * tmp - a temporary file made unique with mkstemp
+ *
+ * Here's how it works:
+ * Create 'tmp' and store our PID in it
+ * Attempt to link it to 'lck'
+ * Unlink 'tmp'
+ * If the link succeeded, the lock is held
+ *
+ * On Windows, where there are no links, no tmp file is used, and lck
+ * is a directory that's mkdir'ed. If the mkdir succeeds, the lock is
+ * held.
+ */
+
+#include "fcint.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <time.h>
+
+#ifdef _WIN32
+#define mkdir(path,mode) _mkdir(path)
+#endif
+
+#define NEW_NAME ".NEW"
+#define LCK_NAME ".LCK"
+#define TMP_NAME ".TMP-XXXXXX"
+
+FcAtomic *
+FcAtomicCreate (const FcChar8 *file)
+{
+ int file_len = strlen ((char *) file);
+ int new_len = file_len + sizeof (NEW_NAME);
+ int lck_len = file_len + sizeof (LCK_NAME);
+ int tmp_len = file_len + sizeof (TMP_NAME);
+ int total_len = (sizeof (FcAtomic) +
+ file_len + 1 +
+ new_len + 1 +
+ lck_len + 1 +
+ tmp_len + 1);
+ FcAtomic *atomic = malloc (total_len);
+ if (!atomic)
+ return 0;
+ FcMemAlloc (FC_MEM_ATOMIC, total_len);
+
+ atomic->file = (FcChar8 *) (atomic + 1);
+ strcpy ((char *) atomic->file, (char *) file);
+
+ atomic->new = atomic->file + file_len + 1;
+ strcpy ((char *) atomic->new, (char *) file);
+ strcat ((char *) atomic->new, NEW_NAME);
+
+ atomic->lck = atomic->new + new_len + 1;
+ strcpy ((char *) atomic->lck, (char *) file);
+ strcat ((char *) atomic->lck, LCK_NAME);
+
+ atomic->tmp = atomic->lck + lck_len + 1;
+
+ return atomic;
+}
+
+FcBool
+FcAtomicLock (FcAtomic *atomic)
+{
+ int fd = -1;
+ FILE *f = 0;
+ int ret;
+ struct stat lck_stat;
+
+#ifdef HAVE_LINK
+ strcpy ((char *) atomic->tmp, (char *) atomic->file);
+ strcat ((char *) atomic->tmp, TMP_NAME);
+ fd = mkstemp ((char *) atomic->tmp);
+ if (fd < 0)
+ return FcFalse;
+ f = fdopen (fd, "w");
+ if (!f)
+ {
+ close (fd);
+ unlink ((char *) atomic->tmp);
+ return FcFalse;
+ }
+ ret = fprintf (f, "%ld\n", (long)getpid());
+ if (ret <= 0)
+ {
+ fclose (f);
+ unlink ((char *) atomic->tmp);
+ return FcFalse;
+ }
+ if (fclose (f) == EOF)
+ {
+ unlink ((char *) atomic->tmp);
+ return FcFalse;
+ }
+ ret = link ((char *) atomic->tmp, (char *) atomic->lck);
+ (void) unlink ((char *) atomic->tmp);
+#else
+ ret = mkdir ((char *) atomic->lck, 0600);
+#endif
+ if (ret < 0)
+ {
+ /*
+ * If the file is around and old (> 10 minutes),
+ * assume the lock is stale. This assumes that any
+ * machines sharing the same filesystem will have clocks
+ * reasonably close to each other.
+ */
+ if (stat ((char *) atomic->lck, &lck_stat) >= 0)
+ {
+ time_t now = time (0);
+ if ((long int) (now - lck_stat.st_mtime) > 10 * 60)
+ {
+#ifdef HAVE_LINK
+ if (unlink ((char *) atomic->lck) == 0)
+ return FcAtomicLock (atomic);
+#else
+ if (rmdir ((char *) atomic->lck) == 0)
+ return FcAtomicLock (atomic);
+#endif
+ }
+ }
+ return FcFalse;
+ }
+ (void) unlink ((char *) atomic->new);
+ return FcTrue;
+}
+
+FcChar8 *
+FcAtomicNewFile (FcAtomic *atomic)
+{
+ return atomic->new;
+}
+
+FcChar8 *
+FcAtomicOrigFile (FcAtomic *atomic)
+{
+ return atomic->file;
+}
+
+FcBool
+FcAtomicReplaceOrig (FcAtomic *atomic)
+{
+ if (rename ((char *) atomic->new, (char *) atomic->file) < 0)
+ return FcFalse;
+ return FcTrue;
+}
+
+void
+FcAtomicDeleteNew (FcAtomic *atomic)
+{
+ unlink ((char *) atomic->new);
+}
+
+void
+FcAtomicUnlock (FcAtomic *atomic)
+{
+#ifdef HAVE_LINK
+ unlink ((char *) atomic->lck);
+#else
+ rmdir ((char *) atomic->lck);
+#endif
+}
+
+void
+FcAtomicDestroy (FcAtomic *atomic)
+{
+ FcMemFree (FC_MEM_ATOMIC, sizeof (FcAtomic) +
+ strlen ((char *) atomic->file) * 4 + 1 +
+ sizeof (NEW_NAME) + sizeof (LCK_NAME) +
+ sizeof (TMP_NAME));
+
+ free (atomic);
+}
diff --git a/nx-X11/extras/fontconfig/src/fcblanks.c b/nx-X11/extras/fontconfig/src/fcblanks.c
new file mode 100644
index 000000000..a78e85fe6
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcblanks.c
@@ -0,0 +1,92 @@
+/*
+ * $RCSId:$
+ *
+ * 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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"
+
+FcBlanks *
+FcBlanksCreate (void)
+{
+ FcBlanks *b;
+
+ b = malloc (sizeof (FcBlanks));
+ if (!b)
+ return 0;
+ FcMemAlloc (FC_MEM_BLANKS, sizeof (FcBlanks));
+ b->nblank = 0;
+ b->sblank = 0;
+ b->blanks = 0;
+ return b;
+}
+
+void
+FcBlanksDestroy (FcBlanks *b)
+{
+ if (b->blanks)
+ {
+ FcMemFree (FC_MEM_BLANKS, b->sblank * sizeof (FcChar32));
+ free (b->blanks);
+ }
+ FcMemFree (FC_MEM_BLANKS, sizeof (FcBlanks));
+ free (b);
+}
+
+FcBool
+FcBlanksAdd (FcBlanks *b, FcChar32 ucs4)
+{
+ FcChar32 *c;
+ int sblank;
+
+ for (sblank = 0; sblank < b->nblank; sblank++)
+ if (b->blanks[sblank] == ucs4)
+ return FcTrue;
+
+ if (b->nblank == b->sblank)
+ {
+ sblank = b->sblank + 32;
+ if (b->blanks)
+ c = (FcChar32 *) realloc (b->blanks, sblank * sizeof (FcChar32));
+ else
+ c = (FcChar32 *) malloc (sblank * sizeof (FcChar32));
+ if (!c)
+ return FcFalse;
+ if (b->sblank)
+ FcMemFree (FC_MEM_BLANKS, b->sblank * sizeof (FcChar32));
+ FcMemAlloc (FC_MEM_BLANKS, sblank * sizeof (FcChar32));
+ b->sblank = sblank;
+ b->blanks = c;
+ }
+ b->blanks[b->nblank++] = ucs4;
+ return FcTrue;
+}
+
+FcBool
+FcBlanksIsMember (FcBlanks *b, FcChar32 ucs4)
+{
+ int i;
+
+ for (i = 0; i < b->nblank; i++)
+ if (b->blanks[i] == ucs4)
+ return FcTrue;
+ return FcFalse;
+}
diff --git a/nx-X11/extras/fontconfig/src/fccache.c b/nx-X11/extras/fontconfig/src/fccache.c
new file mode 100644
index 000000000..28455430a
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fccache.c
@@ -0,0 +1,1168 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fccache.c,v 1.12 2002/08/22 07:36:44 keithp Exp $
+ *
+ * Copyright © 2000 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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"
+
+/*
+ * POSIX has broken stdio so that getc must do thread-safe locking,
+ * this is a serious performance problem for applications doing large
+ * amounts of IO with getc (as is done here). If available, use
+ * the getc_unlocked varient instead.
+ */
+
+#if defined(getc_unlocked) || defined(_IO_getc_unlocked)
+#define GETC(f) getc_unlocked(f)
+#define PUTC(c,f) putc_unlocked(c,f)
+#else
+#define GETC(f) getc(f)
+#define PUTC(c,f) putc(c,f)
+#endif
+
+#define FC_DBG_CACHE_REF 1024
+
+static FcChar8 *
+FcCacheReadString (FILE *f, FcChar8 *dest, int len)
+{
+ int c;
+ FcBool escape;
+ FcChar8 *d;
+ int size;
+ int i;
+
+ while ((c = GETC (f)) != EOF)
+ if (c == '"')
+ break;
+ if (c == EOF)
+ return FcFalse;
+ if (len == 0)
+ return FcFalse;
+
+ size = len;
+ i = 0;
+ d = dest;
+ escape = FcFalse;
+ while ((c = GETC (f)) != EOF)
+ {
+ if (!escape)
+ {
+ switch (c) {
+ case '"':
+ c = '\0';
+ break;
+ case '\\':
+ escape = FcTrue;
+ continue;
+ }
+ }
+ if (i == size)
+ {
+ FcChar8 *new = malloc (size * 2); /* freed in caller */
+ if (!new)
+ break;
+ memcpy (new, d, size);
+ size *= 2;
+ if (d != dest)
+ free (d);
+ d = new;
+ }
+ d[i++] = c;
+ if (c == '\0')
+ return d;
+ escape = FcFalse;
+ }
+ if (d != dest)
+ free (d);
+ return 0;
+}
+
+static FcBool
+FcCacheReadUlong (FILE *f, unsigned long *dest)
+{
+ unsigned long t;
+ int c;
+
+ while ((c = GETC (f)) != EOF)
+ {
+ if (!isspace (c))
+ break;
+ }
+ if (c == EOF)
+ return FcFalse;
+ t = 0;
+ for (;;)
+ {
+ if (c == EOF || isspace (c))
+ break;
+ if (!isdigit (c))
+ return FcFalse;
+ t = t * 10 + (c - '0');
+ c = GETC (f);
+ }
+ *dest = t;
+ return FcTrue;
+}
+
+static FcBool
+FcCacheReadInt (FILE *f, int *dest)
+{
+ unsigned long t;
+ FcBool ret;
+
+ ret = FcCacheReadUlong (f, &t);
+ if (ret)
+ *dest = (int) t;
+ return ret;
+}
+
+static FcBool
+FcCacheReadTime (FILE *f, time_t *dest)
+{
+ unsigned long t;
+ FcBool ret;
+
+ ret = FcCacheReadUlong (f, &t);
+ if (ret)
+ *dest = (time_t) t;
+ return ret;
+}
+
+static FcBool
+FcCacheWriteChars (FILE *f, const FcChar8 *chars)
+{
+ FcChar8 c;
+ while ((c = *chars++))
+ {
+ switch (c) {
+ case '"':
+ case '\\':
+ if (PUTC ('\\', f) == EOF)
+ return FcFalse;
+ /* fall through */
+ default:
+ if (PUTC (c, f) == EOF)
+ return FcFalse;
+ }
+ }
+ return FcTrue;
+}
+
+static FcBool
+FcCacheWriteString (FILE *f, const FcChar8 *string)
+{
+
+ if (PUTC ('"', f) == EOF)
+ return FcFalse;
+ if (!FcCacheWriteChars (f, string))
+ return FcFalse;
+ if (PUTC ('"', f) == EOF)
+ return FcFalse;
+ return FcTrue;
+}
+
+static FcBool
+FcCacheWritePath (FILE *f, const FcChar8 *dir, const FcChar8 *file)
+{
+ if (PUTC ('"', f) == EOF)
+ return FcFalse;
+ if (dir)
+ if (!FcCacheWriteChars (f, dir))
+ return FcFalse;
+#ifdef _WIN32
+ if (dir &&
+ dir[strlen((const char *) dir) - 1] != '/' &&
+ dir[strlen((const char *) dir) - 1] != '\\')
+ {
+ if (!FcCacheWriteChars (f, "\\"))
+ return FcFalse;
+ }
+#else
+ if (dir && dir[strlen((const char *) dir) - 1] != '/')
+ if (PUTC ('/', f) == EOF)
+ return FcFalse;
+#endif
+ if (!FcCacheWriteChars (f, file))
+ return FcFalse;
+ if (PUTC ('"', f) == EOF)
+ return FcFalse;
+ return FcTrue;
+}
+
+static FcBool
+FcCacheWriteUlong (FILE *f, unsigned long t)
+{
+ int pow;
+ unsigned long temp, digit;
+
+ temp = t;
+ pow = 1;
+ while (temp >= 10)
+ {
+ temp /= 10;
+ pow *= 10;
+ }
+ temp = t;
+ while (pow)
+ {
+ digit = temp / pow;
+ if (PUTC ((char) digit + '0', f) == EOF)
+ return FcFalse;
+ temp = temp - pow * digit;
+ pow = pow / 10;
+ }
+ return FcTrue;
+}
+
+static FcBool
+FcCacheWriteInt (FILE *f, int i)
+{
+ return FcCacheWriteUlong (f, (unsigned long) i);
+}
+
+static FcBool
+FcCacheWriteTime (FILE *f, time_t t)
+{
+ return FcCacheWriteUlong (f, (unsigned long) t);
+}
+
+static FcBool
+FcCacheFontSetAdd (FcFontSet *set,
+ FcStrSet *dirs,
+ const FcChar8 *dir,
+ int dir_len,
+ const FcChar8 *file,
+ const FcChar8 *name,
+ FcConfig *config)
+{
+ FcChar8 path_buf[8192], *path;
+ int len;
+ FcBool ret = FcFalse;
+ FcPattern *font;
+ FcPattern *frozen;
+
+ path = path_buf;
+ len = (dir_len + 1 + strlen ((const char *) file) + 1);
+ if (len > sizeof (path_buf))
+ {
+ path = malloc (len); /* freed down below */
+ if (!path)
+ return FcFalse;
+ }
+ strncpy ((char *) path, (const char *) dir, dir_len);
+#ifdef _WIN32
+ if (dir[dir_len - 1] != '/' && dir[dir_len - 1] != '\\' )
+ path[dir_len++] = '\\';
+#else
+ if (dir[dir_len - 1] != '/')
+ path[dir_len++] = '/';
+#endif
+ strcpy ((char *) path + dir_len, (const char *) file);
+ if (config && !FcConfigAcceptFilename (config, path))
+ ret = FcTrue;
+ else if (!FcStrCmp (name, FC_FONT_FILE_DIR))
+ {
+ if (FcDebug () & FC_DBG_CACHEV)
+ printf (" dir cache dir \"%s\"\n", path);
+ ret = FcStrSetAdd (dirs, path);
+ }
+ else if (!FcStrCmp (name, FC_FONT_FILE_INVALID))
+ {
+ ret = FcTrue;
+ }
+ else
+ {
+ font = FcNameParse (name);
+ if (font)
+ {
+ FcChar8 *family;
+
+ if (FcDebug () & FC_DBG_CACHEV)
+ printf (" dir cache file \"%s\"\n", file);
+ ret = FcPatternAddString (font, FC_FILE, path);
+ /*
+ * Make sure the pattern has the file name as well as
+ * already containing at least one family name.
+ */
+ if (ret &&
+ FcPatternGetString (font, FC_FAMILY, 0, &family) == FcResultMatch &&
+ (!config || FcConfigAcceptFont (config, font)))
+ {
+ frozen = FcPatternFreeze (font);
+ ret = (frozen != 0);
+ if (ret)
+ ret = FcFontSetAdd (set, frozen);
+ }
+ FcPatternDestroy (font);
+ }
+ }
+ if (path != path_buf) free (path);
+ return ret;
+
+}
+
+static unsigned int
+FcCacheHash (const FcChar8 *string, int len)
+{
+ unsigned int h = 0;
+ FcChar8 c;
+
+ while (len-- && (c = *string++))
+ h = (h << 1) ^ c;
+ return h;
+}
+
+/*
+ * Verify the saved timestamp for a file
+ */
+FcBool
+FcGlobalCacheCheckTime (const FcChar8 *file, FcGlobalCacheInfo *info)
+{
+ struct stat statb;
+
+ if (stat ((char *) file, &statb) < 0)
+ {
+ if (FcDebug () & FC_DBG_CACHE)
+ printf (" file %s missing\n", file);
+ return FcFalse;
+ }
+ if (statb.st_mtime != info->time)
+ {
+ if (FcDebug () & FC_DBG_CACHE)
+ printf (" timestamp mismatch (was %d is %d)\n",
+ (int) info->time, (int) statb.st_mtime);
+ return FcFalse;
+ }
+ return FcTrue;
+}
+
+void
+FcGlobalCacheReferenced (FcGlobalCache *cache,
+ FcGlobalCacheInfo *info)
+{
+ if (!info->referenced)
+ {
+ info->referenced = FcTrue;
+ cache->referenced++;
+ if (FcDebug () & FC_DBG_CACHE_REF)
+ printf ("Reference %d %s\n", cache->referenced, info->file);
+ }
+}
+
+/*
+ * Break a path into dir/base elements and compute the base hash
+ * and the dir length. This is shared between the functions
+ * which walk the file caches
+ */
+
+typedef struct _FcFilePathInfo {
+ const FcChar8 *dir;
+ int dir_len;
+ const FcChar8 *base;
+ unsigned int base_hash;
+} FcFilePathInfo;
+
+static FcFilePathInfo
+FcFilePathInfoGet (const FcChar8 *path)
+{
+ FcFilePathInfo i;
+ FcChar8 *slash;
+
+ slash = FcStrLastSlash (path);
+ if (slash)
+ {
+ i.dir = path;
+ i.dir_len = slash - path;
+ if (!i.dir_len)
+ i.dir_len = 1;
+ i.base = slash + 1;
+ }
+ else
+ {
+ i.dir = (const FcChar8 *) ".";
+ i.dir_len = 1;
+ i.base = path;
+ }
+ i.base_hash = FcCacheHash (i.base, -1);
+ return i;
+}
+
+FcGlobalCacheDir *
+FcGlobalCacheDirGet (FcGlobalCache *cache,
+ const FcChar8 *dir,
+ int len,
+ FcBool create_missing)
+{
+ unsigned int hash = FcCacheHash (dir, len);
+ FcGlobalCacheDir *d, **prev;
+
+ for (prev = &cache->ents[hash % FC_GLOBAL_CACHE_DIR_HASH_SIZE];
+ (d = *prev);
+ prev = &(*prev)->next)
+ {
+ if (d->info.hash == hash && d->len == len &&
+ !strncmp ((const char *) d->info.file,
+ (const char *) dir, len))
+ break;
+ }
+ if (!(d = *prev))
+ {
+ int i;
+ if (!create_missing)
+ return 0;
+ d = malloc (sizeof (FcGlobalCacheDir) + len + 1);
+ if (!d)
+ return 0;
+ FcMemAlloc (FC_MEM_CACHE, sizeof (FcGlobalCacheDir) + len + 1);
+ d->next = *prev;
+ *prev = d;
+ d->info.hash = hash;
+ d->info.file = (FcChar8 *) (d + 1);
+ strncpy ((char *) d->info.file, (const char *) dir, len);
+ d->info.file[len] = '\0';
+ d->info.time = 0;
+ d->info.referenced = FcFalse;
+ d->len = len;
+ for (i = 0; i < FC_GLOBAL_CACHE_FILE_HASH_SIZE; i++)
+ d->ents[i] = 0;
+ d->subdirs = 0;
+ }
+ return d;
+}
+
+static FcGlobalCacheInfo *
+FcGlobalCacheDirAdd (FcGlobalCache *cache,
+ const FcChar8 *dir,
+ time_t time,
+ FcBool replace,
+ FcBool create_missing)
+{
+ FcGlobalCacheDir *d;
+ FcFilePathInfo i;
+ FcGlobalCacheSubdir *subdir;
+ FcGlobalCacheDir *parent;
+
+ i = FcFilePathInfoGet (dir);
+ parent = FcGlobalCacheDirGet (cache, i.dir, i.dir_len, create_missing);
+ /*
+ * Tricky here -- directories containing fonts.cache-1 files
+ * need entries only when the parent doesn't have a cache file.
+ * That is, when the parent already exists in the cache, is
+ * referenced and has a "real" timestamp. The time of 0 is
+ * special and marks directories which got stuck in the
+ * global cache for this very reason. Yes, it could
+ * use a separate boolean field, and probably should.
+ */
+ if (!parent || (!create_missing &&
+ (!parent->info.referenced ||
+ (parent->info.time == 0))))
+ return 0;
+ /*
+ * Add this directory to the cache
+ */
+ d = FcGlobalCacheDirGet (cache, dir, strlen ((const char *) dir), FcTrue);
+ if (!d)
+ return 0;
+ d->info.time = time;
+ /*
+ * Add this directory to the subdirectory list of the parent
+ */
+ subdir = malloc (sizeof (FcGlobalCacheSubdir));
+ if (!subdir)
+ return 0;
+ FcMemAlloc (FC_MEM_CACHE, sizeof (FcGlobalCacheSubdir));
+ subdir->ent = d;
+ subdir->next = parent->subdirs;
+ parent->subdirs = subdir;
+ return &d->info;
+}
+
+static void
+FcGlobalCacheDirDestroy (FcGlobalCacheDir *d)
+{
+ FcGlobalCacheFile *f, *next;
+ int h;
+ FcGlobalCacheSubdir *s, *nexts;
+
+ for (h = 0; h < FC_GLOBAL_CACHE_FILE_HASH_SIZE; h++)
+ for (f = d->ents[h]; f; f = next)
+ {
+ next = f->next;
+ FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheFile) +
+ strlen ((char *) f->info.file) + 1 +
+ strlen ((char *) f->name) + 1);
+ free (f);
+ }
+ for (s = d->subdirs; s; s = nexts)
+ {
+ nexts = s->next;
+ FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheSubdir));
+ free (s);
+ }
+ FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheDir) + d->len + 1);
+ free (d);
+}
+
+/*
+ * If the parent is in the global cache and referenced, add
+ * an entry for 'dir' to the global cache. This is used
+ * for directories with fonts.cache files
+ */
+
+void
+FcGlobalCacheReferenceSubdir (FcGlobalCache *cache,
+ const FcChar8 *dir)
+{
+ FcGlobalCacheInfo *info;
+ info = FcGlobalCacheDirAdd (cache, dir, 0, FcFalse, FcFalse);
+ if (info && !info->referenced)
+ {
+ info->referenced = FcTrue;
+ cache->referenced++;
+ }
+}
+
+/*
+ * Check to see if the global cache contains valid data for 'dir'.
+ * If so, scan the global cache for files and directories in 'dir'.
+ * else, return False.
+ */
+FcBool
+FcGlobalCacheScanDir (FcFontSet *set,
+ FcStrSet *dirs,
+ FcGlobalCache *cache,
+ const FcChar8 *dir,
+ FcConfig *config)
+{
+ FcGlobalCacheDir *d = FcGlobalCacheDirGet (cache, dir,
+ strlen ((const char *) dir),
+ FcFalse);
+ FcGlobalCacheFile *f;
+ int h;
+ int dir_len;
+ FcGlobalCacheSubdir *subdir;
+ FcBool any_in_cache = FcFalse;
+
+ if (FcDebug() & FC_DBG_CACHE)
+ printf ("FcGlobalCacheScanDir %s\n", dir);
+
+ if (!d)
+ {
+ if (FcDebug () & FC_DBG_CACHE)
+ printf ("\tNo dir cache entry\n");
+ return FcFalse;
+ }
+
+ /*
+ * See if the timestamp recorded in the global cache
+ * matches the directory time, if not, return False
+ */
+ if (!FcGlobalCacheCheckTime (d->info.file, &d->info))
+ {
+ if (FcDebug () & FC_DBG_CACHE)
+ printf ("\tdir cache entry time mismatch\n");
+ return FcFalse;
+ }
+
+ /*
+ * Add files from 'dir' to the fontset
+ */
+ dir_len = strlen ((const char *) dir);
+ for (h = 0; h < FC_GLOBAL_CACHE_FILE_HASH_SIZE; h++)
+ for (f = d->ents[h]; f; f = f->next)
+ {
+ if (FcDebug() & FC_DBG_CACHEV)
+ printf ("FcGlobalCacheScanDir add file %s\n", f->info.file);
+ any_in_cache = FcTrue;
+ if (!FcCacheFontSetAdd (set, dirs, dir, dir_len,
+ f->info.file, f->name, config))
+ {
+ cache->broken = FcTrue;
+ return FcFalse;
+ }
+ FcGlobalCacheReferenced (cache, &f->info);
+ }
+ /*
+ * Add directories in 'dir' to 'dirs'
+ */
+ for (subdir = d->subdirs; subdir; subdir = subdir->next)
+ {
+ FcFilePathInfo info = FcFilePathInfoGet (subdir->ent->info.file);
+
+ any_in_cache = FcTrue;
+ if (!FcCacheFontSetAdd (set, dirs, dir, dir_len,
+ info.base, FC_FONT_FILE_DIR, config))
+ {
+ cache->broken = FcTrue;
+ return FcFalse;
+ }
+ FcGlobalCacheReferenced (cache, &subdir->ent->info);
+ }
+
+ FcGlobalCacheReferenced (cache, &d->info);
+
+ /*
+ * To recover from a bug in previous versions of fontconfig,
+ * return FcFalse if no entries in the cache were found
+ * for this directory. This will cause any empty directories
+ * to get rescanned every time fontconfig is initialized. This
+ * might get removed at some point when the older cache files are
+ * presumably fixed.
+ */
+ return any_in_cache;
+}
+
+/*
+ * Locate the cache entry for a particular file
+ */
+FcGlobalCacheFile *
+FcGlobalCacheFileGet (FcGlobalCache *cache,
+ const FcChar8 *file,
+ int id,
+ int *count)
+{
+ FcFilePathInfo i = FcFilePathInfoGet (file);
+ FcGlobalCacheDir *d = FcGlobalCacheDirGet (cache, i.dir,
+ i.dir_len, FcFalse);
+ FcGlobalCacheFile *f, *match = 0;
+ int max = -1;
+
+ if (!d)
+ return 0;
+ for (f = d->ents[i.base_hash % FC_GLOBAL_CACHE_FILE_HASH_SIZE]; f; f = f->next)
+ {
+ if (f->info.hash == i.base_hash &&
+ !strcmp ((const char *) f->info.file, (const char *) i.base))
+ {
+ if (f->id == id)
+ match = f;
+ if (f->id > max)
+ max = f->id;
+ }
+ }
+ if (count)
+ *count = max + 1;
+ return match;
+}
+
+/*
+ * Add a file entry to the cache
+ */
+static FcGlobalCacheInfo *
+FcGlobalCacheFileAdd (FcGlobalCache *cache,
+ const FcChar8 *path,
+ int id,
+ time_t time,
+ const FcChar8 *name,
+ FcBool replace)
+{
+ FcFilePathInfo i = FcFilePathInfoGet (path);
+ FcGlobalCacheDir *d = FcGlobalCacheDirGet (cache, i.dir,
+ i.dir_len, FcTrue);
+ FcGlobalCacheFile *f, **prev;
+ int size;
+
+ if (!d)
+ return 0;
+ for (prev = &d->ents[i.base_hash % FC_GLOBAL_CACHE_FILE_HASH_SIZE];
+ (f = *prev);
+ prev = &(*prev)->next)
+ {
+ if (f->info.hash == i.base_hash &&
+ f->id == id &&
+ !strcmp ((const char *) f->info.file, (const char *) i.base))
+ {
+ break;
+ }
+ }
+ if (*prev)
+ {
+ if (!replace)
+ return 0;
+
+ f = *prev;
+ if (f->info.referenced)
+ cache->referenced--;
+ *prev = f->next;
+ FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCacheFile) +
+ strlen ((char *) f->info.file) + 1 +
+ strlen ((char *) f->name) + 1);
+ free (f);
+ }
+ size = (sizeof (FcGlobalCacheFile) +
+ strlen ((char *) i.base) + 1 +
+ strlen ((char *) name) + 1);
+ f = malloc (size);
+ if (!f)
+ return 0;
+ FcMemAlloc (FC_MEM_CACHE, size);
+ f->next = *prev;
+ *prev = f;
+ f->info.hash = i.base_hash;
+ f->info.file = (FcChar8 *) (f + 1);
+ f->info.time = time;
+ f->info.referenced = FcFalse;
+ f->id = id;
+ f->name = f->info.file + strlen ((char *) i.base) + 1;
+ strcpy ((char *) f->info.file, (const char *) i.base);
+ strcpy ((char *) f->name, (const char *) name);
+ return &f->info;
+}
+
+FcGlobalCache *
+FcGlobalCacheCreate (void)
+{
+ FcGlobalCache *cache;
+ int h;
+
+ cache = malloc (sizeof (FcGlobalCache));
+ if (!cache)
+ return 0;
+ FcMemAlloc (FC_MEM_CACHE, sizeof (FcGlobalCache));
+ for (h = 0; h < FC_GLOBAL_CACHE_DIR_HASH_SIZE; h++)
+ cache->ents[h] = 0;
+ cache->entries = 0;
+ cache->referenced = 0;
+ cache->updated = FcFalse;
+ cache->broken = FcFalse;
+ return cache;
+}
+
+void
+FcGlobalCacheDestroy (FcGlobalCache *cache)
+{
+ FcGlobalCacheDir *d, *next;
+ int h;
+
+ for (h = 0; h < FC_GLOBAL_CACHE_DIR_HASH_SIZE; h++)
+ {
+ for (d = cache->ents[h]; d; d = next)
+ {
+ next = d->next;
+ FcGlobalCacheDirDestroy (d);
+ }
+ }
+ FcMemFree (FC_MEM_CACHE, sizeof (FcGlobalCache));
+ free (cache);
+}
+
+/*
+ * Cache file syntax is quite simple:
+ *
+ * "file_name" id time "font_name" \n
+ */
+
+void
+FcGlobalCacheLoad (FcGlobalCache *cache,
+ const FcChar8 *cache_file)
+{
+ FILE *f;
+ FcChar8 file_buf[8192], *file;
+ int id;
+ time_t time;
+ FcChar8 name_buf[8192], *name;
+ FcGlobalCacheInfo *info;
+
+ f = fopen ((char *) cache_file, "r");
+ if (!f)
+ return;
+
+ cache->updated = FcFalse;
+ file = 0;
+ name = 0;
+ while ((file = FcCacheReadString (f, file_buf, sizeof (file_buf))) &&
+ FcCacheReadInt (f, &id) &&
+ FcCacheReadTime (f, &time) &&
+ (name = FcCacheReadString (f, name_buf, sizeof (name_buf))))
+ {
+ if (FcDebug () & FC_DBG_CACHEV)
+ printf ("FcGlobalCacheLoad \"%s\" \"%20.20s\"\n", file, name);
+ if (!FcStrCmp (name, FC_FONT_FILE_DIR))
+ info = FcGlobalCacheDirAdd (cache, file, time, FcFalse, FcTrue);
+ else
+ info = FcGlobalCacheFileAdd (cache, file, id, time, name, FcFalse);
+ if (!info)
+ cache->broken = FcTrue;
+ else
+ cache->entries++;
+ if (FcDebug () & FC_DBG_CACHE_REF)
+ printf ("FcGlobalCacheLoad entry %d %s\n",
+ cache->entries, file);
+ if (file != file_buf)
+ free (file);
+ if (name != name_buf)
+ free (name);
+ file = 0;
+ name = 0;
+ }
+ if (file && file != file_buf)
+ free (file);
+ if (name && name != name_buf)
+ free (name);
+ fclose (f);
+}
+
+FcBool
+FcGlobalCacheUpdate (FcGlobalCache *cache,
+ const FcChar8 *file,
+ int id,
+ const FcChar8 *name)
+{
+ const FcChar8 *match;
+ struct stat statb;
+ FcGlobalCacheInfo *info;
+
+ match = file;
+
+ if (stat ((char *) file, &statb) < 0)
+ return FcFalse;
+ if (S_ISDIR (statb.st_mode))
+ info = FcGlobalCacheDirAdd (cache, file, statb.st_mtime,
+ FcTrue, FcTrue);
+ else
+ info = FcGlobalCacheFileAdd (cache, file, id, statb.st_mtime,
+ name, FcTrue);
+ if (info)
+ {
+ FcGlobalCacheReferenced (cache, info);
+ cache->updated = FcTrue;
+ }
+ else
+ cache->broken = FcTrue;
+ return info != 0;
+}
+
+FcBool
+FcGlobalCacheSave (FcGlobalCache *cache,
+ const FcChar8 *cache_file)
+{
+ FILE *f;
+ int dir_hash, file_hash;
+ FcGlobalCacheDir *dir;
+ FcGlobalCacheFile *file;
+ FcAtomic *atomic;
+
+ if (!cache->updated && cache->referenced == cache->entries)
+ return FcTrue;
+
+ if (cache->broken)
+ return FcFalse;
+
+#if defined (HAVE_GETUID) && defined (HAVE_GETEUID)
+ /* Set-UID programs can't safely update the cache */
+ if (getuid () != geteuid ())
+ return FcFalse;
+#endif
+
+ atomic = FcAtomicCreate (cache_file);
+ if (!atomic)
+ goto bail0;
+ if (!FcAtomicLock (atomic))
+ goto bail1;
+ f = fopen ((char *) FcAtomicNewFile(atomic), "w");
+ if (!f)
+ goto bail2;
+
+ for (dir_hash = 0; dir_hash < FC_GLOBAL_CACHE_DIR_HASH_SIZE; dir_hash++)
+ {
+ for (dir = cache->ents[dir_hash]; dir; dir = dir->next)
+ {
+ if (!dir->info.referenced)
+ continue;
+ if (!FcCacheWriteString (f, dir->info.file))
+ goto bail4;
+ if (PUTC (' ', f) == EOF)
+ goto bail4;
+ if (!FcCacheWriteInt (f, 0))
+ goto bail4;
+ if (PUTC (' ', f) == EOF)
+ goto bail4;
+ if (!FcCacheWriteTime (f, dir->info.time))
+ goto bail4;
+ if (PUTC (' ', f) == EOF)
+ goto bail4;
+ if (!FcCacheWriteString (f, (FcChar8 *) FC_FONT_FILE_DIR))
+ goto bail4;
+ if (PUTC ('\n', f) == EOF)
+ goto bail4;
+
+ for (file_hash = 0; file_hash < FC_GLOBAL_CACHE_FILE_HASH_SIZE; file_hash++)
+ {
+ for (file = dir->ents[file_hash]; file; file = file->next)
+ {
+ if (!file->info.referenced)
+ continue;
+ if (!FcCacheWritePath (f, dir->info.file, file->info.file))
+ goto bail4;
+ if (PUTC (' ', f) == EOF)
+ goto bail4;
+ if (!FcCacheWriteInt (f, file->id < 0 ? 0 : file->id))
+ goto bail4;
+ if (PUTC (' ', f) == EOF)
+ goto bail4;
+ if (!FcCacheWriteTime (f, file->info.time))
+ goto bail4;
+ if (PUTC (' ', f) == EOF)
+ goto bail4;
+ if (!FcCacheWriteString (f, file->name))
+ goto bail4;
+ if (PUTC ('\n', f) == EOF)
+ goto bail4;
+ }
+ }
+ }
+ }
+
+ if (fclose (f) == EOF)
+ goto bail3;
+
+ if (!FcAtomicReplaceOrig (atomic))
+ goto bail3;
+
+ FcAtomicUnlock (atomic);
+ FcAtomicDestroy (atomic);
+
+ cache->updated = FcFalse;
+ return FcTrue;
+
+bail4:
+ fclose (f);
+bail3:
+ FcAtomicDeleteNew (atomic);
+bail2:
+ FcAtomicUnlock (atomic);
+bail1:
+ FcAtomicDestroy (atomic);
+bail0:
+ return FcFalse;
+}
+
+FcBool
+FcDirCacheValid (const FcChar8 *dir)
+{
+ FcChar8 *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
+ struct stat file_stat, dir_stat;
+
+ if (stat ((char *) dir, &dir_stat) < 0)
+ {
+ FcStrFree (cache_file);
+ return FcFalse;
+ }
+ if (stat ((char *) cache_file, &file_stat) < 0)
+ {
+ FcStrFree (cache_file);
+ return FcFalse;
+ }
+ FcStrFree (cache_file);
+ /*
+ * If the directory has been modified more recently than
+ * the cache file, the cache is not valid
+ */
+ if (dir_stat.st_mtime - file_stat.st_mtime > 0)
+ return FcFalse;
+ return FcTrue;
+}
+
+FcBool
+FcDirCacheReadDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir, FcConfig *config)
+{
+ FcChar8 *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
+ FILE *f;
+ FcChar8 *base;
+ int id;
+ int dir_len;
+ FcChar8 file_buf[8192], *file;
+ FcChar8 name_buf[8192], *name;
+ FcBool ret = FcFalse;
+
+ if (!cache_file)
+ goto bail0;
+
+ if (FcDebug () & FC_DBG_CACHE)
+ printf ("FcDirCacheReadDir cache_file \"%s\"\n", cache_file);
+
+ f = fopen ((char *) cache_file, "r");
+ if (!f)
+ {
+ if (FcDebug () & FC_DBG_CACHE)
+ printf (" no cache file\n");
+ goto bail1;
+ }
+
+ if (!FcDirCacheValid (dir))
+ {
+ if (FcDebug () & FC_DBG_CACHE)
+ printf (" cache file older than directory\n");
+ goto bail2;
+ }
+
+ base = (FcChar8 *) strrchr ((char *) cache_file, '/');
+ if (!base)
+ goto bail2;
+ base++;
+ dir_len = base - cache_file;
+
+ file = 0;
+ name = 0;
+ while ((file = FcCacheReadString (f, file_buf, sizeof (file_buf))) &&
+ FcCacheReadInt (f, &id) &&
+ (name = FcCacheReadString (f, name_buf, sizeof (name_buf))))
+ {
+ if (!FcCacheFontSetAdd (set, dirs, cache_file, dir_len,
+ file, name, config))
+ goto bail3;
+ if (file != file_buf)
+ free (file);
+ if (name != name_buf)
+ free (name);
+ file = name = 0;
+ }
+ if (FcDebug () & FC_DBG_CACHE)
+ printf (" cache loaded\n");
+
+ ret = FcTrue;
+bail3:
+ if (file && file != file_buf)
+ free (file);
+ if (name && name != name_buf)
+ free (name);
+bail2:
+ fclose (f);
+bail1:
+ FcStrFree (cache_file);
+bail0:
+ return ret;
+}
+
+/*
+ * return the path from the directory containing 'cache' to 'file'
+ */
+
+static const FcChar8 *
+FcFileBaseName (const FcChar8 *cache, const FcChar8 *file)
+{
+ const FcChar8 *cache_slash;
+
+ cache_slash = FcStrLastSlash (cache);
+ if (cache_slash && !strncmp ((const char *) cache, (const char *) file,
+ (cache_slash + 1) - cache))
+ return file + ((cache_slash + 1) - cache);
+ return file;
+}
+
+FcBool
+FcDirCacheWriteDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
+{
+ FcChar8 *cache_file = FcStrPlus (dir, (FcChar8 *) "/" FC_DIR_CACHE_FILE);
+ FcPattern *font;
+ FILE *f;
+ FcChar8 *name;
+ const FcChar8 *file, *base;
+ int n;
+ int id;
+ FcBool ret;
+ FcStrList *list;
+
+ if (!cache_file)
+ goto bail0;
+ if (FcDebug () & FC_DBG_CACHE)
+ printf ("FcDirCacheWriteDir cache_file \"%s\"\n", cache_file);
+
+ f = fopen ((char *) cache_file, "w");
+ if (!f)
+ {
+ if (FcDebug () & FC_DBG_CACHE)
+ printf (" can't create \"%s\"\n", cache_file);
+ goto bail1;
+ }
+
+ list = FcStrListCreate (dirs);
+ if (!list)
+ goto bail2;
+
+ while ((dir = FcStrListNext (list)))
+ {
+ base = FcFileBaseName (cache_file, dir);
+ if (!FcCacheWriteString (f, base))
+ goto bail3;
+ if (PUTC (' ', f) == EOF)
+ goto bail3;
+ if (!FcCacheWriteInt (f, 0))
+ goto bail3;
+ if (PUTC (' ', f) == EOF)
+ goto bail3;
+ if (!FcCacheWriteString (f, FC_FONT_FILE_DIR))
+ goto bail3;
+ if (PUTC ('\n', f) == EOF)
+ goto bail3;
+ }
+
+ for (n = 0; n < set->nfont; n++)
+ {
+ font = set->fonts[n];
+ if (FcPatternGetString (font, FC_FILE, 0, (FcChar8 **) &file) != FcResultMatch)
+ goto bail3;
+ base = FcFileBaseName (cache_file, file);
+ if (FcPatternGetInteger (font, FC_INDEX, 0, &id) != FcResultMatch)
+ goto bail3;
+ if (FcDebug () & FC_DBG_CACHEV)
+ printf (" write file \"%s\"\n", base);
+ if (!FcCacheWriteString (f, base))
+ goto bail3;
+ if (PUTC (' ', f) == EOF)
+ goto bail3;
+ if (!FcCacheWriteInt (f, id))
+ goto bail3;
+ if (PUTC (' ', f) == EOF)
+ goto bail3;
+ name = FcNameUnparse (font);
+ if (!name)
+ goto bail3;
+ ret = FcCacheWriteString (f, name);
+ FcStrFree (name);
+ if (!ret)
+ goto bail3;
+ if (PUTC ('\n', f) == EOF)
+ goto bail3;
+ }
+
+ FcStrListDone (list);
+
+ if (fclose (f) == EOF)
+ goto bail1;
+
+ FcStrFree (cache_file);
+
+ if (FcDebug () & FC_DBG_CACHE)
+ printf (" cache written\n");
+ return FcTrue;
+
+bail3:
+ FcStrListDone (list);
+bail2:
+ fclose (f);
+bail1:
+ unlink ((char *) cache_file);
+ FcStrFree (cache_file);
+bail0:
+ return FcFalse;
+}
diff --git a/nx-X11/extras/fontconfig/src/fccfg.c b/nx-X11/extras/fontconfig/src/fccfg.c
new file mode 100644
index 000000000..551dbe191
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fccfg.c
@@ -0,0 +1,1892 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fccfg.c,v 1.23 2002/08/31 22:17:32 keithp Exp $
+ *
+ * Copyright © 2000 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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"
+
+#if defined (_WIN32) && (defined (PIC) || defined (DLL_EXPORT))
+#define STRICT
+#include <windows.h>
+#undef STRICT
+#endif
+
+#if defined (_WIN32) && !defined (R_OK)
+#define R_OK 4
+#endif
+
+FcConfig *_fcConfig;
+
+FcConfig *
+FcConfigCreate (void)
+{
+ FcSetName set;
+ FcConfig *config;
+
+ config = malloc (sizeof (FcConfig));
+ if (!config)
+ goto bail0;
+ FcMemAlloc (FC_MEM_CONFIG, sizeof (FcConfig));
+
+ config->configDirs = FcStrSetCreate ();
+ if (!config->configDirs)
+ goto bail1;
+
+ config->configFiles = FcStrSetCreate ();
+ if (!config->configFiles)
+ goto bail2;
+
+ config->fontDirs = FcStrSetCreate ();
+ if (!config->fontDirs)
+ goto bail3;
+
+ config->acceptGlobs = FcStrSetCreate ();
+ if (!config->acceptGlobs)
+ goto bail4;
+
+ config->rejectGlobs = FcStrSetCreate ();
+ if (!config->rejectGlobs)
+ goto bail5;
+
+ config->acceptPatterns = FcFontSetCreate ();
+ if (!config->acceptPatterns)
+ goto bail6;
+
+ config->rejectPatterns = FcFontSetCreate ();
+ if (!config->rejectPatterns)
+ goto bail7;
+
+ config->cache = 0;
+ if (FcConfigHome())
+ if (!FcConfigSetCache (config, (FcChar8 *) ("~/" FC_USER_CACHE_FILE)))
+ goto bail8;
+
+#ifdef _WIN32
+ if (config->cache == 0)
+ {
+ /* If no home, use the temp folder. */
+ FcChar8 dummy[1];
+ int templen = GetTempPath (1, dummy);
+ FcChar8 *temp = malloc (templen + 1);
+
+ if (temp)
+ {
+ FcChar8 *cache_dir;
+
+ GetTempPath (templen + 1, temp);
+ cache_dir = FcStrPlus (temp, FC_USER_CACHE_FILE);
+ free (temp);
+ if (!FcConfigSetCache (config, cache_dir))
+ {
+ FcStrFree (cache_dir);
+ goto bail6;
+ }
+ FcStrFree (cache_dir);
+ }
+ }
+#endif
+
+ config->blanks = 0;
+
+ config->substPattern = 0;
+ config->substFont = 0;
+ config->maxObjects = 0;
+ for (set = FcSetSystem; set <= FcSetApplication; set++)
+ config->fonts[set] = 0;
+
+ config->rescanTime = time(0);
+ config->rescanInterval = 30;
+
+ return config;
+
+bail8:
+ FcFontSetDestroy (config->rejectPatterns);
+bail7:
+ FcFontSetDestroy (config->acceptPatterns);
+bail6:
+ FcStrSetDestroy (config->rejectGlobs);
+bail5:
+ FcStrSetDestroy (config->acceptGlobs);
+bail4:
+ FcStrSetDestroy (config->fontDirs);
+bail3:
+ FcStrSetDestroy (config->configFiles);
+bail2:
+ FcStrSetDestroy (config->configDirs);
+bail1:
+ free (config);
+ FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
+bail0:
+ return 0;
+}
+
+typedef struct _FcFileTime {
+ time_t time;
+ FcBool set;
+} FcFileTime;
+
+static FcFileTime
+FcConfigNewestFile (FcStrSet *files)
+{
+ FcStrList *list = FcStrListCreate (files);
+ FcFileTime newest = { 0, FcFalse };
+ FcChar8 *file;
+ struct stat statb;
+
+ if (list)
+ {
+ while ((file = FcStrListNext (list)))
+ if (stat ((char *) file, &statb) == 0)
+ if (!newest.set || statb.st_mtime - newest.time > 0)
+ {
+ newest.set = FcTrue;
+ newest.time = statb.st_mtime;
+ }
+ FcStrListDone (list);
+ }
+ return newest;
+}
+
+FcBool
+FcConfigUptoDate (FcConfig *config)
+{
+ FcFileTime config_time, font_time;
+ time_t now = time(0);
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return FcFalse;
+ }
+ config_time = FcConfigNewestFile (config->configFiles);
+ font_time = FcConfigNewestFile (config->fontDirs);
+ if ((config_time.set && config_time.time - config->rescanTime > 0) ||
+ (font_time.set && (font_time.time - config->rescanTime) > 0))
+ {
+ return FcFalse;
+ }
+ config->rescanTime = now;
+ return FcTrue;
+}
+
+static void
+FcSubstDestroy (FcSubst *s)
+{
+ FcSubst *n;
+
+ while (s)
+ {
+ n = s->next;
+ if (s->test)
+ FcTestDestroy (s->test);
+ if (s->edit)
+ FcEditDestroy (s->edit);
+ free (s);
+ FcMemFree (FC_MEM_SUBST, sizeof (FcSubst));
+ s = n;
+ }
+}
+
+void
+FcConfigDestroy (FcConfig *config)
+{
+ FcSetName set;
+
+ if (config == _fcConfig)
+ _fcConfig = 0;
+
+ FcStrSetDestroy (config->configDirs);
+ FcStrSetDestroy (config->fontDirs);
+ FcStrSetDestroy (config->configFiles);
+ FcStrSetDestroy (config->acceptGlobs);
+ FcStrSetDestroy (config->rejectGlobs);
+ FcFontSetDestroy (config->acceptPatterns);
+ FcFontSetDestroy (config->rejectPatterns);
+
+ if (config->blanks)
+ FcBlanksDestroy (config->blanks);
+
+ if (config->cache)
+ FcStrFree (config->cache);
+
+ FcSubstDestroy (config->substPattern);
+ FcSubstDestroy (config->substFont);
+ for (set = FcSetSystem; set <= FcSetApplication; set++)
+ if (config->fonts[set])
+ FcFontSetDestroy (config->fonts[set]);
+
+ free (config);
+ FcMemFree (FC_MEM_CONFIG, sizeof (FcConfig));
+}
+
+/*
+ * Scan the current list of directories in the configuration
+ * and build the set of available fonts. Update the
+ * per-user cache file to reflect the new configuration
+ */
+
+FcBool
+FcConfigBuildFonts (FcConfig *config)
+{
+ FcFontSet *fonts;
+ FcGlobalCache *cache;
+ FcStrList *list;
+ FcChar8 *dir;
+
+ fonts = FcFontSetCreate ();
+ if (!fonts)
+ goto bail0;
+
+ cache = FcGlobalCacheCreate ();
+ if (!cache)
+ goto bail1;
+
+ if (config->cache)
+ FcGlobalCacheLoad (cache, config->cache);
+
+ list = FcConfigGetFontDirs (config);
+ if (!list)
+ goto bail1;
+
+ while ((dir = FcStrListNext (list)))
+ {
+ if (FcDebug () & FC_DBG_FONTSET)
+ printf ("scan dir %s\n", dir);
+ FcDirScanConfig (fonts, config->fontDirs, cache,
+ config->blanks, dir, FcFalse, config);
+ }
+
+ FcStrListDone (list);
+
+ if (FcDebug () & FC_DBG_FONTSET)
+ FcFontSetPrint (fonts);
+
+ if (config->cache)
+ FcGlobalCacheSave (cache, config->cache);
+ FcGlobalCacheDestroy (cache);
+
+ FcConfigSetFonts (config, fonts, FcSetSystem);
+
+ return FcTrue;
+bail1:
+ FcFontSetDestroy (fonts);
+bail0:
+ return FcFalse;
+}
+
+FcBool
+FcConfigSetCurrent (FcConfig *config)
+{
+ if (!config->fonts)
+ if (!FcConfigBuildFonts (config))
+ return FcFalse;
+
+ if (_fcConfig)
+ FcConfigDestroy (_fcConfig);
+ _fcConfig = config;
+ return FcTrue;
+}
+
+FcConfig *
+FcConfigGetCurrent (void)
+{
+ if (!_fcConfig)
+ if (!FcInit ())
+ return 0;
+ return _fcConfig;
+}
+
+FcBool
+FcConfigAddConfigDir (FcConfig *config,
+ const FcChar8 *d)
+{
+ return FcStrSetAddFilename (config->configDirs, d);
+}
+
+FcStrList *
+FcConfigGetConfigDirs (FcConfig *config)
+{
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return 0;
+ }
+ return FcStrListCreate (config->configDirs);
+}
+
+FcBool
+FcConfigAddFontDir (FcConfig *config,
+ const FcChar8 *d)
+{
+ return FcStrSetAddFilename (config->fontDirs, d);
+}
+
+FcBool
+FcConfigAddDir (FcConfig *config,
+ const FcChar8 *d)
+{
+ return (FcConfigAddConfigDir (config, d) &&
+ FcConfigAddFontDir (config, d));
+}
+
+FcStrList *
+FcConfigGetFontDirs (FcConfig *config)
+{
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return 0;
+ }
+ return FcStrListCreate (config->fontDirs);
+}
+
+FcBool
+FcConfigAddConfigFile (FcConfig *config,
+ const FcChar8 *f)
+{
+ FcBool ret;
+ FcChar8 *file = FcConfigFilename (f);
+
+ if (!file)
+ return FcFalse;
+
+ ret = FcStrSetAdd (config->configFiles, file);
+ FcStrFree (file);
+ return ret;
+}
+
+FcStrList *
+FcConfigGetConfigFiles (FcConfig *config)
+{
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return 0;
+ }
+ return FcStrListCreate (config->configFiles);
+}
+
+FcBool
+FcConfigSetCache (FcConfig *config,
+ const FcChar8 *c)
+{
+ FcChar8 *new = FcStrCopyFilename (c);
+
+ if (!new)
+ return FcFalse;
+ if (config->cache)
+ FcStrFree (config->cache);
+ config->cache = new;
+ return FcTrue;
+}
+
+FcChar8 *
+FcConfigGetCache (FcConfig *config)
+{
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return 0;
+ }
+ return config->cache;
+}
+
+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)
+{
+ FcBlanks *b;
+
+ b = config->blanks;
+ if (!b)
+ {
+ b = FcBlanksCreate ();
+ if (!b)
+ return FcFalse;
+ }
+ if (!FcBlanksAdd (b, blank))
+ return FcFalse;
+ config->blanks = b;
+ return FcTrue;
+}
+
+int
+FcConfigGetRescanInverval (FcConfig *config)
+{
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return 0;
+ }
+ return config->rescanInterval;
+}
+
+FcBool
+FcConfigSetRescanInverval (FcConfig *config, int rescanInterval)
+{
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return FcFalse;
+ }
+ config->rescanInterval = rescanInterval;
+ return FcTrue;
+}
+
+FcBool
+FcConfigAddEdit (FcConfig *config,
+ FcTest *test,
+ FcEdit *edit,
+ FcMatchKind kind)
+{
+ FcSubst *subst, **prev;
+ FcTest *t;
+ int num;
+
+ subst = (FcSubst *) malloc (sizeof (FcSubst));
+ if (!subst)
+ return FcFalse;
+ FcMemAlloc (FC_MEM_SUBST, sizeof (FcSubst));
+ if (kind == FcMatchPattern)
+ prev = &config->substPattern;
+ else
+ prev = &config->substFont;
+ 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)
+ {
+ if (t->kind == FcMatchDefault)
+ t->kind = kind;
+ num++;
+ }
+ if (config->maxObjects < num)
+ config->maxObjects = num;
+ if (FcDebug () & FC_DBG_EDIT)
+ {
+ printf ("Add Subst ");
+ FcSubstPrint (subst);
+ }
+ 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)
+ {
+ v.u.m = &FcIdentityMatrix;
+ v.type = FcTypeMatrix;
+ }
+ else if (v.type == FcTypeString && u.type == FcTypeLangSet)
+ {
+ v.u.l = FcLangSetPromote (v.u.s);
+ v.type = FcTypeLangSet;
+ }
+ return v;
+}
+
+FcBool
+FcConfigCompareValue (const FcValue left_o,
+ FcOp op,
+ const FcValue right_o)
+{
+ FcValue left = left_o;
+ FcValue right = right_o;
+ FcBool ret = FcFalse;
+
+ left = FcConfigPromote (left, right);
+ right = FcConfigPromote (right, left);
+ if (left.type == right.type)
+ {
+ switch (left.type) {
+ case FcTypeInteger:
+ break; /* FcConfigPromote prevents this from happening */
+ case FcTypeDouble:
+ switch (op) {
+ case FcOpEqual:
+ case FcOpContains:
+ case FcOpListing:
+ ret = left.u.d == right.u.d;
+ break;
+ case FcOpNotEqual:
+ case FcOpNotContains:
+ ret = left.u.d != right.u.d;
+ break;
+ case FcOpLess:
+ ret = left.u.d < right.u.d;
+ break;
+ case FcOpLessEqual:
+ ret = left.u.d <= right.u.d;
+ break;
+ case FcOpMore:
+ ret = left.u.d > right.u.d;
+ break;
+ case FcOpMoreEqual:
+ ret = left.u.d >= right.u.d;
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeBool:
+ switch (op) {
+ case FcOpEqual:
+ case FcOpContains:
+ case FcOpListing:
+ ret = left.u.b == right.u.b;
+ break;
+ case FcOpNotEqual:
+ case FcOpNotContains:
+ ret = left.u.b != right.u.b;
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeString:
+ switch (op) {
+ case FcOpEqual:
+ case FcOpListing:
+ ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) == 0;
+ break;
+ case FcOpContains:
+ ret = FcStrStrIgnoreCase (left.u.s, right.u.s) != 0;
+ break;
+ case FcOpNotEqual:
+ case FcOpNotContains:
+ ret = FcStrCmpIgnoreCase (left.u.s, right.u.s) != 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeMatrix:
+ switch (op) {
+ case FcOpEqual:
+ case FcOpContains:
+ case FcOpListing:
+ ret = FcMatrixEqual (left.u.m, right.u.m);
+ break;
+ case FcOpNotEqual:
+ case FcOpNotContains:
+ ret = !FcMatrixEqual (left.u.m, right.u.m);
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeCharSet:
+ switch (op) {
+ case FcOpContains:
+ case FcOpListing:
+ /* left contains right if right is a subset of left */
+ ret = FcCharSetIsSubset (right.u.c, left.u.c);
+ break;
+ case FcOpNotContains:
+ /* left contains right if right is a subset of left */
+ ret = !FcCharSetIsSubset (right.u.c, left.u.c);
+ break;
+ case FcOpEqual:
+ ret = FcCharSetEqual (left.u.c, right.u.c);
+ break;
+ case FcOpNotEqual:
+ ret = !FcCharSetEqual (left.u.c, right.u.c);
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeLangSet:
+ switch (op) {
+ case FcOpContains:
+ case FcOpListing:
+ ret = FcLangSetContains (left.u.l, right.u.l);
+ break;
+ case FcOpNotContains:
+ ret = !FcLangSetContains (left.u.l, right.u.l);
+ break;
+ case FcOpEqual:
+ ret = FcLangSetEqual (left.u.l, right.u.l);
+ break;
+ case FcOpNotEqual:
+ ret = !FcLangSetEqual (left.u.l, right.u.l);
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeVoid:
+ switch (op) {
+ case FcOpEqual:
+ case FcOpContains:
+ case FcOpListing:
+ ret = FcTrue;
+ break;
+ default:
+ break;
+ }
+ break;
+ case FcTypeFTFace:
+ switch (op) {
+ case FcOpEqual:
+ case FcOpContains:
+ case FcOpListing:
+ ret = left.u.f == right.u.f;
+ break;
+ case FcOpNotEqual:
+ case FcOpNotContains:
+ ret = left.u.f != right.u.f;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+ else
+ {
+ if (op == FcOpNotEqual || op == FcOpNotContains)
+ ret = FcTrue;
+ }
+ return ret;
+}
+
+
+#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)))
+
+static FcValue
+FcConfigEvaluate (FcPattern *p, FcExpr *e)
+{
+ FcValue v, vl, vr;
+ FcResult r;
+ FcMatrix *m;
+
+ 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;
+ v.u.s = e->u.sval;
+ v = FcValueSave (v);
+ break;
+ case FcOpMatrix:
+ v.type = FcTypeMatrix;
+ v.u.m = e->u.mval;
+ v = FcValueSave (v);
+ break;
+ case FcOpCharSet:
+ v.type = FcTypeCharSet;
+ v.u.c = e->u.cval;
+ v = FcValueSave (v);
+ break;
+ case FcOpBool:
+ v.type = FcTypeBool;
+ v.u.b = e->u.bval;
+ break;
+ case FcOpField:
+ r = FcPatternGet (p, e->u.field, 0, &v);
+ if (r != FcResultMatch)
+ v.type = FcTypeVoid;
+ 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;
+ case FcOpEqual:
+ case FcOpNotEqual:
+ case FcOpLess:
+ case FcOpLessEqual:
+ case FcOpMore:
+ case FcOpMoreEqual:
+ case FcOpContains:
+ case FcOpNotContains:
+ case FcOpListing:
+ vl = FcConfigEvaluate (p, e->u.tree.left);
+ vr = FcConfigEvaluate (p, e->u.tree.right);
+ v.type = FcTypeBool;
+ v.u.b = FcConfigCompareValue (vl, e->op, vr);
+ FcValueDestroy (vl);
+ FcValueDestroy (vr);
+ break;
+ case FcOpOr:
+ case FcOpAnd:
+ 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) {
+ case FcOpPlus:
+ v.type = FcTypeDouble;
+ v.u.d = vl.u.d + vr.u.d;
+ break;
+ case FcOpMinus:
+ v.type = FcTypeDouble;
+ v.u.d = vl.u.d - vr.u.d;
+ break;
+ case FcOpTimes:
+ v.type = FcTypeDouble;
+ v.u.d = vl.u.d * vr.u.d;
+ break;
+ case FcOpDivide:
+ v.type = FcTypeDouble;
+ v.u.d = vl.u.d / vr.u.d;
+ break;
+ default:
+ v.type = FcTypeVoid;
+ 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:
+ v.type = FcTypeVoid;
+ break;
+ }
+ break;
+ case FcTypeString:
+ switch (e->op) {
+ case FcOpPlus:
+ v.type = FcTypeString;
+ v.u.s = FcStrPlus (vl.u.s, vr.u.s);
+ if (!v.u.s)
+ v.type = FcTypeVoid;
+ break;
+ default:
+ v.type = FcTypeVoid;
+ break;
+ }
+ break;
+ case FcTypeMatrix:
+ switch (e->op) {
+ case FcOpTimes:
+ v.type = FcTypeMatrix;
+ m = malloc (sizeof (FcMatrix));
+ if (m)
+ {
+ FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix));
+ FcMatrixMultiply (m, vl.u.m, vr.u.m);
+ v.u.m = m;
+ }
+ 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;
+ 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;
+ default:
+ v.type = FcTypeVoid;
+ break;
+ }
+ return v;
+}
+
+static FcValueList *
+FcConfigMatchValueList (FcPattern *p,
+ FcTest *t,
+ FcValueList *values)
+{
+ FcValueList *ret = 0;
+ FcExpr *e = t->expr;
+ FcValue value;
+ FcValueList *v;
+
+ while (e)
+ {
+ /* Compute the value of the match expression */
+ if (e->op == FcOpComma)
+ {
+ value = FcConfigEvaluate (p, e->u.tree.left);
+ e = e->u.tree.right;
+ }
+ else
+ {
+ value = FcConfigEvaluate (p, e);
+ e = 0;
+ }
+
+ for (v = values; v; v = v->next)
+ {
+ /* Compare the pattern value to the match expression value */
+ if (FcConfigCompareValue (v->value, t->op, value))
+ {
+ if (!ret)
+ ret = v;
+ }
+ else
+ {
+ if (t->qual == FcQualAll)
+ {
+ ret = 0;
+ break;
+ }
+ }
+ }
+ FcValueDestroy (value);
+ }
+ return ret;
+}
+
+static FcValueList *
+FcConfigValues (FcPattern *p, FcExpr *e, FcValueBinding binding)
+{
+ FcValueList *l;
+
+ 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);
+ l->next = FcConfigValues (p, e->u.tree.right, binding);
+ }
+ else
+ {
+ l->value = FcConfigEvaluate (p, e);
+ l->next = 0;
+ }
+ l->binding = binding;
+ while (l && l->value.type == FcTypeVoid)
+ {
+ FcValueList *next = l->next;
+
+ FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
+ free (l);
+ l = next;
+ }
+ return l;
+}
+
+static FcBool
+FcConfigAdd (FcValueList **head,
+ FcValueList *position,
+ FcBool append,
+ FcValueList *new)
+{
+ FcValueList **prev, *last, *v;
+ FcValueBinding sameBinding;
+
+ if (position)
+ sameBinding = position->binding;
+ else
+ sameBinding = FcValueBindingWeak;
+ for (v = new; v; v = v->next)
+ if (v->binding == FcValueBindingSame)
+ v->binding = sameBinding;
+ if (append)
+ {
+ if (position)
+ prev = &position->next;
+ else
+ for (prev = head; *prev; prev = &(*prev)->next)
+ ;
+ }
+ else
+ {
+ if (position)
+ {
+ for (prev = head; *prev; prev = &(*prev)->next)
+ {
+ if (*prev == position)
+ break;
+ }
+ }
+ else
+ prev = head;
+
+ if (FcDebug () & FC_DBG_EDIT)
+ {
+ if (!*prev)
+ printf ("position not on list\n");
+ }
+ }
+
+ if (FcDebug () & FC_DBG_EDIT)
+ {
+ printf ("%s list before ", append ? "Append" : "Prepend");
+ FcValueListPrint (*head);
+ printf ("\n");
+ }
+
+ if (new)
+ {
+ last = new;
+ while (last->next)
+ last = last->next;
+
+ last->next = *prev;
+ *prev = new;
+ }
+
+ if (FcDebug () & FC_DBG_EDIT)
+ {
+ printf ("%s list after ", append ? "Append" : "Prepend");
+ FcValueListPrint (*head);
+ printf ("\n");
+ }
+
+ return FcTrue;
+}
+
+static void
+FcConfigDel (FcValueList **head,
+ FcValueList *position)
+{
+ FcValueList **prev;
+
+ for (prev = head; *prev; prev = &(*prev)->next)
+ {
+ if (*prev == position)
+ {
+ *prev = position->next;
+ position->next = 0;
+ FcValueListDestroy (position);
+ break;
+ }
+ }
+}
+
+static void
+FcConfigPatternAdd (FcPattern *p,
+ const char *object,
+ FcValueList *list,
+ FcBool append)
+{
+ if (list)
+ {
+ FcPatternElt *e = FcPatternInsertElt (p, object);
+
+ if (!e)
+ return;
+ FcConfigAdd (&e->values, 0, append, list);
+ }
+}
+
+/*
+ * Delete all values associated with a field
+ */
+static void
+FcConfigPatternDel (FcPattern *p,
+ const char *object)
+{
+ FcPatternElt *e = FcPatternFindElt (p, object);
+ if (!e)
+ return;
+ while (e->values)
+ FcConfigDel (&e->values, e->values);
+}
+
+static void
+FcConfigPatternCanon (FcPattern *p,
+ const char *object)
+{
+ FcPatternElt *e = FcPatternFindElt (p, object);
+ if (!e)
+ return;
+ if (!e->values)
+ FcPatternDel (p, object);
+}
+
+FcBool
+FcConfigSubstituteWithPat (FcConfig *config,
+ FcPattern *p,
+ FcPattern *p_pat,
+ FcMatchKind kind)
+{
+ FcSubst *s;
+ FcSubState *st;
+ int i;
+ FcTest *t;
+ FcEdit *e;
+ FcValueList *l;
+ FcPattern *m;
+
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return FcFalse;
+ }
+
+ 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);
+ }
+ if (kind == FcMatchPattern)
+ s = config->substPattern;
+ else
+ s = config->substFont;
+ 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);
+ }
+ st[i].elt = 0;
+ if (kind == FcMatchFont && t->kind == FcMatchPattern)
+ m = p_pat;
+ else
+ m = p;
+ if (m)
+ st[i].elt = FcPatternFindElt (m, t->field);
+ else
+ st[i].elt = 0;
+ /*
+ * 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
+ */
+ st[i].value = FcConfigMatchValueList (m, t, st[i].elt->values);
+ if (!st[i].value)
+ break;
+ if (t->qual == FcQualFirst && st[i].value != st[i].elt->values)
+ break;
+ if (t->qual == FcQualNotFirst && st[i].value == st[i].elt->values)
+ break;
+ }
+ 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
+ */
+ l = FcConfigValues (p, e->expr, e->binding);
+ /*
+ * Locate any test associated with this field, skipping
+ * tests associated with the pattern when substituting in
+ * the font
+ */
+ for (t = s->test, i = 0; t; t = t->next, i++)
+ {
+ if ((t->kind == FcMatchFont || kind == FcMatchPattern) &&
+ !FcStrCmpIgnoreCase ((FcChar8 *) t->field,
+ (FcChar8 *) e->field))
+ {
+ /*
+ * 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)
+ st[i].elt = FcPatternFindElt (p, t->field);
+ if (!st[i].elt)
+ t = 0;
+ break;
+ }
+ }
+ switch (e->op) {
+ case FcOpAssign:
+ /*
+ * If there was a test, then replace the matched
+ * value with the new list of values
+ */
+ if (t)
+ {
+ FcValueList *thisValue = st[i].value;
+ FcValueList *nextValue = thisValue ? thisValue->next : 0;
+
+ /*
+ * Append the new list of values after the current value
+ */
+ FcConfigAdd (&st[i].elt->values, thisValue, FcTrue, l);
+ /*
+ * Delete the marked value
+ */
+ FcConfigDel (&st[i].elt->values, thisValue);
+ /*
+ * 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
+ */
+ FcConfigPatternDel (p, e->field);
+ FcConfigPatternAdd (p, e->field, l, FcTrue);
+ /*
+ * 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:
+ FcConfigPatternAdd (p, e->field, l, FcFalse);
+ break;
+ case FcOpAppend:
+ if (t)
+ {
+ FcConfigAdd (&st[i].elt->values, st[i].value, FcTrue, l);
+ break;
+ }
+ /* fall through ... */
+ case FcOpAppendLast:
+ FcConfigPatternAdd (p, e->field, l, FcTrue);
+ break;
+ default:
+ break;
+ }
+ }
+ /*
+ * Now go through the pattern and eliminate
+ * any properties without data
+ */
+ for (e = s->edit; e; e = e->next)
+ FcConfigPatternCanon (p, e->field);
+
+ 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;
+}
+
+FcBool
+FcConfigSubstitute (FcConfig *config,
+ FcPattern *p,
+ FcMatchKind kind)
+{
+ return FcConfigSubstituteWithPat (config, p, 0, kind);
+}
+
+#if defined (_WIN32) && (defined (PIC) || defined (DLL_EXPORT))
+
+static FcChar8 fontconfig_path[1000] = "";
+
+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';
+
+ break;
+ }
+
+ return TRUE;
+}
+
+#undef FONTCONFIG_PATH
+#define FONTCONFIG_PATH fontconfig_path
+
+#else /* !(_WIN32 && PIC) */
+
+#endif /* !(_WIN32 && PIC) */
+
+#ifndef FONTCONFIG_FILE
+#define FONTCONFIG_FILE "fonts.conf"
+#endif
+
+static FcChar8 *
+FcConfigFileExists (const FcChar8 *dir, const FcChar8 *file)
+{
+ FcChar8 *path;
+
+ if (!dir)
+ dir = (FcChar8 *) "";
+ path = malloc (strlen ((char *) dir) + 1 + strlen ((char *) file) + 1);
+ if (!path)
+ return 0;
+
+ strcpy ((char *) path, (const char *) dir);
+ /* make sure there's a single separator */
+#ifdef _WIN32
+ if ((!path[0] || (path[strlen((char *) path)-1] != '/' &&
+ path[strlen((char *) path)-1] != '\\')) &&
+ !(file[0] == '/' ||
+ file[0] == '\\' ||
+ (isalpha (file[0]) && file[1] == ':' && (file[2] == '/' || file[2] == '\\'))))
+ strcat ((char *) path, "\\");
+#else
+ if ((!path[0] || path[strlen((char *) path)-1] != '/') && file[0] != '/')
+ strcat ((char *) path, "/");
+#endif
+ strcat ((char *) path, (char *) file);
+
+ FcMemAlloc (FC_MEM_STRING, strlen ((char *) path) + 1);
+ if (access ((char *) path, R_OK) == 0)
+ return path;
+
+ FcStrFree (path);
+ return 0;
+}
+
+static FcChar8 **
+FcConfigGetPath (void)
+{
+ FcChar8 **path;
+ FcChar8 *env, *e, *colon;
+ FcChar8 *dir;
+ int npath;
+ int i;
+
+ npath = 2; /* default dir + null */
+ env = (FcChar8 *) getenv ("FONTCONFIG_PATH");
+ if (env)
+ {
+ e = env;
+ npath++;
+ while (*e)
+ if (*e++ == FC_SEARCH_PATH_SEPARATOR)
+ npath++;
+ }
+ path = calloc (npath, sizeof (FcChar8 *));
+ if (!path)
+ goto bail0;
+ i = 0;
+
+ if (env)
+ {
+ e = env;
+ while (*e)
+ {
+ colon = (FcChar8 *) strchr ((char *) e, FC_SEARCH_PATH_SEPARATOR);
+ if (!colon)
+ colon = e + strlen ((char *) e);
+ path[i] = malloc (colon - e + 1);
+ if (!path[i])
+ goto bail1;
+ strncpy ((char *) path[i], (const char *) e, colon - e);
+ path[i][colon - e] = '\0';
+ if (*colon)
+ e = colon + 1;
+ else
+ e = colon;
+ i++;
+ }
+ }
+
+ dir = (FcChar8 *) FONTCONFIG_PATH;
+ path[i] = malloc (strlen ((char *) dir) + 1);
+ if (!path[i])
+ goto bail1;
+ strcpy ((char *) path[i], (const char *) dir);
+ return path;
+
+bail1:
+ for (i = 0; path[i]; i++)
+ free (path[i]);
+ free (path);
+bail0:
+ return 0;
+}
+
+static void
+FcConfigFreePath (FcChar8 **path)
+{
+ FcChar8 **p;
+
+ for (p = path; *p; p++)
+ free (*p);
+ free (path);
+}
+
+static FcBool _FcConfigHomeEnabled = FcTrue;
+
+FcChar8 *
+FcConfigHome (void)
+{
+ if (_FcConfigHomeEnabled)
+ {
+ char *home = getenv ("HOME");
+
+#ifdef _WIN32
+ if (home == NULL)
+ home = getenv ("USERPROFILE");
+#endif
+
+ return home;
+ }
+ return 0;
+}
+
+FcBool
+FcConfigEnableHome (FcBool enable)
+{
+ FcBool prev = _FcConfigHomeEnabled;
+ _FcConfigHomeEnabled = enable;
+ return prev;
+}
+
+FcChar8 *
+FcConfigFilename (const FcChar8 *url)
+{
+ FcChar8 *file, *dir, **path, **p;
+
+ if (!url || !*url)
+ {
+ url = (FcChar8 *) getenv ("FONTCONFIG_FILE");
+ if (!url)
+ url = (FcChar8 *) FONTCONFIG_FILE;
+ }
+ file = 0;
+
+#ifdef _WIN32
+ if (isalpha (*url) &&
+ url[1] == ':' &&
+ (url[2] == '/' || url[2] == '\\'))
+ goto absolute_path;
+#endif
+
+ switch (*url) {
+ case '~':
+ dir = FcConfigHome ();
+ if (dir)
+ file = FcConfigFileExists (dir, url + 1);
+ else
+ file = 0;
+ break;
+#ifdef _WIN32
+ case '\\':
+ absolute_path:
+#endif
+ 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,
+ const FcChar8 *file)
+{
+ FcFontSet *set;
+ FcStrSet *subdirs;
+ FcStrList *sublist;
+ FcChar8 *subdir;
+
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return FcFalse;
+ }
+
+ subdirs = FcStrSetCreate ();
+ if (!subdirs)
+ return FcFalse;
+
+ set = FcConfigGetFonts (config, FcSetApplication);
+ if (!set)
+ {
+ set = FcFontSetCreate ();
+ if (!set)
+ {
+ FcStrSetDestroy (subdirs);
+ return FcFalse;
+ }
+ FcConfigSetFonts (config, set, FcSetApplication);
+ }
+
+ if (!FcFileScanConfig (set, subdirs, 0, config->blanks, file, FcFalse, config))
+ {
+ FcStrSetDestroy (subdirs);
+ return FcFalse;
+ }
+ if ((sublist = FcStrListCreate (subdirs)))
+ {
+ while ((subdir = FcStrListNext (sublist)))
+ {
+ FcConfigAppFontAddDir (config, subdir);
+ }
+ FcStrListDone (sublist);
+ }
+ return FcTrue;
+}
+
+FcBool
+FcConfigAppFontAddDir (FcConfig *config,
+ const FcChar8 *dir)
+{
+ FcFontSet *set;
+ FcStrSet *subdirs;
+ FcStrList *sublist;
+ FcChar8 *subdir;
+
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return FcFalse;
+ }
+ subdirs = FcStrSetCreate ();
+ if (!subdirs)
+ return FcFalse;
+
+ set = FcConfigGetFonts (config, FcSetApplication);
+ if (!set)
+ {
+ set = FcFontSetCreate ();
+ if (!set)
+ {
+ FcStrSetDestroy (subdirs);
+ return FcFalse;
+ }
+ FcConfigSetFonts (config, set, FcSetApplication);
+ }
+
+ if (!FcDirScanConfig (set, subdirs, 0, config->blanks, dir, FcFalse, config))
+ {
+ FcStrSetDestroy (subdirs);
+ return FcFalse;
+ }
+ if ((sublist = FcStrListCreate (subdirs)))
+ {
+ while ((subdir = FcStrListNext (sublist)))
+ {
+ FcConfigAppFontAddDir (config, subdir);
+ }
+ FcStrListDone (sublist);
+ }
+ return FcTrue;
+}
+
+void
+FcConfigAppFontClear (FcConfig *config)
+{
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return;
+ }
+
+ FcConfigSetFonts (config, 0, FcSetApplication);
+}
+
+/*
+ * 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;
+
+ while ((c = *glob++))
+ {
+ 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++)
+ if (FcConfigGlobMatch (globs->strs[i], string))
+ 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;
+}
+
+/*
+ * 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;
+
+ 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;
+}
diff --git a/nx-X11/extras/fontconfig/src/fccharset.c b/nx-X11/extras/fontconfig/src/fccharset.c
new file mode 100644
index 000000000..8003bccc3
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fccharset.c
@@ -0,0 +1,1231 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fccharset.c,v 1.18 2002/08/22 07:36:44 keithp Exp $
+ *
+ * Copyright © 2001 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include "fcint.h"
+
+/* #define CHECK */
+
+/* #define CHATTY */
+
+FcCharSet *
+FcCharSetCreate (void)
+{
+ FcCharSet *fcs;
+
+ fcs = (FcCharSet *) malloc (sizeof (FcCharSet));
+ if (!fcs)
+ return 0;
+ FcMemAlloc (FC_MEM_CHARSET, sizeof (FcCharSet));
+ fcs->ref = 1;
+ fcs->num = 0;
+ fcs->leaves = 0;
+ fcs->numbers = 0;
+ return fcs;
+}
+
+FcCharSet *
+FcCharSetNew (void);
+
+FcCharSet *
+FcCharSetNew (void)
+{
+ return FcCharSetCreate ();
+}
+
+
+void
+FcCharSetDestroy (FcCharSet *fcs)
+{
+ int i;
+ if (fcs->ref == FC_REF_CONSTANT)
+ return;
+ if (--fcs->ref > 0)
+ return;
+ for (i = 0; i < fcs->num; i++)
+ {
+ FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
+ free (fcs->leaves[i]);
+ }
+ if (fcs->leaves)
+ {
+ FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *));
+ free (fcs->leaves);
+ }
+ if (fcs->numbers)
+ {
+ FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
+ free (fcs->numbers);
+ }
+ FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
+ free (fcs);
+}
+
+/*
+ * Locate the leaf containing the specified char, return
+ * its index if it exists, otherwise return negative of
+ * the (position + 1) where it should be inserted
+ */
+
+static int
+FcCharSetFindLeafPos (const FcCharSet *fcs, FcChar32 ucs4)
+{
+ FcChar16 *numbers = fcs->numbers;
+ FcChar16 page;
+ int low = 0;
+ int high = fcs->num - 1;
+
+ if (!numbers)
+ return -1;
+ ucs4 >>= 8;
+ while (low <= high)
+ {
+ int mid = (low + high) >> 1;
+ page = numbers[mid];
+ if (page == ucs4)
+ return mid;
+ if (page < ucs4)
+ low = mid + 1;
+ else
+ high = mid - 1;
+ }
+ if (high < 0 || (high < fcs->num && numbers[high] < ucs4))
+ high++;
+ return -(high + 1);
+}
+
+static FcCharLeaf *
+FcCharSetFindLeaf (const FcCharSet *fcs, FcChar32 ucs4)
+{
+ int pos = FcCharSetFindLeafPos (fcs, ucs4);
+ if (pos >= 0)
+ return fcs->leaves[pos];
+ return 0;
+}
+
+static FcBool
+FcCharSetPutLeaf (FcCharSet *fcs,
+ FcChar32 ucs4,
+ FcCharLeaf *leaf,
+ int pos)
+{
+ FcCharLeaf **leaves;
+ FcChar16 *numbers;
+
+ ucs4 >>= 8;
+ if (ucs4 >= 0x10000)
+ return FcFalse;
+ if (!fcs->leaves)
+ leaves = malloc (sizeof (FcCharLeaf *));
+ else
+ leaves = realloc (fcs->leaves, (fcs->num + 1) * sizeof (FcCharLeaf *));
+ if (!leaves)
+ return FcFalse;
+ if (fcs->num)
+ FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcCharLeaf *));
+ FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcCharLeaf *));
+ fcs->leaves = leaves;
+ if (!fcs->numbers)
+ numbers = malloc (sizeof (FcChar16));
+ else
+ numbers = realloc (fcs->numbers, (fcs->num + 1) * sizeof (FcChar16));
+ if (!numbers)
+ return FcFalse;
+ if (fcs->num)
+ FcMemFree (FC_MEM_CHARSET, fcs->num * sizeof (FcChar16));
+ FcMemAlloc (FC_MEM_CHARSET, (fcs->num + 1) * sizeof (FcChar16));
+ fcs->numbers = numbers;
+
+ memmove (fcs->leaves + pos + 1, fcs->leaves + pos,
+ (fcs->num - pos) * sizeof (FcCharLeaf *));
+ memmove (fcs->numbers + pos + 1, fcs->numbers + pos,
+ (fcs->num - pos) * sizeof (FcChar16));
+ fcs->numbers[pos] = (FcChar16) ucs4;
+ fcs->leaves[pos] = leaf;
+ fcs->num++;
+ return FcTrue;
+}
+
+/*
+ * Locate the leaf containing the specified char, creating it
+ * if desired
+ */
+
+FcCharLeaf *
+FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4)
+{
+ int pos;
+ FcCharLeaf *leaf;
+
+ pos = FcCharSetFindLeafPos (fcs, ucs4);
+ if (pos >= 0)
+ return fcs->leaves[pos];
+
+ leaf = calloc (1, sizeof (FcCharLeaf));
+ if (!leaf)
+ return 0;
+
+ pos = -pos - 1;
+ if (!FcCharSetPutLeaf (fcs, ucs4, leaf, pos))
+ {
+ free (leaf);
+ return 0;
+ }
+ FcMemAlloc (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
+ return leaf;
+}
+
+static FcBool
+FcCharSetInsertLeaf (FcCharSet *fcs, FcChar32 ucs4, FcCharLeaf *leaf)
+{
+ int pos;
+
+ pos = FcCharSetFindLeafPos (fcs, ucs4);
+ if (pos >= 0)
+ {
+ FcMemFree (FC_MEM_CHARLEAF, sizeof (FcCharLeaf));
+ free (fcs->leaves[pos]);
+ fcs->leaves[pos] = leaf;
+ return FcTrue;
+ }
+ pos = -pos - 1;
+ return FcCharSetPutLeaf (fcs, ucs4, leaf, pos);
+}
+
+FcBool
+FcCharSetAddChar (FcCharSet *fcs, FcChar32 ucs4)
+{
+ FcCharLeaf *leaf;
+ FcChar32 *b;
+
+ if (fcs->ref == FC_REF_CONSTANT)
+ return FcFalse;
+ leaf = FcCharSetFindLeafCreate (fcs, ucs4);
+ if (!leaf)
+ return FcFalse;
+ b = &leaf->map[(ucs4 & 0xff) >> 5];
+ *b |= (1 << (ucs4 & 0x1f));
+ return FcTrue;
+}
+
+/*
+ * An iterator for the leaves of a charset
+ */
+
+typedef struct _fcCharSetIter {
+ FcCharLeaf *leaf;
+ FcChar32 ucs4;
+ int pos;
+} FcCharSetIter;
+
+/*
+ * Set iter->leaf to the leaf containing iter->ucs4 or higher
+ */
+
+static void
+FcCharSetIterSet (const FcCharSet *fcs, FcCharSetIter *iter)
+{
+ int pos = FcCharSetFindLeafPos (fcs, iter->ucs4);
+
+ if (pos < 0)
+ {
+ pos = -pos - 1;
+ if (pos == fcs->num)
+ {
+ iter->ucs4 = ~0;
+ iter->leaf = 0;
+ return;
+ }
+ iter->ucs4 = (FcChar32) fcs->numbers[pos] << 8;
+ }
+ iter->leaf = fcs->leaves[pos];
+ iter->pos = pos;
+#ifdef CHATTY
+ printf ("set %08x: %08x\n", iter->ucs4, (FcChar32) iter->leaf);
+#endif
+}
+
+static void
+FcCharSetIterNext (const FcCharSet *fcs, FcCharSetIter *iter)
+{
+ int pos = iter->pos + 1;
+ if (pos >= fcs->num)
+ {
+ iter->ucs4 = ~0;
+ iter->leaf = 0;
+ }
+ else
+ {
+ iter->ucs4 = (FcChar32) fcs->numbers[pos] << 8;
+ iter->leaf = fcs->leaves[pos];
+ iter->pos = pos;
+ }
+}
+
+#ifdef CHATTY
+static void
+FcCharSetDump (const FcCharSet *fcs)
+{
+ int pos;
+
+ printf ("fcs %08x:\n", (FcChar32) fcs);
+ for (pos = 0; pos < fcs->num; pos++)
+ {
+ FcCharLeaf *leaf = fcs->leaves[pos];
+ FcChar32 ucs4 = (FcChar32) fcs->numbers[pos] << 8;
+
+ printf (" %08x: %08x\n", ucs4, (FcChar32) leaf);
+ }
+}
+#endif
+
+static void
+FcCharSetIterStart (const FcCharSet *fcs, FcCharSetIter *iter)
+{
+#ifdef CHATTY
+ FcCharSetDump (fcs);
+#endif
+ iter->ucs4 = 0;
+ FcCharSetIterSet (fcs, iter);
+}
+
+FcCharSet *
+FcCharSetCopy (FcCharSet *src)
+{
+ if (src->ref != FC_REF_CONSTANT)
+ src->ref++;
+ return src;
+}
+
+FcBool
+FcCharSetEqual (const FcCharSet *a, const FcCharSet *b)
+{
+ FcCharSetIter ai, bi;
+ int i;
+
+ if (a == b)
+ return FcTrue;
+ for (FcCharSetIterStart (a, &ai), FcCharSetIterStart (b, &bi);
+ ai.leaf && bi.leaf;
+ FcCharSetIterNext (a, &ai), FcCharSetIterNext (b, &bi))
+ {
+ if (ai.ucs4 != bi.ucs4)
+ return FcFalse;
+ for (i = 0; i < 256/32; i++)
+ if (ai.leaf->map[i] != bi.leaf->map[i])
+ return FcFalse;
+ }
+ return ai.leaf == bi.leaf;
+}
+
+static FcBool
+FcCharSetAddLeaf (FcCharSet *fcs,
+ FcChar32 ucs4,
+ FcCharLeaf *leaf)
+{
+ FcCharLeaf *new = FcCharSetFindLeafCreate (fcs, ucs4);
+ if (!new)
+ return FcFalse;
+ *new = *leaf;
+ return FcTrue;
+}
+
+static FcCharSet *
+FcCharSetOperate (const FcCharSet *a,
+ const FcCharSet *b,
+ FcBool (*overlap) (FcCharLeaf *result,
+ const FcCharLeaf *al,
+ const FcCharLeaf *bl),
+ FcBool aonly,
+ FcBool bonly)
+{
+ FcCharSet *fcs;
+ FcCharSetIter ai, bi;
+
+ fcs = FcCharSetCreate ();
+ if (!fcs)
+ goto bail0;
+ FcCharSetIterStart (a, &ai);
+ FcCharSetIterStart (b, &bi);
+ while ((ai.leaf || (bonly && bi.leaf)) && (bi.leaf || (aonly && ai.leaf)))
+ {
+ if (ai.ucs4 < bi.ucs4)
+ {
+ if (aonly)
+ {
+ if (!FcCharSetAddLeaf (fcs, ai.ucs4, ai.leaf))
+ goto bail1;
+ FcCharSetIterNext (a, &ai);
+ }
+ else
+ {
+ ai.ucs4 = bi.ucs4;
+ FcCharSetIterSet (a, &ai);
+ }
+ }
+ else if (bi.ucs4 < ai.ucs4 )
+ {
+ if (bonly)
+ {
+ if (!FcCharSetAddLeaf (fcs, bi.ucs4, bi.leaf))
+ goto bail1;
+ FcCharSetIterNext (b, &bi);
+ }
+ else
+ {
+ bi.ucs4 = ai.ucs4;
+ FcCharSetIterSet (b, &bi);
+ }
+ }
+ else
+ {
+ FcCharLeaf leaf;
+
+ if ((*overlap) (&leaf, ai.leaf, bi.leaf))
+ {
+ if (!FcCharSetAddLeaf (fcs, ai.ucs4, &leaf))
+ goto bail1;
+ }
+ FcCharSetIterNext (a, &ai);
+ FcCharSetIterNext (b, &bi);
+ }
+ }
+ return fcs;
+bail1:
+ FcCharSetDestroy (fcs);
+bail0:
+ return 0;
+}
+
+static FcBool
+FcCharSetIntersectLeaf (FcCharLeaf *result,
+ const FcCharLeaf *al,
+ const FcCharLeaf *bl)
+{
+ int i;
+ FcBool nonempty = FcFalse;
+
+ for (i = 0; i < 256/32; i++)
+ if ((result->map[i] = al->map[i] & bl->map[i]))
+ nonempty = FcTrue;
+ return nonempty;
+}
+
+FcCharSet *
+FcCharSetIntersect (const FcCharSet *a, const FcCharSet *b)
+{
+ return FcCharSetOperate (a, b, FcCharSetIntersectLeaf, FcFalse, FcFalse);
+}
+
+static FcBool
+FcCharSetUnionLeaf (FcCharLeaf *result,
+ const FcCharLeaf *al,
+ const FcCharLeaf *bl)
+{
+ int i;
+
+ for (i = 0; i < 256/32; i++)
+ result->map[i] = al->map[i] | bl->map[i];
+ return FcTrue;
+}
+
+FcCharSet *
+FcCharSetUnion (const FcCharSet *a, const FcCharSet *b)
+{
+ return FcCharSetOperate (a, b, FcCharSetUnionLeaf, FcTrue, FcTrue);
+}
+
+static FcBool
+FcCharSetSubtractLeaf (FcCharLeaf *result,
+ const FcCharLeaf *al,
+ const FcCharLeaf *bl)
+{
+ int i;
+ FcBool nonempty = FcFalse;
+
+ for (i = 0; i < 256/32; i++)
+ if ((result->map[i] = al->map[i] & ~bl->map[i]))
+ nonempty = FcTrue;
+ return nonempty;
+}
+
+FcCharSet *
+FcCharSetSubtract (const FcCharSet *a, const FcCharSet *b)
+{
+ return FcCharSetOperate (a, b, FcCharSetSubtractLeaf, FcTrue, FcFalse);
+}
+
+FcBool
+FcCharSetHasChar (const FcCharSet *fcs, FcChar32 ucs4)
+{
+ FcCharLeaf *leaf = FcCharSetFindLeaf (fcs, ucs4);
+ if (!leaf)
+ return FcFalse;
+ return (leaf->map[(ucs4 & 0xff) >> 5] & (1 << (ucs4 & 0x1f))) != 0;
+}
+
+static FcChar32
+FcCharSetPopCount (FcChar32 c1)
+{
+ /* hackmem 169 */
+ FcChar32 c2 = (c1 >> 1) & 033333333333;
+ c2 = c1 - c2 - ((c2 >> 1) & 033333333333);
+ return (((c2 + (c2 >> 3)) & 030707070707) % 077);
+}
+
+FcChar32
+FcCharSetIntersectCount (const FcCharSet *a, const FcCharSet *b)
+{
+ FcCharSetIter ai, bi;
+ FcChar32 count = 0;
+
+ FcCharSetIterStart (a, &ai);
+ FcCharSetIterStart (b, &bi);
+ while (ai.leaf && bi.leaf)
+ {
+ if (ai.ucs4 == bi.ucs4)
+ {
+ FcChar32 *am = ai.leaf->map;
+ FcChar32 *bm = bi.leaf->map;
+ int i = 256/32;
+ while (i--)
+ count += FcCharSetPopCount (*am++ & *bm++);
+ FcCharSetIterNext (a, &ai);
+ }
+ else if (ai.ucs4 < bi.ucs4)
+ {
+ ai.ucs4 = bi.ucs4;
+ FcCharSetIterSet (a, &ai);
+ }
+ if (bi.ucs4 < ai.ucs4)
+ {
+ bi.ucs4 = ai.ucs4;
+ FcCharSetIterSet (b, &bi);
+ }
+ }
+ return count;
+}
+
+FcChar32
+FcCharSetCount (const FcCharSet *a)
+{
+ FcCharSetIter ai;
+ FcChar32 count = 0;
+
+ for (FcCharSetIterStart (a, &ai); ai.leaf; FcCharSetIterNext (a, &ai))
+ {
+ int i = 256/32;
+ FcChar32 *am = ai.leaf->map;
+
+ while (i--)
+ count += FcCharSetPopCount (*am++);
+ }
+ return count;
+}
+
+FcChar32
+FcCharSetSubtractCount (const FcCharSet *a, const FcCharSet *b)
+{
+ FcCharSetIter ai, bi;
+ FcChar32 count = 0;
+
+ FcCharSetIterStart (a, &ai);
+ FcCharSetIterStart (b, &bi);
+ while (ai.leaf)
+ {
+ if (ai.ucs4 <= bi.ucs4)
+ {
+ FcChar32 *am = ai.leaf->map;
+ int i = 256/32;
+ if (ai.ucs4 == bi.ucs4)
+ {
+ FcChar32 *bm = bi.leaf->map;;
+ while (i--)
+ count += FcCharSetPopCount (*am++ & ~*bm++);
+ }
+ else
+ {
+ while (i--)
+ count += FcCharSetPopCount (*am++);
+ }
+ FcCharSetIterNext (a, &ai);
+ }
+ else if (bi.leaf)
+ {
+ bi.ucs4 = ai.ucs4;
+ FcCharSetIterSet (b, &bi);
+ }
+ }
+ return count;
+}
+
+/*
+ * return FcTrue iff a is a subset of b
+ */
+FcBool
+FcCharSetIsSubset (const FcCharSet *a, const FcCharSet *b)
+{
+ int ai, bi;
+ FcChar16 an, bn;
+
+ if (a == b) return FcTrue;
+ bi = 0;
+ ai = 0;
+ while (ai < a->num && bi < b->num)
+ {
+ an = a->numbers[ai];
+ bn = b->numbers[bi];
+ /*
+ * Check matching pages
+ */
+ if (an == bn)
+ {
+ FcChar32 *am = a->leaves[ai]->map;
+ FcChar32 *bm = b->leaves[bi]->map;
+
+ if (am != bm)
+ {
+ int i = 256/32;
+ /*
+ * Does am have any bits not in bm?
+ */
+ while (i--)
+ if (*am++ & ~*bm++)
+ return FcFalse;
+ }
+ ai++;
+ bi++;
+ }
+ /*
+ * Does a have any pages not in b?
+ */
+ else if (an < bn)
+ return FcFalse;
+ else
+ {
+ int low = bi + 1;
+ int high = b->num - 1;
+
+ /*
+ * Search for page 'an' in 'b'
+ */
+ while (low <= high)
+ {
+ int mid = (low + high) >> 1;
+ bn = b->numbers[mid];
+ if (bn == an)
+ {
+ high = mid;
+ break;
+ }
+ if (bn < an)
+ low = mid + 1;
+ else
+ high = mid - 1;
+ }
+ bi = high;
+ while (bi < b->num && b->numbers[bi] < an)
+ bi++;
+ }
+ }
+ /*
+ * did we look at every page?
+ */
+ return ai >= a->num;
+}
+
+/*
+ * These two functions efficiently walk the entire charmap for
+ * other software (like pango) that want their own copy
+ */
+
+FcChar32
+FcCharSetNextPage (const FcCharSet *a,
+ FcChar32 map[FC_CHARSET_MAP_SIZE],
+ FcChar32 *next)
+{
+ FcCharSetIter ai;
+ FcChar32 page;
+
+ ai.ucs4 = *next;
+ FcCharSetIterSet (a, &ai);
+ if (!ai.leaf)
+ return FC_CHARSET_DONE;
+
+ /*
+ * Save current information
+ */
+ page = ai.ucs4;
+ memcpy (map, ai.leaf->map, sizeof (ai.leaf->map));
+ /*
+ * Step to next page
+ */
+ FcCharSetIterNext (a, &ai);
+ *next = ai.ucs4;
+
+ return page;
+}
+
+FcChar32
+FcCharSetFirstPage (const FcCharSet *a,
+ FcChar32 map[FC_CHARSET_MAP_SIZE],
+ FcChar32 *next)
+{
+ *next = 0;
+ return FcCharSetNextPage (a, map, next);
+}
+
+/*
+ * old coverage API, rather hard to use correctly
+ */
+FcChar32
+FcCharSetCoverage (const FcCharSet *a, FcChar32 page, FcChar32 *result);
+
+FcChar32
+FcCharSetCoverage (const FcCharSet *a, FcChar32 page, FcChar32 *result)
+{
+ FcCharSetIter ai;
+
+ ai.ucs4 = page;
+ FcCharSetIterSet (a, &ai);
+ if (!ai.leaf)
+ {
+ memset (result, '\0', 256 / 8);
+ page = 0;
+ }
+ else
+ {
+ memcpy (result, ai.leaf->map, sizeof (ai.leaf->map));
+ FcCharSetIterNext (a, &ai);
+ page = ai.ucs4;
+ }
+ return page;
+}
+
+/*
+ * ASCII representation of charsets.
+ *
+ * Each leaf is represented as 9 32-bit values, the code of the first character followed
+ * by 8 32 bit values for the leaf itself. Each value is encoded as 5 ASCII characters,
+ * only 85 different values are used to avoid control characters as well as the other
+ * characters used to encode font names. 85**5 > 2^32 so things work out, but
+ * it's not exactly human readable output. As a special case, 0 is encoded as a space
+ */
+
+static const unsigned char charToValue[256] = {
+ /* "" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\b" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\020" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\030" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* " " */ 0xff, 0x00, 0xff, 0x01, 0x02, 0x03, 0x04, 0xff,
+ /* "(" */ 0x05, 0x06, 0x07, 0x08, 0xff, 0xff, 0x09, 0x0a,
+ /* "0" */ 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+ /* "8" */ 0x13, 0x14, 0xff, 0x15, 0x16, 0xff, 0x17, 0x18,
+ /* "@" */ 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+ /* "H" */ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ /* "P" */ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+ /* "X" */ 0x31, 0x32, 0x33, 0x34, 0xff, 0x35, 0x36, 0xff,
+ /* "`" */ 0xff, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
+ /* "h" */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
+ /* "p" */ 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d,
+ /* "x" */ 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0xff,
+ /* "\200" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\210" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\220" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\230" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\240" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\250" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\260" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\270" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\300" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\310" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\320" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\330" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\340" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\350" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\360" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ /* "\370" */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+static const FcChar8 valueToChar[0x55] = {
+ /* 0x00 */ '!', '#', '$', '%', '&', '(', ')', '*',
+ /* 0x08 */ '+', '.', '/', '0', '1', '2', '3', '4',
+ /* 0x10 */ '5', '6', '7', '8', '9', ';', '<', '>',
+ /* 0x18 */ '?', '@', 'A', 'B', 'C', 'D', 'E', 'F',
+ /* 0x20 */ 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+ /* 0x28 */ 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+ /* 0x30 */ 'W', 'X', 'Y', 'Z', '[', ']', '^', 'a',
+ /* 0x38 */ 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
+ /* 0x40 */ 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
+ /* 0x48 */ 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
+ /* 0x50 */ 'z', '{', '|', '}', '~',
+};
+
+static FcChar8 *
+FcCharSetParseValue (FcChar8 *string, FcChar32 *value)
+{
+ int i;
+ FcChar32 v;
+ FcChar32 c;
+
+ if (*string == ' ')
+ {
+ v = 0;
+ string++;
+ }
+ else
+ {
+ v = 0;
+ for (i = 0; i < 5; i++)
+ {
+ if (!(c = (FcChar32) (unsigned char) *string++))
+ return 0;
+ c = charToValue[c];
+ if (c == 0xff)
+ return 0;
+ v = v * 85 + c;
+ }
+ }
+ *value = v;
+ return string;
+}
+
+static FcBool
+FcCharSetUnparseValue (FcStrBuf *buf, FcChar32 value)
+{
+ int i;
+ if (value == 0)
+ {
+ return FcStrBufChar (buf, ' ');
+ }
+ else
+ {
+ FcChar8 string[6];
+ FcChar8 *s = string + 5;
+ string[5] = '\0';
+ for (i = 0; i < 5; i++)
+ {
+ *--s = valueToChar[value % 85];
+ value /= 85;
+ }
+ for (i = 0; i < 5; i++)
+ if (!FcStrBufChar (buf, *s++))
+ return FcFalse;
+ }
+ return FcTrue;
+}
+
+typedef struct _FcCharLeafEnt FcCharLeafEnt;
+
+struct _FcCharLeafEnt {
+ FcCharLeafEnt *next;
+ FcChar32 hash;
+ FcCharLeaf leaf;
+};
+
+#define FC_CHAR_LEAF_BLOCK (4096 / sizeof (FcCharLeafEnt))
+static FcCharLeafEnt **FcCharLeafBlocks;
+static int FcCharLeafBlockCount;
+
+static FcCharLeafEnt *
+FcCharLeafEntCreate (void)
+{
+ static FcCharLeafEnt *block;
+ static int remain;
+
+ if (!remain)
+ {
+ FcCharLeafEnt **newBlocks;
+
+ FcCharLeafBlockCount++;
+ newBlocks = realloc (FcCharLeafBlocks, FcCharLeafBlockCount * sizeof (FcCharLeafEnt *));
+ if (!newBlocks)
+ return 0;
+ FcCharLeafBlocks = newBlocks;
+ block = FcCharLeafBlocks[FcCharLeafBlockCount-1] = malloc (FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
+ if (!block)
+ return 0;
+ FcMemAlloc (FC_MEM_CHARLEAF, FC_CHAR_LEAF_BLOCK * sizeof (FcCharLeafEnt));
+ remain = FC_CHAR_LEAF_BLOCK;
+ }
+ remain--;
+ return block++;
+}
+
+#define FC_CHAR_LEAF_HASH_SIZE 257
+
+static FcChar32
+FcCharLeafHash (FcCharLeaf *leaf)
+{
+ FcChar32 hash = 0;
+ int i;
+
+ for (i = 0; i < 256/32; i++)
+ hash = ((hash << 1) | (hash >> 31)) ^ leaf->map[i];
+ return hash;
+}
+
+static int FcCharLeafTotal;
+static int FcCharLeafUsed;
+
+static FcCharLeafEnt *FcCharLeafHashTable[FC_CHAR_LEAF_HASH_SIZE];
+
+static FcCharLeaf *
+FcCharSetFreezeLeaf (FcCharLeaf *leaf)
+{
+ FcChar32 hash = FcCharLeafHash (leaf);
+ FcCharLeafEnt **bucket = &FcCharLeafHashTable[hash % FC_CHAR_LEAF_HASH_SIZE];
+ FcCharLeafEnt *ent;
+
+ FcCharLeafTotal++;
+ for (ent = *bucket; ent; ent = ent->next)
+ {
+ if (ent->hash == hash && !memcmp (&ent->leaf, leaf, sizeof (FcCharLeaf)))
+ return &ent->leaf;
+ }
+
+ ent = FcCharLeafEntCreate();
+ if (!ent)
+ return 0;
+ FcCharLeafUsed++;
+ ent->leaf = *leaf;
+ ent->hash = hash;
+ ent->next = *bucket;
+ *bucket = ent;
+ return &ent->leaf;
+}
+
+static void
+FcCharSetThawAllLeaf (void)
+{
+ int i;
+
+ for (i = 0; i < FC_CHAR_LEAF_HASH_SIZE; i++)
+ FcCharLeafHashTable[i] = 0;
+
+ FcCharLeafTotal = 0;
+ FcCharLeafUsed = 0;
+
+ for (i = 0; i < FcCharLeafBlockCount; i++)
+ free (FcCharLeafBlocks[i]);
+
+ free (FcCharLeafBlocks);
+ FcCharLeafBlocks = 0;
+ FcCharLeafBlockCount = 0;
+}
+
+typedef struct _FcCharSetEnt FcCharSetEnt;
+
+struct _FcCharSetEnt {
+ FcCharSetEnt *next;
+ FcChar32 hash;
+ FcCharSet set;
+};
+
+#define FC_CHAR_SET_HASH_SIZE 67
+
+static FcChar32
+FcCharSetHash (FcCharSet *fcs)
+{
+ FcChar32 hash = 0;
+ FcChar32 *p;
+ int i;
+
+ /* hash in leaves */
+ p = (FcChar32 *) fcs->leaves;
+ for (i = 0; i < fcs->num * sizeof (FcCharLeaf *) / sizeof (FcChar32); i++)
+ hash = ((hash << 1) | (hash >> 31)) ^ *p++;
+ /* hash in numbers */
+ for (i = 0; i < fcs->num; i++)
+ hash = ((hash << 1) | (hash >> 31)) ^ fcs->numbers[i];
+ return hash;
+}
+
+static int FcCharSetTotal;
+static int FcCharSetUsed;
+static int FcCharSetTotalEnts, FcCharSetUsedEnts;
+
+static FcCharSetEnt *FcCharSetHashTable[FC_CHAR_SET_HASH_SIZE];
+
+static FcCharSet *
+FcCharSetFreezeBase (FcCharSet *fcs)
+{
+ FcChar32 hash = FcCharSetHash (fcs);
+ FcCharSetEnt **bucket = &FcCharSetHashTable[hash % FC_CHAR_SET_HASH_SIZE];
+ FcCharSetEnt *ent;
+ int size;
+
+ FcCharSetTotal++;
+ FcCharSetTotalEnts += fcs->num;
+ for (ent = *bucket; ent; ent = ent->next)
+ {
+ if (ent->hash == hash &&
+ ent->set.num == fcs->num &&
+ !memcmp (ent->set.leaves, fcs->leaves,
+ fcs->num * sizeof (FcCharLeaf *)) &&
+ !memcmp (ent->set.numbers, fcs->numbers,
+ fcs->num * sizeof (FcChar16)))
+ {
+ return &ent->set;
+ }
+ }
+
+ size = (sizeof (FcCharSetEnt) +
+ fcs->num * sizeof (FcCharLeaf *) +
+ fcs->num * sizeof (FcChar16));
+ ent = malloc (size);
+ if (!ent)
+ return 0;
+ FcMemAlloc (FC_MEM_CHARSET, size);
+ FcCharSetUsed++;
+ FcCharSetUsedEnts += fcs->num;
+
+ ent->set.ref = FC_REF_CONSTANT;
+ ent->set.num = fcs->num;
+ if (fcs->num)
+ {
+ ent->set.leaves = (FcCharLeaf **) (ent + 1);
+ ent->set.numbers = (FcChar16 *) (ent->set.leaves + fcs->num);
+ memcpy (ent->set.leaves, fcs->leaves, fcs->num * sizeof (FcCharLeaf *));
+ memcpy (ent->set.numbers, fcs->numbers, fcs->num * sizeof (FcChar16));
+ }
+ else
+ {
+ ent->set.leaves = 0;
+ ent->set.numbers = 0;
+ }
+
+ ent->hash = hash;
+ ent->next = *bucket;
+ *bucket = ent;
+ return &ent->set;
+}
+
+void
+FcCharSetThawAll (void)
+{
+ int i;
+ FcCharSetEnt *ent, *next;
+
+ for (i = 0; i < FC_CHAR_SET_HASH_SIZE; i++)
+ {
+ for (ent = FcCharSetHashTable[i]; ent; ent = next)
+ {
+ next = ent->next;
+ free (ent);
+ }
+ FcCharSetHashTable[i] = 0;
+ }
+
+ FcCharSetTotal = 0;
+ FcCharSetTotalEnts = 0;
+ FcCharSetUsed = 0;
+ FcCharSetUsedEnts = 0;
+
+ FcCharSetThawAllLeaf ();
+}
+
+FcCharSet *
+FcCharSetFreeze (FcCharSet *fcs)
+{
+ FcCharSet *b;
+ FcCharSet *n = 0;
+ FcCharLeaf *l;
+ int i;
+
+ b = FcCharSetCreate ();
+ if (!b)
+ goto bail0;
+ for (i = 0; i < fcs->num; i++)
+ {
+ l = FcCharSetFreezeLeaf (fcs->leaves[i]);
+ if (!l)
+ goto bail1;
+ if (!FcCharSetInsertLeaf (b, fcs->numbers[i] << 8, l))
+ goto bail1;
+ }
+ n = FcCharSetFreezeBase (b);
+bail1:
+ if (b->leaves)
+ {
+ FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcCharLeaf *));
+ free (b->leaves);
+ }
+ if (b->numbers)
+ {
+ FcMemFree (FC_MEM_CHARSET, b->num * sizeof (FcChar16));
+ free (b->numbers);
+ }
+ FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
+ free (b);
+bail0:
+ return n;
+}
+
+FcCharSet *
+FcNameParseCharSet (FcChar8 *string)
+{
+ FcCharSet *c, *n = 0;
+ FcChar32 ucs4;
+ FcCharLeaf *leaf;
+ FcCharLeaf temp;
+ FcChar32 bits;
+ int i;
+
+ c = FcCharSetCreate ();
+ if (!c)
+ goto bail0;
+ while (*string)
+ {
+ string = FcCharSetParseValue (string, &ucs4);
+ if (!string)
+ goto bail1;
+ bits = 0;
+ for (i = 0; i < 256/32; i++)
+ {
+ string = FcCharSetParseValue (string, &temp.map[i]);
+ if (!string)
+ goto bail1;
+ bits |= temp.map[i];
+ }
+ if (bits)
+ {
+ leaf = FcCharSetFreezeLeaf (&temp);
+ if (!leaf)
+ goto bail1;
+ if (!FcCharSetInsertLeaf (c, ucs4, leaf))
+ goto bail1;
+ }
+ }
+#ifdef CHATTY
+ printf (" %8s %8s %8s %8s\n", "total", "totalmem", "new", "newmem");
+ printf ("Leaves: %8d %8d %8d %8d\n",
+ FcCharLeafTotal, sizeof (FcCharLeaf) * FcCharLeafTotal,
+ FcCharLeafUsed, sizeof (FcCharLeaf) * FcCharLeafUsed);
+ printf ("Charsets: %8d %8d %8d %8d\n",
+ FcCharSetTotal, sizeof (FcCharSet) * FcCharSetTotal,
+ FcCharSetUsed, sizeof (FcCharSet) * FcCharSetUsed);
+ printf ("Tables: %8d %8d %8d %8d\n",
+ FcCharSetTotalEnts, FcCharSetTotalEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)),
+ FcCharSetUsedEnts, FcCharSetUsedEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)));
+ printf ("Total: %8s %8d %8s %8d\n",
+ "",
+ sizeof (FcCharLeaf) * FcCharLeafTotal +
+ sizeof (FcCharSet) * FcCharSetTotal +
+ FcCharSetTotalEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)),
+ "",
+ sizeof (FcCharLeaf) * FcCharLeafUsed +
+ sizeof (FcCharSet) * FcCharSetUsed +
+ FcCharSetUsedEnts * (sizeof (FcCharLeaf *) + sizeof (FcChar16)));
+#endif
+ n = FcCharSetFreezeBase (c);
+bail1:
+ if (c->leaves)
+ {
+ FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcCharLeaf *));
+ free (c->leaves);
+ }
+ if (c->numbers)
+ {
+ FcMemFree (FC_MEM_CHARSET, c->num * sizeof (FcChar16));
+ free (c->numbers);
+ }
+ FcMemFree (FC_MEM_CHARSET, sizeof (FcCharSet));
+ free (c);
+bail0:
+ return n;
+}
+
+FcBool
+FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c)
+{
+ FcCharSetIter ci;
+ int i;
+#ifdef CHECK
+ int len = buf->len;
+#endif
+
+ for (FcCharSetIterStart (c, &ci);
+ ci.leaf;
+ FcCharSetIterNext (c, &ci))
+ {
+ if (!FcCharSetUnparseValue (buf, ci.ucs4))
+ return FcFalse;
+ for (i = 0; i < 256/32; i++)
+ if (!FcCharSetUnparseValue (buf, ci.leaf->map[i]))
+ return FcFalse;
+ }
+#ifdef CHECK
+ {
+ FcCharSet *check;
+ FcChar32 missing;
+ FcCharSetIter ci, checki;
+
+ /* null terminate for parser */
+ FcStrBufChar (buf, '\0');
+ /* step back over null for life after test */
+ buf->len--;
+ check = FcNameParseCharSet (buf->buf + len);
+ FcCharSetIterStart (c, &ci);
+ FcCharSetIterStart (check, &checki);
+ while (ci.leaf || checki.leaf)
+ {
+ if (ci.ucs4 < checki.ucs4)
+ {
+ printf ("Missing leaf node at 0x%x\n", ci.ucs4);
+ FcCharSetIterNext (c, &ci);
+ }
+ else if (checki.ucs4 < ci.ucs4)
+ {
+ printf ("Extra leaf node at 0x%x\n", checki.ucs4);
+ FcCharSetIterNext (check, &checki);
+ }
+ else
+ {
+ int i = 256/32;
+ FcChar32 *cm = ci.leaf->map;
+ FcChar32 *checkm = checki.leaf->map;
+
+ for (i = 0; i < 256; i += 32)
+ {
+ if (*cm != *checkm)
+ printf ("Mismatching sets at 0x%08x: 0x%08x != 0x%08x\n",
+ ci.ucs4 + i, *cm, *checkm);
+ cm++;
+ checkm++;
+ }
+ FcCharSetIterNext (c, &ci);
+ FcCharSetIterNext (check, &checki);
+ }
+ }
+ if ((missing = FcCharSetSubtractCount (c, check)))
+ printf ("%d missing in reparsed result\n", missing);
+ if ((missing = FcCharSetSubtractCount (check, c)))
+ printf ("%d extra in reparsed result\n", missing);
+ FcCharSetDestroy (check);
+ }
+#endif
+
+ return FcTrue;
+}
diff --git a/nx-X11/extras/fontconfig/src/fcdbg.c b/nx-X11/extras/fontconfig/src/fcdbg.c
new file mode 100644
index 000000000..cd72edad8
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcdbg.c
@@ -0,0 +1,363 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fcdbg.c,v 1.10 2002/08/22 18:53:22 keithp Exp $
+ *
+ * Copyright © 2000 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdio.h>
+#include <stdlib.h>
+#include "fcint.h"
+
+void
+FcValuePrint (const FcValue v)
+{
+ switch (v.type) {
+ case FcTypeVoid:
+ printf (" <void>");
+ break;
+ case FcTypeInteger:
+ printf (" %d(i)", v.u.i);
+ break;
+ case FcTypeDouble:
+ printf (" %g(f)", v.u.d);
+ break;
+ case FcTypeString:
+ printf (" \"%s\"", v.u.s);
+ break;
+ case FcTypeBool:
+ printf (" %s", v.u.b ? "FcTrue" : "FcFalse");
+ break;
+ case FcTypeMatrix:
+ printf (" (%f %f; %f %f)", v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
+ break;
+ case FcTypeCharSet: /* XXX */
+ printf (" set");
+ break;
+ case FcTypeLangSet:
+ printf (" ");
+ FcLangSetPrint (v.u.l);
+ break;
+ case FcTypeFTFace:
+ printf (" face");
+ break;
+ }
+}
+
+void
+FcValueListPrint (const FcValueList *l)
+{
+ for (; l; l = l->next)
+ {
+ FcValuePrint (l->value);
+ switch (l->binding) {
+ case FcValueBindingWeak:
+ printf ("(w)");
+ break;
+ case FcValueBindingStrong:
+ printf ("(s)");
+ break;
+ case FcValueBindingSame:
+ printf ("(=)");
+ break;
+ }
+ }
+}
+
+void
+FcLangSetPrint (const FcLangSet *ls)
+{
+ FcStrBuf buf;
+ FcChar8 init_buf[1024];
+
+ FcStrBufInit (&buf, init_buf, sizeof (init_buf));
+ if (FcNameUnparseLangSet (&buf, ls) && FcStrBufChar (&buf,'\0'))
+ printf ("%s", buf.buf);
+ else
+ printf ("langset (alloc error)");
+ FcStrBufDestroy (&buf);
+}
+
+void
+FcPatternPrint (const FcPattern *p)
+{
+ int i;
+ FcPatternElt *e;
+
+ if (!p)
+ {
+ printf ("Null pattern\n");
+ return;
+ }
+ printf ("Pattern %d of %d\n", p->num, p->size);
+ for (i = 0; i < p->num; i++)
+ {
+ e = &p->elts[i];
+ printf ("\t%s:", e->object);
+ FcValueListPrint (e->values);
+ printf ("\n");
+ }
+ printf ("\n");
+}
+
+void
+FcOpPrint (FcOp op)
+{
+ switch (op) {
+ case FcOpInteger: printf ("Integer"); break;
+ case FcOpDouble: printf ("Double"); break;
+ case FcOpString: printf ("String"); break;
+ case FcOpMatrix: printf ("Matrix"); break;
+ case FcOpBool: printf ("Bool"); break;
+ case FcOpCharSet: printf ("CharSet"); break;
+ case FcOpField: printf ("Field"); break;
+ case FcOpConst: printf ("Const"); break;
+ case FcOpAssign: printf ("Assign"); break;
+ case FcOpAssignReplace: printf ("AssignReplace"); break;
+ case FcOpPrepend: printf ("Prepend"); break;
+ case FcOpPrependFirst: printf ("PrependFirst"); break;
+ case FcOpAppend: printf ("Append"); break;
+ case FcOpAppendLast: printf ("AppendLast"); break;
+ case FcOpQuest: printf ("Quest"); break;
+ case FcOpOr: printf ("Or"); break;
+ case FcOpAnd: printf ("And"); break;
+ case FcOpEqual: printf ("Equal"); break;
+ case FcOpNotEqual: printf ("NotEqual"); break;
+ case FcOpLess: printf ("Less"); break;
+ case FcOpLessEqual: printf ("LessEqual"); break;
+ case FcOpMore: printf ("More"); break;
+ case FcOpMoreEqual: printf ("MoreEqual"); break;
+ case FcOpContains: printf ("Contains"); break;
+ case FcOpNotContains: printf ("NotContains"); break;
+ case FcOpPlus: printf ("Plus"); break;
+ case FcOpMinus: printf ("Minus"); break;
+ case FcOpTimes: printf ("Times"); break;
+ case FcOpDivide: printf ("Divide"); break;
+ case FcOpNot: printf ("Not"); break;
+ case FcOpNil: printf ("Nil"); break;
+ case FcOpComma: printf ("Comma"); break;
+ case FcOpFloor: printf ("Floor"); break;
+ case FcOpCeil: printf ("Ceil"); break;
+ case FcOpRound: printf ("Round"); break;
+ case FcOpTrunc: printf ("Trunc"); break;
+ case FcOpListing: printf ("Listing"); break;
+ case FcOpInvalid: printf ("Invalid"); break;
+ }
+}
+
+void
+FcExprPrint (const FcExpr *expr)
+{
+ if (!expr) printf ("none");
+ else switch (expr->op) {
+ case FcOpInteger: printf ("%d", expr->u.ival); break;
+ case FcOpDouble: printf ("%g", expr->u.dval); break;
+ case FcOpString: printf ("\"%s\"", expr->u.sval); break;
+ case FcOpMatrix: printf ("[%g %g %g %g]",
+ expr->u.mval->xx,
+ expr->u.mval->xy,
+ expr->u.mval->yx,
+ expr->u.mval->yy); break;
+ case FcOpBool: printf ("%s", expr->u.bval ? "true" : "false"); break;
+ case FcOpCharSet: printf ("charset\n"); break;
+ case FcOpNil: printf ("nil\n"); break;
+ case FcOpField: printf ("%s", expr->u.field); break;
+ case FcOpConst: printf ("%s", expr->u.constant); break;
+ case FcOpQuest:
+ FcExprPrint (expr->u.tree.left);
+ printf (" quest ");
+ FcExprPrint (expr->u.tree.right->u.tree.left);
+ printf (" colon ");
+ FcExprPrint (expr->u.tree.right->u.tree.right);
+ break;
+ case FcOpAssign:
+ case FcOpAssignReplace:
+ case FcOpPrependFirst:
+ case FcOpPrepend:
+ case FcOpAppend:
+ case FcOpAppendLast:
+ case FcOpOr:
+ case FcOpAnd:
+ case FcOpEqual:
+ case FcOpNotEqual:
+ case FcOpLess:
+ case FcOpLessEqual:
+ case FcOpMore:
+ case FcOpMoreEqual:
+ case FcOpContains:
+ case FcOpListing:
+ case FcOpNotContains:
+ case FcOpPlus:
+ case FcOpMinus:
+ case FcOpTimes:
+ case FcOpDivide:
+ case FcOpComma:
+ FcExprPrint (expr->u.tree.left);
+ printf (" ");
+ switch (expr->op) {
+ case FcOpAssign: printf ("Assign"); break;
+ case FcOpAssignReplace: printf ("AssignReplace"); break;
+ case FcOpPrependFirst: printf ("PrependFirst"); break;
+ case FcOpPrepend: printf ("Prepend"); break;
+ case FcOpAppend: printf ("Append"); break;
+ case FcOpAppendLast: printf ("AppendLast"); break;
+ case FcOpOr: printf ("Or"); break;
+ case FcOpAnd: printf ("And"); break;
+ case FcOpEqual: printf ("Equal"); break;
+ case FcOpNotEqual: printf ("NotEqual"); break;
+ case FcOpLess: printf ("Less"); break;
+ case FcOpLessEqual: printf ("LessEqual"); break;
+ case FcOpMore: printf ("More"); break;
+ case FcOpMoreEqual: printf ("MoreEqual"); break;
+ case FcOpContains: printf ("Contains"); break;
+ case FcOpListing: printf ("Listing"); break;
+ case FcOpNotContains: printf ("NotContains"); break;
+ case FcOpPlus: printf ("Plus"); break;
+ case FcOpMinus: printf ("Minus"); break;
+ case FcOpTimes: printf ("Times"); break;
+ case FcOpDivide: printf ("Divide"); break;
+ case FcOpComma: printf ("Comma"); break;
+ default: break;
+ }
+ printf (" ");
+ FcExprPrint (expr->u.tree.right);
+ break;
+ case FcOpNot:
+ printf ("Not ");
+ FcExprPrint (expr->u.tree.left);
+ break;
+ case FcOpFloor:
+ printf ("Floor ");
+ FcExprPrint (expr->u.tree.left);
+ break;
+ case FcOpCeil:
+ printf ("Ceil ");
+ FcExprPrint (expr->u.tree.left);
+ break;
+ case FcOpRound:
+ printf ("Round ");
+ FcExprPrint (expr->u.tree.left);
+ break;
+ case FcOpTrunc:
+ printf ("Trunc ");
+ FcExprPrint (expr->u.tree.left);
+ break;
+ case FcOpInvalid: printf ("Invalid"); break;
+ }
+}
+
+void
+FcTestPrint (const FcTest *test)
+{
+ switch (test->kind) {
+ case FcMatchPattern:
+ printf ("pattern ");
+ break;
+ case FcMatchFont:
+ printf ("font ");
+ break;
+ }
+ switch (test->qual) {
+ case FcQualAny:
+ printf ("any ");
+ break;
+ case FcQualAll:
+ printf ("all ");
+ break;
+ case FcQualFirst:
+ printf ("first ");
+ break;
+ case FcQualNotFirst:
+ printf ("not_first ");
+ break;
+ }
+ printf ("%s ", test->field);
+ FcOpPrint (test->op);
+ printf (" ");
+ FcExprPrint (test->expr);
+ printf ("\n");
+}
+
+void
+FcEditPrint (const FcEdit *edit)
+{
+ printf ("Edit %s ", edit->field);
+ FcOpPrint (edit->op);
+ printf (" ");
+ FcExprPrint (edit->expr);
+}
+
+void
+FcSubstPrint (const FcSubst *subst)
+{
+ FcEdit *e;
+ FcTest *t;
+
+ printf ("match\n");
+ for (t = subst->test; t; t = t->next)
+ {
+ printf ("\t");
+ FcTestPrint (t);
+ }
+ printf ("edit\n");
+ for (e = subst->edit; e; e = e->next)
+ {
+ printf ("\t");
+ FcEditPrint (e);
+ printf (";\n");
+ }
+ printf ("\n");
+}
+
+void
+FcFontSetPrint (const FcFontSet *s)
+{
+ int i;
+
+ printf ("FontSet %d of %d\n", s->nfont, s->sfont);
+ for (i = 0; i < s->nfont; i++)
+ {
+ printf ("Font %d ", i);
+ FcPatternPrint (s->fonts[i]);
+ }
+}
+
+int
+FcDebug (void)
+{
+ static int initialized;
+ static int debug;
+
+ if (!initialized)
+ {
+ char *e;
+
+ initialized = 1;
+ e = getenv ("FC_DEBUG");
+ if (e)
+ {
+ printf ("FC_DEBUG=%s\n", e);
+ debug = atoi (e);
+ if (debug < 0)
+ debug = 0;
+ }
+ }
+ return debug;
+}
diff --git a/nx-X11/extras/fontconfig/src/fcdefault.c b/nx-X11/extras/fontconfig/src/fcdefault.c
new file mode 100644
index 000000000..0e84311fa
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcdefault.c
@@ -0,0 +1,152 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fcdefault.c,v 1.2 2002/07/09 22:08:14 keithp Exp $
+ *
+ * Copyright © 2001 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <locale.h>
+
+static struct {
+ char *field;
+ FcBool value;
+} FcBoolDefaults[] = {
+ { FC_HINTING, FcTrue }, /* !FT_LOAD_NO_HINTING */
+ { FC_VERTICAL_LAYOUT, FcFalse }, /* FC_LOAD_VERTICAL_LAYOUT */
+ { FC_AUTOHINT, FcFalse }, /* FC_LOAD_FORCE_AUTOHINT */
+ { FC_GLOBAL_ADVANCE, FcTrue }, /* !FC_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH */
+};
+
+#define NUM_FC_BOOL_DEFAULTS (sizeof FcBoolDefaults / sizeof FcBoolDefaults[0])
+
+void
+FcDefaultSubstitute (FcPattern *pattern)
+{
+ FcValue v;
+ int i;
+
+ if (FcPatternGet (pattern, FC_STYLE, 0, &v) == FcResultNoMatch)
+ {
+ if (FcPatternGet (pattern, FC_WEIGHT, 0, &v) == FcResultNoMatch )
+ {
+ FcPatternAddInteger (pattern, FC_WEIGHT, FC_WEIGHT_MEDIUM);
+ }
+ if (FcPatternGet (pattern, FC_SLANT, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddInteger (pattern, FC_SLANT, FC_SLANT_ROMAN);
+ }
+ }
+
+ if (FcPatternGet (pattern, FC_WIDTH, 0, &v) == FcResultNoMatch)
+ FcPatternAddInteger (pattern, FC_WIDTH, FC_WIDTH_NORMAL);
+
+ for (i = 0; i < NUM_FC_BOOL_DEFAULTS; i++)
+ if (FcPatternGet (pattern, FcBoolDefaults[i].field, 0, &v) == FcResultNoMatch)
+ FcPatternAddBool (pattern, FcBoolDefaults[i].field, FcBoolDefaults[i].value);
+
+ if (FcPatternGet (pattern, FC_PIXEL_SIZE, 0, &v) == FcResultNoMatch)
+ {
+ double dpi, size, scale;
+
+ if (FcPatternGetDouble (pattern, FC_SIZE, 0, &size) != FcResultMatch)
+ {
+ size = 12.0;
+ (void) FcPatternDel (pattern, FC_SIZE);
+ FcPatternAddDouble (pattern, FC_SIZE, size);
+ }
+ if (FcPatternGetDouble (pattern, FC_SCALE, 0, &scale) != FcResultMatch)
+ {
+ scale = 1.0;
+ (void) FcPatternDel (pattern, FC_SCALE);
+ FcPatternAddDouble (pattern, FC_SCALE, scale);
+ }
+ size *= scale;
+ if (FcPatternGetDouble (pattern, FC_DPI, 0, &dpi) != FcResultMatch)
+ {
+ dpi = 75.0;
+ (void) FcPatternDel (pattern, FC_DPI);
+ FcPatternAddDouble (pattern, FC_DPI, dpi);
+ }
+ size *= dpi / 72.0;
+ FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size);
+ }
+
+ if (FcPatternGet (pattern, FC_LANG, 0, &v) == FcResultNoMatch)
+ {
+ char *lang;
+ char *territory;
+ char *after;
+ int lang_len, territory_len;
+ char lang_local[128];
+ char *ctype = setlocale (LC_CTYPE, NULL);
+
+ /*
+ * Check if setlocale (LC_ALL, "") has been called
+ */
+ if (!ctype || !strcmp (ctype, "C"))
+ {
+ ctype = getenv ("LC_ALL");
+ if (!ctype)
+ {
+ ctype = getenv ("LC_CTYPE");
+ if (!ctype)
+ ctype = getenv ("LANG");
+ }
+ }
+ if (ctype)
+ {
+ lang = ctype;
+ territory = strchr (ctype, '_');
+ if (territory)
+ {
+ lang_len = territory - lang;
+ territory = territory + 1;
+ after = strchr (territory, '.');
+ if (!after)
+ {
+ after = strchr (territory, '@');
+ if (!after)
+ after = territory + strlen (territory);
+ }
+ territory_len = after - territory;
+ if (lang_len + 1 + territory_len + 1 <= sizeof (lang_local))
+ {
+ strncpy (lang_local, lang, lang_len);
+ lang_local[lang_len] = '-';
+ strncpy (lang_local + lang_len + 1, territory, territory_len);
+ lang_local[lang_len + 1 + territory_len] = '\0';
+ FcPatternAddString (pattern, FC_LANG, (FcChar8 *) lang_local);
+ }
+ }
+ else
+ FcPatternAddString (pattern, FC_LANG, (FcChar8 *) lang);
+ }
+ }
+ if (FcPatternGet (pattern, FC_FONTVERSION, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddInteger (pattern, FC_FONTVERSION, 0x7fffffff);
+ }
+
+ if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch)
+ {
+ FcPatternAddInteger (pattern, FC_HINT_STYLE, FC_HINT_FULL);
+ }
+}
diff --git a/nx-X11/extras/fontconfig/src/fcdir.c b/nx-X11/extras/fontconfig/src/fcdir.c
new file mode 100644
index 000000000..974886d36
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcdir.c
@@ -0,0 +1,270 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fcdir.c,v 1.9 2002/08/31 22:17:32 keithp Exp $
+ *
+ * Copyright © 2000 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <dirent.h>
+
+FcBool
+FcFileIsDir (const FcChar8 *file)
+{
+ struct stat statb;
+
+ if (stat ((const char *) file, &statb) != 0)
+ return FcFalse;
+ return S_ISDIR(statb.st_mode);
+}
+
+FcBool
+FcFileScanConfig (FcFontSet *set,
+ FcStrSet *dirs,
+ FcGlobalCache *cache,
+ FcBlanks *blanks,
+ const FcChar8 *file,
+ FcBool force,
+ FcConfig *config)
+{
+ int id;
+ FcChar8 *name;
+ FcPattern *font;
+ FcBool ret = FcTrue;
+ FcBool isDir;
+ int count = 0;
+ FcGlobalCacheFile *cache_file;
+ FcGlobalCacheDir *cache_dir;
+ FcBool need_scan;
+
+ if (config && !FcConfigAcceptFilename (config, file))
+ return FcTrue;
+
+ if (force)
+ cache = 0;
+ id = 0;
+ do
+ {
+ need_scan = FcTrue;
+ font = 0;
+ /*
+ * Check the cache
+ */
+ if (cache)
+ {
+ if ((cache_file = FcGlobalCacheFileGet (cache, file, id, &count)))
+ {
+ /*
+ * Found a cache entry for the file
+ */
+ if (FcGlobalCacheCheckTime (file, &cache_file->info))
+ {
+ name = cache_file->name;
+ need_scan = FcFalse;
+ FcGlobalCacheReferenced (cache, &cache_file->info);
+ /* "." means the file doesn't contain a font */
+ if (FcStrCmp (name, FC_FONT_FILE_INVALID) != 0)
+ {
+ font = FcNameParse (name);
+ if (font)
+ if (!FcPatternAddString (font, FC_FILE, file))
+ ret = FcFalse;
+ }
+ }
+ }
+ else if ((cache_dir = FcGlobalCacheDirGet (cache, file,
+ strlen ((const char *) file),
+ FcFalse)))
+ {
+ if (FcGlobalCacheCheckTime (cache_dir->info.file,
+ &cache_dir->info))
+ {
+ font = 0;
+ need_scan = FcFalse;
+ FcGlobalCacheReferenced (cache, &cache_dir->info);
+ if (!FcStrSetAdd (dirs, file))
+ ret = FcFalse;
+ }
+ }
+ }
+ /*
+ * Nothing in the cache, scan the file
+ */
+ if (need_scan)
+ {
+ if (FcDebug () & FC_DBG_SCAN)
+ {
+ printf ("\tScanning file %s...", file);
+ fflush (stdout);
+ }
+ font = FcFreeTypeQuery (file, id, blanks, &count);
+ if (FcDebug () & FC_DBG_SCAN)
+ printf ("done\n");
+ isDir = FcFalse;
+ if (!font && FcFileIsDir (file))
+ {
+ isDir = FcTrue;
+ ret = FcStrSetAdd (dirs, file);
+ }
+ /*
+ * Update the cache
+ */
+ if (cache && font)
+ {
+ FcChar8 *unparse;
+
+ unparse = FcNameUnparse (font);
+ if (unparse)
+ {
+ (void) FcGlobalCacheUpdate (cache, file, id, unparse);
+ FcStrFree (unparse);
+ }
+ }
+ }
+ /*
+ * Add the font
+ */
+ if (font && (!config || FcConfigAcceptFont (config, font)))
+ {
+ if (!FcFontSetAdd (set, font))
+ {
+ FcPatternDestroy (font);
+ font = 0;
+ ret = FcFalse;
+ }
+ }
+ else if (font)
+ FcPatternDestroy (font);
+ id++;
+ } while (font && ret && id < count);
+ return ret;
+}
+
+FcBool
+FcFileScan (FcFontSet *set,
+ FcStrSet *dirs,
+ FcGlobalCache *cache,
+ FcBlanks *blanks,
+ const FcChar8 *file,
+ FcBool force)
+{
+ return FcFileScanConfig (set, dirs, cache, blanks, file, force, 0);
+}
+
+/*
+ * Scan 'dir', adding font files to 'set' and
+ * subdirectories to 'dirs'
+ */
+
+FcBool
+FcDirScanConfig (FcFontSet *set,
+ FcStrSet *dirs,
+ FcGlobalCache *cache,
+ FcBlanks *blanks,
+ const FcChar8 *dir,
+ FcBool force,
+ FcConfig *config)
+{
+ DIR *d;
+ struct dirent *e;
+ FcChar8 *file;
+ FcChar8 *base;
+ FcBool ret = FcTrue;
+
+ if (config && !FcConfigAcceptFilename (config, dir))
+ return FcTrue;
+
+ if (!force)
+ {
+ /*
+ * Check fonts.cache-<version> file
+ */
+ if (FcDirCacheReadDir (set, dirs, dir, config))
+ {
+ if (cache)
+ FcGlobalCacheReferenceSubdir (cache, dir);
+ return FcTrue;
+ }
+
+ /*
+ * Check ~/.fonts.cache-<version> file
+ */
+ if (cache && FcGlobalCacheScanDir (set, dirs, cache, dir, config))
+ return FcTrue;
+ }
+
+ /* freed below */
+ file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
+ if (!file)
+ return FcFalse;
+
+ strcpy ((char *) file, (char *) dir);
+ strcat ((char *) file, "/");
+ base = file + strlen ((char *) file);
+
+ if (FcDebug () & FC_DBG_SCAN)
+ printf ("\tScanning dir %s\n", dir);
+
+ d = opendir ((char *) dir);
+
+ if (!d)
+ {
+ free (file);
+ /* Don't complain about missing directories */
+ if (errno == ENOENT)
+ return FcTrue;
+ return FcFalse;
+ }
+ while (ret && (e = readdir (d)))
+ {
+ if (e->d_name[0] != '.' && strlen (e->d_name) < FC_MAX_FILE_LEN)
+ {
+ strcpy ((char *) base, (char *) e->d_name);
+ ret = FcFileScanConfig (set, dirs, cache, blanks, file, force, config);
+ }
+ }
+ free (file);
+ closedir (d);
+ /*
+ * Now that the directory has been scanned,
+ * add the cache entry
+ */
+ if (ret && cache)
+ FcGlobalCacheUpdate (cache, dir, 0, 0);
+
+ return ret;
+}
+
+FcBool
+FcDirScan (FcFontSet *set,
+ FcStrSet *dirs,
+ FcGlobalCache *cache,
+ FcBlanks *blanks,
+ const FcChar8 *dir,
+ FcBool force)
+{
+ return FcDirScanConfig (set, dirs, cache, blanks, dir, force, 0);
+}
+
+FcBool
+FcDirSave (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir)
+{
+ return FcDirCacheWriteDir (set, dirs, dir);
+}
diff --git a/nx-X11/extras/fontconfig/src/fcfreetype.c b/nx-X11/extras/fontconfig/src/fcfreetype.c
new file mode 100644
index 000000000..ee4af4056
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcfreetype.c
@@ -0,0 +1,2847 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fcfreetype.c,v 1.11 2002/08/31 22:17:32 keithp Exp $
+ *
+ * Copyright © 2001 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+/*
+ Copyright © 2002-2003 by Juliusz Chroboczek
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "fcint.h"
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_TRUETYPE_TABLES_H
+#include FT_SFNT_NAMES_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TYPE1_TABLES_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_SFNT_H
+#include FT_INTERNAL_TRUETYPE_TYPES_H
+#if HAVE_FT_GET_X11_FONT_FORMAT
+#include FT_XFREE86_H
+#endif
+
+#if HAVE_FT_GET_BDF_PROPERTY
+#include FT_BDF_H
+#include FT_MODULE_H
+#define HAS_BDF_PROPERTY(f) ((f) && (f)->driver && \
+ (f)->driver->root.clazz->get_interface)
+#define MY_Get_BDF_Property(f,n,p) (HAS_BDF_PROPERTY(f) ? \
+ FT_Get_BDF_Property(f,n,p) : \
+ FT_Err_Invalid_Argument)
+#endif
+
+#if !HAVE_FT_GET_BDF_PROPERTY
+#warning "No FT_Get_BDF_Property: Please install freetype 2.1.4 or later"
+#endif
+
+#if !HAVE_FT_GET_PS_FONT_INFO
+#warning "No FT_Get_PS_Font_Info: Please install freetype 2.1.1 or later"
+#endif
+
+/*
+ * Keep Han languages separated by eliminating languages
+ * that the codePageRange bits says aren't supported
+ */
+
+static const struct {
+ int bit;
+ const FcChar8 *lang;
+} FcCodePageRange[] = {
+ { 17, (const FcChar8 *) "ja" },
+ { 18, (const FcChar8 *) "zh-cn" },
+ { 19, (const FcChar8 *) "ko" },
+ { 20, (const FcChar8 *) "zh-tw" },
+};
+
+#define NUM_CODE_PAGE_RANGE (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
+
+FcBool
+FcFreeTypeIsExclusiveLang (const FcChar8 *lang)
+{
+ int i;
+
+ for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
+ {
+ if (FcLangCompare (lang, FcCodePageRange[i].lang) != FcLangDifferentLang)
+ return FcTrue;
+ }
+ return FcFalse;
+}
+
+typedef struct {
+ FT_UShort platform_id;
+ FT_UShort encoding_id;
+ char *fromcode;
+} FcFtEncoding;
+
+#define TT_ENCODING_DONT_CARE 0xffff
+#define FC_ENCODING_MAC_ROMAN "MACINTOSH"
+
+static const FcFtEncoding fcFtEncoding[] = {
+ { TT_PLATFORM_APPLE_UNICODE, TT_ENCODING_DONT_CARE, "UCS-2BE" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, "MACINTOSH" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_ID_JAPANESE, "SJIS" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, "UTF-16BE" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, "SJIS-WIN" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, "GB3212" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, "BIG-5" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, "Wansung" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, "Johab" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, "UCS4" },
+ { TT_PLATFORM_ISO, TT_ISO_ID_7BIT_ASCII, "ASCII" },
+ { TT_PLATFORM_ISO, TT_ISO_ID_10646, "UCS-2BE" },
+ { TT_PLATFORM_ISO, TT_ISO_ID_8859_1, "ISO-8859-1" },
+};
+
+#define NUM_FC_FT_ENCODING (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0]))
+
+typedef struct {
+ FT_UShort platform_id;
+ FT_UShort language_id;
+ char *lang;
+} FcFtLanguage;
+
+#define TT_LANGUAGE_DONT_CARE 0xffff
+
+static const FcFtLanguage fcFtLanguage[] = {
+ { TT_PLATFORM_APPLE_UNICODE, TT_LANGUAGE_DONT_CARE, 0 },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ENGLISH, "en" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FRENCH, "fr" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GERMAN, "de" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ITALIAN, "it" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_DUTCH, "nl" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SWEDISH, "sv" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SPANISH, "es" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_DANISH, "da" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_PORTUGUESE, "pt" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_NORWEGIAN, "no" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_HEBREW, "he" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_JAPANESE, "ja" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ARABIC, "ar" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FINNISH, "fi" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GREEK, "el" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ICELANDIC, "is" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALTESE, "mt" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TURKISH, "tr" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CROATIAN, "hr" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CHINESE_TRADITIONAL, "zh-tw" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_URDU, "ur" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_HINDI, "hi" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_THAI, "th" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KOREAN, "ko" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LITHUANIAN, "lt" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_POLISH, "pl" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_HUNGARIAN, "hu" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ESTONIAN, "et" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LETTISH, "lv" },
+/* { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SAAMISK, ??? */
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FAEROESE, "fo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FARSI, "fa" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_RUSSIAN, "ru" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CHINESE_SIMPLIFIED, "zh-cn" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FLEMISH, "nl" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_IRISH, "ga" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ALBANIAN, "sq" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ROMANIAN, "ro" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CZECH, "cs" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SLOVAK, "sk" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SLOVENIAN, "sl" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_YIDDISH, "yi" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SERBIAN, "sr" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MACEDONIAN, "mk" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BULGARIAN, "bg" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_UKRAINIAN, "uk" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BYELORUSSIAN, "be" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_UZBEK, "uz" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KAZAKH, "kk" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI, "az" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT, "az" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT, "ar" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ARMENIAN, "hy" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GEORGIAN, "ka" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MOLDAVIAN, "mo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KIRGHIZ, "ky" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TAJIKI, "tg" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TURKMEN, "tk" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MONGOLIAN, "mo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT,"mo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT, "mo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_PASHTO, "ps" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KURDISH, "ku" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KASHMIRI, "ks" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SINDHI, "sd" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TIBETAN, "bo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_NEPALI, "ne" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SANSKRIT, "sa" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MARATHI, "mr" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BENGALI, "bn" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ASSAMESE, "as" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GUJARATI, "gu" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_PUNJABI, "pa" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ORIYA, "or" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAYALAM, "ml" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KANNADA, "kn" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TAMIL, "ta" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TELUGU, "te" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SINHALESE, "si" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BURMESE, "my" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KHMER, "km" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LAO, "lo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_VIETNAMESE, "vi" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_INDONESIAN, "id" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TAGALOG, "tl" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAY_ROMAN_SCRIPT, "ms" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAY_ARABIC_SCRIPT, "ms" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AMHARIC, "am" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TIGRINYA, "ti" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GALLA, "om" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SOMALI, "so" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SWAHILI, "sw" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_RUANDA, "rw" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_RUNDI, "rn" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CHEWA, "ny" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAGASY, "mg" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ESPERANTO, "eo" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_WELSH, "cy" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BASQUE, "eu" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CATALAN, "ca" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LATIN, "la" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_QUECHUA, "qu" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GUARANI, "gn" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AYMARA, "ay" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TATAR, "tt" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_UIGHUR, "ug" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_DZONGKHA, "dz" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_JAVANESE, "jw" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SUNDANESE, "su" },
+
+#if 0 /* these seem to be errors that have been dropped */
+
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SCOTTISH_GAELIC },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_IRISH_GAELIC },
+
+#endif
+
+ /* The following codes are new as of 2000-03-10 */
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GALICIAN, "gl" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AFRIKAANS, "af" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BRETON, "br" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_INUKTITUT, "iu" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SCOTTISH_GAELIC, "gd" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MANX_GAELIC, "gv" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_IRISH_GAELIC, "ga" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TONGAN, "to" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GREEK_POLYTONIC, "el" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GREELANDIC, "ik" },
+ { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT,"az" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_SAUDI_ARABIA, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_IRAQ, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_EGYPT, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_LIBYA, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_ALGERIA, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_MOROCCO, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_TUNISIA, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_OMAN, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_YEMEN, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_SYRIA, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_JORDAN, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_LEBANON, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_KUWAIT, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_UAE, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_BAHRAIN, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_QATAR, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BULGARIAN_BULGARIA, "bg" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CATALAN_SPAIN, "ca" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_TAIWAN, "zh-tw" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_PRC, "zh-cn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_HONG_KONG, "zh-hk" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_SINGAPORE, "zh-sg" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_MACAU, "zh-mo" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CZECH_CZECH_REPUBLIC, "cs" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DANISH_DENMARK, "da" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_GERMANY, "de" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_SWITZERLAND, "de" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_AUSTRIA, "de" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_LUXEMBOURG, "de" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_LIECHTENSTEI, "de" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GREEK_GREECE, "el" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_UNITED_STATES, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_UNITED_KINGDOM, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_AUSTRALIA, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_CANADA, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_NEW_ZEALAND, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_IRELAND, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_SOUTH_AFRICA, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_JAMAICA, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_CARIBBEAN, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_BELIZE, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_TRINIDAD, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_ZIMBABWE, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_PHILIPPINES, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT,"es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_MEXICO, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT,"es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_GUATEMALA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_COSTA_RICA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PANAMA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC,"es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_VENEZUELA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_COLOMBIA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PERU, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_ARGENTINA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_ECUADOR, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_CHILE, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_URUGUAY, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PARAGUAY, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_BOLIVIA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_EL_SALVADOR, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_HONDURAS, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_NICARAGUA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PUERTO_RICO, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FINNISH_FINLAND, "fi" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_FRANCE, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_BELGIUM, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_CANADA, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_SWITZERLAND, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_LUXEMBOURG, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_MONACO, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HEBREW_ISRAEL, "he" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HUNGARIAN_HUNGARY, "hu" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ICELANDIC_ICELAND, "is" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ITALIAN_ITALY, "it" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ITALIAN_SWITZERLAND, "it" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_JAPANESE_JAPAN, "ja" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA,"ko" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KOREAN_JOHAB_KOREA, "ko" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DUTCH_NETHERLANDS, "nl" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DUTCH_BELGIUM, "nl" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL, "no" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK, "nn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_POLISH_POLAND, "pl" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PORTUGUESE_BRAZIL, "pt" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PORTUGUESE_PORTUGAL, "pt" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND,"rm" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ROMANIAN_ROMANIA, "ro" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MOLDAVIAN_MOLDAVIA, "mo" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_RUSSIAN_RUSSIA, "ru" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_RUSSIAN_MOLDAVIA, "ru" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CROATIAN_CROATIA, "hr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SERBIAN_SERBIA_LATIN, "sr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC, "sr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SLOVAK_SLOVAKIA, "sk" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ALBANIAN_ALBANIA, "sq" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SWEDISH_SWEDEN, "sv" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SWEDISH_FINLAND, "sv" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_THAI_THAILAND, "th" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TURKISH_TURKEY, "tr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_URDU_PAKISTAN, "ur" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_INDONESIAN_INDONESIA, "id" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_UKRAINIAN_UKRAINE, "uk" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BELARUSIAN_BELARUS, "be" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SLOVENE_SLOVENIA, "sl" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ESTONIAN_ESTONIA, "et" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LATVIAN_LATVIA, "lv" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LITHUANIAN_LITHUANIA, "lt" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA,"lt" },
+
+#ifdef TT_MS_LANGID_MAORI_NEW_ZELAND
+ /* this seems to be an error that have been dropped */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MAORI_NEW_ZEALAND, "mi" },
+#endif
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FARSI_IRAN, "fa" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_VIETNAMESE_VIET_NAM, "vi" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARMENIAN_ARMENIA, "hy" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN, "az" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC, "az" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BASQUE_SPAIN, "eu" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SORBIAN_GERMANY, "wen" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MACEDONIAN_MACEDONIA, "mk" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SUTU_SOUTH_AFRICA, "st" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TSONGA_SOUTH_AFRICA, "ts" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TSWANA_SOUTH_AFRICA, "tn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_VENDA_SOUTH_AFRICA, "ven" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_XHOSA_SOUTH_AFRICA, "xh" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ZULU_SOUTH_AFRICA, "zu" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA, "af" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GEORGIAN_GEORGIA, "ka" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS, "fo" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HINDI_INDIA, "hi" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALTESE_MALTA, "mt" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SAAMI_LAPONIA, "se" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM,"gd" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_IRISH_GAELIC_IRELAND, "ga" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALAY_MALAYSIA, "ms" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM, "ms" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KAZAK_KAZAKSTAN, "kk" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SWAHILI_KENYA, "sw" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN, "uz" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC, "uz" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TATAR_TATARSTAN, "tt" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BENGALI_INDIA, "bn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PUNJABI_INDIA, "pa" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GUJARATI_INDIA, "gu" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ORIYA_INDIA, "or" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAMIL_INDIA, "ta" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TELUGU_INDIA, "te" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KANNADA_INDIA, "kn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALAYALAM_INDIA, "ml" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ASSAMESE_INDIA, "as" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MARATHI_INDIA, "mr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SANSKRIT_INDIA, "sa" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KONKANI_INDIA, "kok" },
+
+ /* new as of 2001-01-01 */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_GENERAL, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_GENERAL, "zh" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_GENERAL, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_WEST_INDIES, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_REUNION, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_CONGO, "fr" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_SENEGAL, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_CAMEROON, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_COTE_D_IVOIRE, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_MALI, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA,"bs" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_URDU_INDIA, "ur" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAJIK_TAJIKISTAN, "tg" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_YIDDISH_GERMANY, "yi" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN, "ky" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TURKMEN_TURKMENISTAN, "tk" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MONGOLIAN_MONGOLIA, "mn" },
+
+ /* the following seems to be inconsistent;
+ here is the current "official" way: */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIBETAN_BHUTAN, "bo" },
+ /* and here is what is used by Passport SDK */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIBETAN_CHINA, "bo" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DZONGHKA_BHUTAN, "dz" },
+ /* end of inconsistency */
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_WELSH_WALES, "cy" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KHMER_CAMBODIA, "km" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LAO_LAOS, "lo" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BURMESE_MYANMAR, "my" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GALICIAN_SPAIN, "gl" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MANIPURI_INDIA, "mni" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SINDHI_INDIA, "sd" },
+ /* the following one is only encountered in Microsoft RTF specification */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KASHMIRI_PAKISTAN, "ks" },
+ /* the following one is not in the Passport list, looks like an omission */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KASHMIRI_INDIA, "ks" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NEPALI_NEPAL, "ne" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NEPALI_INDIA, "ne" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRISIAN_NETHERLANDS, "fy" },
+
+ /* new as of 2001-03-01 (from Office Xp) */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_HONG_KONG, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_INDIA, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_MALAYSIA, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_SINGAPORE, "en" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SYRIAC_SYRIA, "syr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SINHALESE_SRI_LANKA, "si" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHEROKEE_UNITED_STATES, "chr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_INUKTITUT_CANADA, "iu" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AMHARIC_ETHIOPIA, "am" },
+#if 0
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAMAZIGHT_MOROCCO },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN },
+#endif
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PASHTO_AFGHANISTAN, "ps" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FILIPINO_PHILIPPINES, "phi" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DHIVEHI_MALDIVES, "div" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_OROMO_ETHIOPIA, "om" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIGRIGNA_ETHIOPIA, "ti" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIGRIGNA_ERYTHREA, "ti" },
+
+ /* New additions from Windows Xp/Passport SDK 2001-11-10. */
+
+ /* don't ask what this one means... It is commented out currently. */
+#if 0
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GREEK_GREECE2 },
+#endif
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_UNITED_STATES, "es" },
+ /* The following two IDs blatantly violate MS specs by using a */
+ /* sublanguage >,. */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_LATIN_AMERICA, "es" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_NORTH_AFRICA, "fr" },
+
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_MOROCCO, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_HAITI, "fr" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BENGALI_BANGLADESH, "bn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN, "ar" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN,"mn" },
+#if 0
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_EDO_NIGERIA },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FULFULDE_NIGERIA },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_IBIBIO_NIGERIA },
+#endif
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HAUSA_NIGERIA, "ha" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_YORUBA_NIGERIA, "yo" },
+ /* language codes from, to, are (still) unknown. */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_IGBO_NIGERIA, "ibo" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KANURI_NIGERIA, "kau" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GUARANI_PARAGUAY, "gn" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HAWAIIAN_UNITED_STATES, "haw" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LATIN, "la" },
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SOMALI_SOMALIA, "so" },
+#if 0
+ /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */
+ /* not written (but OTOH the peculiar writing system is worth */
+ /* studying). */
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_YI_CHINA },
+#endif
+ { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES,"pap" },
+};
+
+#define NUM_FC_FT_LANGUAGE (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0]))
+
+typedef struct {
+ FT_UShort language_id;
+ char *fromcode;
+} FcMacRomanFake;
+
+static const FcMacRomanFake fcMacRomanFake[] = {
+ { TT_MS_LANGID_JAPANESE_JAPAN, "SJIS-WIN" },
+ { TT_MS_LANGID_ENGLISH_UNITED_STATES, "ASCII" },
+};
+
+static FcChar8 *
+FcFontCapabilities(FT_Face face);
+
+#define NUM_FC_MAC_ROMAN_FAKE (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0]))
+
+#if HAVE_ICONV && HAVE_ICONV_H
+#define USE_ICONV 1
+#include <iconv.h>
+#endif
+
+static FcChar8 *
+FcSfntNameTranscode (FT_SfntName *sname)
+{
+ int i;
+ char *fromcode;
+#if USE_ICONV
+ iconv_t cd;
+#endif
+ FcChar8 *utf8;
+
+ for (i = 0; i < NUM_FC_FT_ENCODING; i++)
+ if (fcFtEncoding[i].platform_id == sname->platform_id &&
+ (fcFtEncoding[i].encoding_id == TT_ENCODING_DONT_CARE ||
+ fcFtEncoding[i].encoding_id == sname->encoding_id))
+ break;
+ if (i == NUM_FC_FT_ENCODING)
+ return 0;
+ fromcode = fcFtEncoding[i].fromcode;
+
+ /*
+ * "real" Mac language IDs are all less than 150.
+ * Names using one of the MS language IDs are assumed
+ * to use an associated encoding (Yes, this is a kludge)
+ */
+ if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN) &&
+ sname->language_id >= 0x100)
+ {
+ int f;
+
+ fromcode = 0;
+ for (f = 0; f < NUM_FC_MAC_ROMAN_FAKE; f++)
+ if (fcMacRomanFake[f].language_id == sname->language_id)
+ {
+ fromcode = fcMacRomanFake[f].fromcode;
+ break;
+ }
+ if (!fromcode)
+ return 0;
+ }
+ if (!strcmp (fromcode, "UCS-2BE") || !strcmp (fromcode, "UTF-16BE"))
+ {
+ FcChar8 *src = sname->string;
+ int src_len = sname->string_len;
+ int len;
+ int wchar;
+ int ilen, olen;
+ FcChar8 *u8;
+ FcChar32 ucs4;
+
+ /*
+ * Convert Utf16 to Utf8
+ */
+
+ if (!FcUtf16Len (src, FcEndianBig, src_len, &len, &wchar))
+ return 0;
+
+ /*
+ * Allocate plenty of space. Freed below
+ */
+ utf8 = malloc (len * FC_UTF8_MAX_LEN + 1);
+ if (!utf8)
+ return 0;
+
+ u8 = utf8;
+
+ while ((ilen = FcUtf16ToUcs4 (src, FcEndianBig, &ucs4, src_len)) > 0)
+ {
+ src_len -= ilen;
+ src += ilen;
+ olen = FcUcs4ToUtf8 (ucs4, u8);
+ u8 += olen;
+ }
+ *u8 = '\0';
+ goto done;
+ }
+ if (!strcmp (fromcode, "ASCII") || !strcmp (fromcode, "ISO-8859-1"))
+ {
+ FcChar8 *src = sname->string;
+ int src_len = sname->string_len;
+ int olen;
+ FcChar8 *u8;
+ FcChar32 ucs4;
+
+ /*
+ * Convert Latin1 to Utf8. Freed below
+ */
+ utf8 = malloc (src_len * 2 + 1);
+ if (!utf8)
+ return 0;
+
+ u8 = utf8;
+ while (src_len > 0)
+ {
+ ucs4 = *src++;
+ src_len--;
+ olen = FcUcs4ToUtf8 (ucs4, u8);
+ u8 += olen;
+ }
+ *u8 = '\0';
+ goto done;
+ }
+ if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN))
+ {
+ FcChar8 *u8;
+ const FcCharMap *map = FcFreeTypeGetPrivateMap (ft_encoding_apple_roman);
+ FcChar8 *src = (FcChar8 *) sname->string;
+ int src_len = sname->string_len;
+
+ /*
+ * Convert AppleRoman to Utf8
+ */
+ if (!map)
+ return 0;
+
+ utf8 = malloc (sname->string_len * 3 + 1);
+ if (!utf8)
+ return 0;
+
+ u8 = utf8;
+ while (src_len > 0)
+ {
+ FcChar32 ucs4 = FcFreeTypePrivateToUcs4 (*src++, map);
+ int olen = FcUcs4ToUtf8 (ucs4, u8);
+ src_len--;
+ u8 += olen;
+ }
+ *u8 = '\0';
+ goto done;
+ }
+#if USE_ICONV
+ cd = iconv_open ("UTF-8", fromcode);
+ if (cd && cd != (iconv_t) (-1))
+ {
+ size_t in_bytes_left = sname->string_len;
+ size_t out_bytes_left = sname->string_len * FC_UTF8_MAX_LEN;
+ char *inbuf, *outbuf;
+
+ utf8 = malloc (out_bytes_left + 1);
+ if (!utf8)
+ {
+ iconv_close (cd);
+ return 0;
+ }
+
+ outbuf = (char *) utf8;
+ inbuf = (char *) sname->string;
+
+ while (in_bytes_left)
+ {
+ size_t did = iconv (cd,
+ &inbuf, &in_bytes_left,
+ &outbuf, &out_bytes_left);
+ if (did == (size_t) (-1))
+ {
+ iconv_close (cd);
+ free (utf8);
+ return 0;
+ }
+ }
+ iconv_close (cd);
+ *outbuf = '\0';
+ goto done;
+ }
+#endif
+ return 0;
+done:
+ if (FcStrCmpIgnoreBlanksAndCase (utf8, "") == 0)
+ {
+ free (utf8);
+ return 0;
+ }
+ return utf8;
+}
+
+static FcChar8 *
+FcSfntNameLanguage (FT_SfntName *sname)
+{
+ int i;
+ for (i = 0; i < NUM_FC_FT_LANGUAGE; i++)
+ if (fcFtLanguage[i].platform_id == sname->platform_id &&
+ (fcFtLanguage[i].language_id == TT_LANGUAGE_DONT_CARE ||
+ fcFtLanguage[i].language_id == sname->language_id))
+ return fcFtLanguage[i].lang;
+ return 0;
+}
+
+/* Order is significant. For example, some B&H fonts are hinted by
+ URW++, and both strings appear in the notice. */
+
+static const struct {
+ const FT_String *notice;
+ const FcChar8 *foundry;
+} FcNoticeFoundries[] = {
+ { (const FT_String *) "Bigelow", (const FcChar8 *) "b&h" },
+ { (const FT_String *) "Adobe", (const FcChar8 *) "adobe" },
+ { (const FT_String *) "Bitstream", (const FcChar8 *) "bitstream" },
+ { (const FT_String *) "Monotype", (const FcChar8 *) "monotype" },
+ { (const FT_String *) "Linotype", (const FcChar8 *) "linotype" },
+ { (const FT_String *) "LINOTYPE-HELL",
+ (const FcChar8 *) "linotype" },
+ { (const FT_String *) "IBM", (const FcChar8 *) "ibm" },
+ { (const FT_String *) "URW", (const FcChar8 *) "urw" },
+ { (const FT_String *) "International Typeface Corporation",
+ (const FcChar8 *) "itc" },
+ { (const FT_String *) "Tiro Typeworks",
+ (const FcChar8 *) "tiro" },
+ { (const FT_String *) "XFree86", (const FcChar8 *) "xfree86" },
+ { (const FT_String *) "Microsoft", (const FcChar8 *) "microsoft" },
+ { (const FT_String *) "Omega", (const FcChar8 *) "omega" },
+ { (const FT_String *) "Font21", (const FcChar8 *) "hwan" },
+ { (const FT_String *) "HanYang System",
+ (const FcChar8 *) "hanyang" }
+};
+
+#define NUM_NOTICE_FOUNDRIES (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0]))
+
+static const FcChar8 *
+FcNoticeFoundry(const FT_String *notice)
+{
+ int i;
+
+ if (notice)
+ for(i = 0; i < NUM_NOTICE_FOUNDRIES; i++)
+ if (strstr ((const char *) notice, (const char *) FcNoticeFoundries[i].notice))
+ return FcNoticeFoundries[i].foundry;
+ return 0;
+}
+
+static FcBool
+FcVendorMatch(const FT_Char vendor[4], const FT_Char *vendor_string)
+{
+ /* vendor is not necessarily NUL-terminated. */
+ int i, len;
+
+ len = strlen(vendor_string);
+ if (memcmp(vendor, vendor_string, len) != 0)
+ return FcFalse;
+ for (i = len; i < 4; i++)
+ if (vendor[i] != ' ' && vendor[i] != '\0')
+ return FcFalse;
+ return FcTrue;
+}
+
+/* This table is partly taken from ttmkfdir by Joerg Pommnitz. */
+
+/* It should not contain useless entries (such as UNKN) nor duplicate
+ entries for padding both with spaces and NULs. */
+
+static const struct {
+ const FT_Char *vendor;
+ const FcChar8 *foundry;
+} FcVendorFoundries[] = {
+ { (const FT_Char *) "ADBE", (const FcChar8 *) "adobe"},
+ { (const FT_Char *) "AGFA", (const FcChar8 *) "agfa"},
+ { (const FT_Char *) "ALTS", (const FcChar8 *) "altsys"},
+ { (const FT_Char *) "APPL", (const FcChar8 *) "apple"},
+ { (const FT_Char *) "ARPH", (const FcChar8 *) "arphic"},
+ { (const FT_Char *) "ATEC", (const FcChar8 *) "alltype"},
+ { (const FT_Char *) "B&H", (const FcChar8 *) "b&h"},
+ { (const FT_Char *) "BITS", (const FcChar8 *) "bitstream"},
+ { (const FT_Char *) "CANO", (const FcChar8 *) "cannon"},
+ { (const FT_Char *) "DYNA", (const FcChar8 *) "dynalab"},
+ { (const FT_Char *) "EPSN", (const FcChar8 *) "epson"},
+ { (const FT_Char *) "FJ", (const FcChar8 *) "fujitsu"},
+ { (const FT_Char *) "IBM", (const FcChar8 *) "ibm"},
+ { (const FT_Char *) "ITC", (const FcChar8 *) "itc"},
+ { (const FT_Char *) "IMPR", (const FcChar8 *) "impress"},
+ { (const FT_Char *) "LARA", (const FcChar8 *) "larabiefonts"},
+ { (const FT_Char *) "LEAF", (const FcChar8 *) "interleaf"},
+ { (const FT_Char *) "LETR", (const FcChar8 *) "letraset"},
+ { (const FT_Char *) "LINO", (const FcChar8 *) "linotype"},
+ { (const FT_Char *) "MACR", (const FcChar8 *) "macromedia"},
+ { (const FT_Char *) "MONO", (const FcChar8 *) "monotype"},
+ { (const FT_Char *) "MS", (const FcChar8 *) "microsoft"},
+ { (const FT_Char *) "MT", (const FcChar8 *) "monotype"},
+ { (const FT_Char *) "NEC", (const FcChar8 *) "nec"},
+ { (const FT_Char *) "PARA", (const FcChar8 *) "paratype"},
+ { (const FT_Char *) "QMSI", (const FcChar8 *) "qms"},
+ { (const FT_Char *) "RICO", (const FcChar8 *) "ricoh"},
+ { (const FT_Char *) "URW", (const FcChar8 *) "urw"},
+ { (const FT_Char *) "Y&Y", (const FcChar8 *) "y&y"}
+};
+
+#define NUM_VENDOR_FOUNDRIES (sizeof (FcVendorFoundries) / sizeof (FcVendorFoundries[0]))
+
+static const FcChar8 *
+FcVendorFoundry(const FT_Char vendor[4])
+{
+ int i;
+
+ if (vendor)
+ for(i = 0; i < NUM_VENDOR_FOUNDRIES; i++)
+ if (FcVendorMatch (vendor, FcVendorFoundries[i].vendor))
+ return FcVendorFoundries[i].foundry;
+ return 0;
+}
+
+typedef struct _FcStringConst {
+ const FcChar8 *name;
+ int value;
+} FcStringConst;
+
+static int
+FcStringIsConst (const FcChar8 *string,
+ const FcStringConst *c,
+ int nc)
+{
+ int i;
+
+ for (i = 0; i < nc; i++)
+ if (FcStrCmpIgnoreBlanksAndCase (string, c[i].name) == 0)
+ return c[i].value;
+ return -1;
+}
+
+static int
+FcStringContainsConst (const FcChar8 *string,
+ const FcStringConst *c,
+ int nc)
+{
+ int i;
+
+ for (i = 0; i < nc; i++)
+ if (FcStrContainsIgnoreBlanksAndCase (string, c[i].name))
+ return c[i].value;
+ return -1;
+}
+
+static const FcStringConst weightConsts[] = {
+ { "thin", FC_WEIGHT_THIN },
+ { "extralight", FC_WEIGHT_EXTRALIGHT },
+ { "ultralight", FC_WEIGHT_ULTRALIGHT },
+ { "light", FC_WEIGHT_LIGHT },
+ { "book", FC_WEIGHT_BOOK },
+ { "regular", FC_WEIGHT_REGULAR },
+ { "normal", FC_WEIGHT_NORMAL },
+ { "medium", FC_WEIGHT_MEDIUM },
+ { "demibold", FC_WEIGHT_DEMIBOLD },
+ { "demi", FC_WEIGHT_DEMIBOLD },
+ { "semibold", FC_WEIGHT_SEMIBOLD },
+ { "bold", FC_WEIGHT_BOLD },
+ { "extrabold", FC_WEIGHT_EXTRABOLD },
+ { "ultrabold", FC_WEIGHT_ULTRABOLD },
+ { "black", FC_WEIGHT_BLACK },
+ { "heavy", FC_WEIGHT_HEAVY },
+};
+
+#define NUM_WEIGHT_CONSTS (sizeof (weightConsts) / sizeof (weightConsts[0]))
+
+#define FcIsWeight(s) FcStringIsConst(s,weightConsts,NUM_WEIGHT_CONSTS)
+#define FcContainsWeight(s) FcStringContainsConst (s,weightConsts,NUM_WEIGHT_CONSTS)
+
+static const FcStringConst widthConsts[] = {
+ { "ultracondensed", FC_WIDTH_ULTRACONDENSED },
+ { "extracondensed", FC_WIDTH_EXTRACONDENSED },
+ { "semicondensed", FC_WIDTH_SEMICONDENSED },
+ { "condensed", FC_WIDTH_CONDENSED }, /* must be after *condensed */
+ { "normal", FC_WIDTH_NORMAL },
+ { "semiexpanded", FC_WIDTH_SEMIEXPANDED },
+ { "extraexpanded", FC_WIDTH_EXTRAEXPANDED },
+ { "ultraexpanded", FC_WIDTH_ULTRAEXPANDED },
+ { "expanded", FC_WIDTH_EXPANDED }, /* must be after *expanded */
+};
+
+#define NUM_WIDTH_CONSTS (sizeof (widthConsts) / sizeof (widthConsts[0]))
+
+#define FcIsWidth(s) FcStringIsConst(s,widthConsts,NUM_WIDTH_CONSTS)
+#define FcContainsWidth(s) FcStringContainsConst (s,widthConsts,NUM_WIDTH_CONSTS)
+
+static const FcStringConst slantConsts[] = {
+ { "italic", FC_SLANT_ITALIC },
+ { "oblique", FC_SLANT_OBLIQUE },
+};
+
+#define NUM_SLANT_CONSTS (sizeof (slantConsts) / sizeof (slantConsts[0]))
+
+#define FcIsSlant(s) FcStringIsConst(s,slantConsts,NUM_SLANT_CONSTS)
+#define FcContainsSlant(s) FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS)
+
+static double
+FcGetPixelSize (FT_Face face, int i)
+{
+#if HAVE_FT_GET_BDF_PROPERTY
+ if (face->num_fixed_sizes == 1)
+ {
+ BDF_PropertyRec prop;
+ int rc;
+
+ rc = MY_Get_BDF_Property (face, "PIXEL_SIZE", &prop);
+ if (rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
+ return (double) prop.u.integer;
+ }
+#endif
+#if HAVE_FT_BITMAP_SIZE_Y_PPEM
+ return (double) face->available_sizes[i].y_ppem / 64.0;
+#else
+ return (double) face->available_sizes[i].height;
+#endif
+}
+
+static FcBool
+FcStringInPatternElement (FcPattern *pat, char *elt, FcChar8 *string)
+{
+ int e;
+ FcChar8 *old;
+ for (e = 0; FcPatternGetString (pat, elt, e, &old) == FcResultMatch; e++)
+ if (!FcStrCmpIgnoreBlanksAndCase (old, string))
+ {
+ return FcTrue;
+ break;
+ }
+ return FcFalse;
+}
+
+FcPattern *
+FcFreeTypeQuery (const FcChar8 *file,
+ int id,
+ FcBlanks *blanks,
+ int *count)
+{
+ FT_Face face;
+ FcPattern *pat;
+ int slant = -1;
+ int weight = -1;
+ int width = -1;
+ int i;
+ FcCharSet *cs;
+ FcLangSet *ls;
+ FT_Library ftLibrary;
+#if 0
+ FcChar8 *family = 0;
+#endif
+ FcChar8 *complex;
+ const FcChar8 *foundry = 0;
+ int spacing;
+ TT_OS2 *os2;
+#if HAVE_FT_GET_PS_FONT_INFO
+ PS_FontInfoRec psfontinfo;
+#endif
+#if HAVE_FT_GET_BDF_PROPERTY
+ BDF_PropertyRec prop;
+#endif
+ TT_Header *head;
+ const FcChar8 *exclusiveLang = 0;
+ FT_SfntName sname;
+ FT_UInt snamei, snamec;
+
+ int nfamily = 0;
+ int nfamily_lang = 0;
+ int nstyle = 0;
+ int nstyle_lang = 0;
+ int nfullname = 0;
+ int nfullname_lang = 0;
+
+ FcChar8 *style = 0;
+ int st;
+
+ if (FT_Init_FreeType (&ftLibrary))
+ return 0;
+
+ if (FT_New_Face (ftLibrary, (char *) file, id, &face))
+ goto bail;
+
+ *count = face->num_faces;
+
+ pat = FcPatternCreate ();
+ if (!pat)
+ goto bail0;
+
+ if (!FcPatternAddBool (pat, FC_OUTLINE,
+ (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0))
+ goto bail1;
+
+ if (!FcPatternAddBool (pat, FC_SCALABLE,
+ (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0))
+ goto bail1;
+
+
+ /*
+ * Get the OS/2 table
+ */
+ os2 = (TT_OS2 *) FT_Get_Sfnt_Table (face, ft_sfnt_os2);
+
+ /*
+ * Look first in the OS/2 table for the foundry, if
+ * not found here, the various notices will be searched for
+ * that information, either from the sfnt name tables or
+ * the Postscript FontInfo dictionary. Finally, the
+ * BDF properties will queried.
+ */
+
+ if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
+ foundry = FcVendorFoundry(os2->achVendID);
+
+ if (FcDebug () & FC_DBG_SCANV)
+ printf ("\n");
+ /*
+ * Grub through the name table looking for family
+ * and style names. FreeType makes quite a hash
+ * of them
+ */
+ snamec = FT_Get_Sfnt_Name_Count (face);
+ for (snamei = 0; snamei < snamec; snamei++)
+ {
+ FcChar8 *utf8;
+ FcChar8 *lang;
+ char *elt = 0, *eltlang = 0;
+ int *np = 0, *nlangp = 0;
+
+ if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0)
+ continue;
+
+ utf8 = FcSfntNameTranscode (&sname);
+ lang = FcSfntNameLanguage (&sname);
+
+ if (!utf8)
+ continue;
+
+ switch (sname.name_id) {
+ case TT_NAME_ID_FONT_FAMILY:
+#if 0
+ case TT_NAME_ID_PS_NAME:
+ case TT_NAME_ID_UNIQUE_ID:
+#endif
+ if (FcDebug () & FC_DBG_SCANV)
+ printf ("found family (n %2d p %d e %d l 0x%04x) %s\n",
+ sname.name_id, sname.platform_id,
+ sname.encoding_id, sname.language_id,
+ utf8);
+
+ elt = FC_FAMILY;
+ eltlang = FC_FAMILYLANG;
+ np = &nfamily;
+ nlangp = &nfamily_lang;
+ break;
+ case TT_NAME_ID_FULL_NAME:
+ case TT_NAME_ID_MAC_FULL_NAME:
+ if (FcDebug () & FC_DBG_SCANV)
+ printf ("found full (n %2d p %d e %d l 0x%04x) %s\n",
+ sname.name_id, sname.platform_id,
+ sname.encoding_id, sname.language_id,
+ utf8);
+
+ elt = FC_FULLNAME;
+ eltlang = FC_FULLNAMELANG;
+ np = &nfullname;
+ nlangp = &nfullname_lang;
+ break;
+ case TT_NAME_ID_FONT_SUBFAMILY:
+ if (FcDebug () & FC_DBG_SCANV)
+ printf ("found style (n %2d p %d e %d l 0x%04x) %s\n",
+ sname.name_id, sname.platform_id,
+ sname.encoding_id, sname.language_id,
+ utf8);
+
+ elt = FC_STYLE;
+ eltlang = FC_STYLELANG;
+ np = &nstyle;
+ nlangp = &nstyle_lang;
+ break;
+ case TT_NAME_ID_TRADEMARK:
+ case TT_NAME_ID_MANUFACTURER:
+ /* If the foundry wasn't found in the OS/2 table, look here */
+ if(!foundry)
+ foundry = FcNoticeFoundry((FT_String *) utf8);
+ break;
+ }
+ if (elt)
+ {
+ if (FcStringInPatternElement (pat, elt, utf8))
+ {
+ free (utf8);
+ continue;
+ }
+
+ /* add new element */
+ if (!FcPatternAddString (pat, elt, utf8))
+ {
+ free (utf8);
+ goto bail1;
+ }
+ free (utf8);
+ if (lang)
+ {
+ /* pad lang list with 'xx' to line up with elt */
+ while (*nlangp < *np)
+ {
+ if (!FcPatternAddString (pat, eltlang, "xx"))
+ goto bail1;
+ ++*nlangp;
+ }
+ if (!FcPatternAddString (pat, eltlang, lang))
+ goto bail1;
+ ++*nlangp;
+ }
+ ++*np;
+ }
+ else
+ free (utf8);
+ }
+
+ if (!nfamily && face->family_name &&
+ FcStrCmpIgnoreBlanksAndCase (face->family_name, "") != 0)
+ {
+ if (FcDebug () & FC_DBG_SCANV)
+ printf ("using FreeType family \"%s\"\n", face->family_name);
+ if (!FcPatternAddString (pat, FC_FAMILY, face->family_name))
+ goto bail1;
+ ++nfamily;
+ }
+
+ if (!nstyle && face->style_name &&
+ FcStrCmpIgnoreBlanksAndCase (face->style_name, "") != 0)
+ {
+ if (FcDebug () & FC_DBG_SCANV)
+ printf ("using FreeType style \"%s\"\n", face->style_name);
+ if (!FcPatternAddString (pat, FC_STYLE, face->style_name))
+ goto bail1;
+ ++nstyle;
+ }
+
+ if (!nfamily)
+ {
+ FcChar8 *start, *end;
+ FcChar8 *family;
+
+ start = (FcChar8 *) strrchr ((char *) file, '/');
+ if (start)
+ start++;
+ else
+ start = (FcChar8 *) file;
+ end = (FcChar8 *) strrchr ((char *) start, '.');
+ if (!end)
+ end = start + strlen ((char *) start);
+ /* freed below */
+ family = malloc (end - start + 1);
+ strncpy ((char *) family, (char *) start, end - start);
+ family[end - start] = '\0';
+ if (FcDebug () & FC_DBG_SCANV)
+ printf ("using filename for family %s\n", family);
+ if (!FcPatternAddString (pat, FC_FAMILY, family))
+ {
+ free (family);
+ goto bail1;
+ }
+ free (family);
+ ++nfamily;
+ }
+
+ /*
+ * Walk through FC_FULLNAME entries eliding those in FC_FAMILY
+ * or which are simply a FC_FAMILY and FC_STYLE glued together
+ */
+ {
+ int fn, fa, st;
+ FcChar8 *full;
+ FcChar8 *fam;
+ FcChar8 *style;
+
+ for (fn = 0; FcPatternGetString (pat, FC_FULLNAME, fn, &full) == FcResultMatch; fn++)
+ {
+ FcBool remove = FcFalse;
+ /*
+ * Check each family
+ */
+ for (fa = 0; !remove &&
+ FcPatternGetString (pat, FC_FAMILY,
+ fa, &fam) == FcResultMatch;
+ fa++)
+ {
+ /*
+ * for exact match
+ */
+ if (!FcStrCmpIgnoreBlanksAndCase (full, fam))
+ {
+ remove = FcTrue;
+ break;
+ }
+ /*
+ * If the family is in the full name, check the
+ * combination of this family with every style
+ */
+ if (!FcStrContainsIgnoreBlanksAndCase (full, fam))
+ continue;
+ for (st = 0; !remove &&
+ FcPatternGetString (pat, FC_STYLE,
+ st, &style) == FcResultMatch;
+ st++)
+ {
+ FcChar8 *both = FcStrPlus (fam, style);
+
+ if (both)
+ {
+ if (FcStrCmpIgnoreBlanksAndCase (full, both) == 0)
+ remove = FcTrue;
+ free (both);
+ }
+ }
+ }
+ if (remove)
+ {
+ FcPatternRemove (pat, FC_FULLNAME, fn);
+ FcPatternRemove (pat, FC_FULLNAMELANG, fn);
+ fn--;
+ nfullname--;
+ nfullname_lang--;
+ }
+ }
+ if (FcDebug () & FC_DBG_SCANV)
+ for (fn = 0; FcPatternGetString (pat, FC_FULLNAME, fn, &full) == FcResultMatch; fn++)
+ printf ("Saving unique fullname %s\n", full);
+ }
+
+ if (!FcPatternAddString (pat, FC_FILE, file))
+ goto bail1;
+
+ if (!FcPatternAddInteger (pat, FC_INDEX, id))
+ goto bail1;
+
+#if 0
+ /*
+ * don't even try this -- CJK 'monospace' fonts are really
+ * dual width, and most other fonts don't bother to set
+ * the attribute. Sigh.
+ */
+ if ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0)
+ if (!FcPatternAddInteger (pat, FC_SPACING, FC_MONO))
+ goto bail1;
+#endif
+
+ /*
+ * Find the font revision (if available)
+ */
+ head = (TT_Header *) FT_Get_Sfnt_Table (face, ft_sfnt_head);
+ if (head)
+ {
+ if (!FcPatternAddInteger (pat, FC_FONTVERSION, head->Font_Revision))
+ goto bail1;
+ }
+ else
+ {
+ if (!FcPatternAddInteger (pat, FC_FONTVERSION, 0))
+ goto bail1;
+ }
+
+ if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
+ {
+ for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
+ {
+ FT_ULong bits;
+ int bit;
+ if (FcCodePageRange[i].bit < 32)
+ {
+ bits = os2->ulCodePageRange1;
+ bit = FcCodePageRange[i].bit;
+ }
+ else
+ {
+ bits = os2->ulCodePageRange2;
+ bit = FcCodePageRange[i].bit - 32;
+ }
+ if (bits & (1 << bit))
+ {
+ /*
+ * If the font advertises support for multiple
+ * "exclusive" languages, then include support
+ * for any language found to have coverage
+ */
+ if (exclusiveLang)
+ {
+ exclusiveLang = 0;
+ break;
+ }
+ exclusiveLang = FcCodePageRange[i].lang;
+ }
+ }
+ }
+
+ if (os2 && os2->version != 0xffff)
+ {
+ if (os2->usWeightClass == 0)
+ ;
+ else if (os2->usWeightClass < 150)
+ weight = FC_WEIGHT_THIN;
+ else if (os2->usWeightClass < 250)
+ weight = FC_WEIGHT_EXTRALIGHT;
+ else if (os2->usWeightClass < 350)
+ weight = FC_WEIGHT_LIGHT;
+ else if (os2->usWeightClass < 450)
+ weight = FC_WEIGHT_REGULAR;
+ else if (os2->usWeightClass < 550)
+ weight = FC_WEIGHT_MEDIUM;
+ else if (os2->usWeightClass < 650)
+ weight = FC_WEIGHT_SEMIBOLD;
+ else if (os2->usWeightClass < 750)
+ weight = FC_WEIGHT_BOLD;
+ else if (os2->usWeightClass < 850)
+ weight = FC_WEIGHT_EXTRABOLD;
+ else if (os2->usWeightClass < 950)
+ weight = FC_WEIGHT_BLACK;
+
+ switch (os2->usWidthClass) {
+ case 1: width = FC_WIDTH_ULTRACONDENSED; break;
+ case 2: width = FC_WIDTH_EXTRACONDENSED; break;
+ case 3: width = FC_WIDTH_CONDENSED; break;
+ case 4: width = FC_WIDTH_SEMICONDENSED; break;
+ case 5: width = FC_WIDTH_NORMAL; break;
+ case 6: width = FC_WIDTH_SEMIEXPANDED; break;
+ case 7: width = FC_WIDTH_EXPANDED; break;
+ case 8: width = FC_WIDTH_EXTRAEXPANDED; break;
+ case 9: width = FC_WIDTH_ULTRAEXPANDED; break;
+ }
+ }
+ if (os2 && (complex = FcFontCapabilities(face)))
+ {
+ if (!FcPatternAddString (pat, FC_CAPABILITY, complex))
+ {
+ free (complex);
+ goto bail1;
+ }
+ free (complex);
+ }
+
+ /*
+ * Type 1: Check for FontInfo dictionary information
+ * Code from g2@magestudios.net (Gerard Escalante)
+ */
+
+#if HAVE_FT_GET_PS_FONT_INFO
+ if (FT_Get_PS_Font_Info(face, &psfontinfo) == 0)
+ {
+ if (weight == -1 && psfontinfo.weight)
+ {
+ weight = FcIsWeight (psfontinfo.weight);
+ if (FcDebug() & FC_DBG_SCANV)
+ printf ("\tType1 weight %s maps to %d\n",
+ psfontinfo.weight, weight);
+ }
+
+#if 0
+ /*
+ * Don't bother with italic_angle; FreeType already extracts that
+ * information for us and sticks it into style_flags
+ */
+ if (psfontinfo.italic_angle)
+ slant = FC_SLANT_ITALIC;
+ else
+ slant = FC_SLANT_ROMAN;
+#endif
+
+ if(!foundry)
+ foundry = FcNoticeFoundry(psfontinfo.notice);
+ }
+#endif /* HAVE_FT_GET_PS_FONT_INFO */
+
+#if HAVE_FT_GET_BDF_PROPERTY
+ /*
+ * Finally, look for a FOUNDRY BDF property if no other
+ * mechanism has managed to locate a foundry
+ */
+
+ if (!foundry)
+ {
+ int rc;
+ BDF_PropertyRec prop;
+ rc = MY_Get_BDF_Property(face, "FOUNDRY", &prop);
+ if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM)
+ foundry = prop.u.atom;
+ }
+
+ if (width == -1)
+ {
+ if (MY_Get_BDF_Property(face, "RELATIVE_SETWIDTH", &prop) == 0 &&
+ (prop.type == BDF_PROPERTY_TYPE_INTEGER ||
+ prop.type == BDF_PROPERTY_TYPE_CARDINAL))
+ {
+ FT_Int32 value;
+
+ if (prop.type == BDF_PROPERTY_TYPE_INTEGER)
+ value = prop.u.integer;
+ else
+ value = (FT_Int32) prop.u.cardinal;
+ switch ((value + 5) / 10) {
+ case 1: width = FC_WIDTH_ULTRACONDENSED; break;
+ case 2: width = FC_WIDTH_EXTRACONDENSED; break;
+ case 3: width = FC_WIDTH_CONDENSED; break;
+ case 4: width = FC_WIDTH_SEMICONDENSED; break;
+ case 5: width = FC_WIDTH_NORMAL; break;
+ case 6: width = FC_WIDTH_SEMIEXPANDED; break;
+ case 7: width = FC_WIDTH_EXPANDED; break;
+ case 8: width = FC_WIDTH_EXTRAEXPANDED; break;
+ case 9: width = FC_WIDTH_ULTRAEXPANDED; break;
+ }
+ }
+ if (width == -1 &&
+ MY_Get_BDF_Property (face, "SETWIDTH_NAME", &prop) == 0 &&
+ prop.type == BDF_PROPERTY_TYPE_ATOM)
+ {
+ width = FcIsWidth (prop.u.atom);
+ if (FcDebug () & FC_DBG_SCANV)
+ printf ("\tsetwidth %s maps to %d\n", prop.u.atom, width);
+ }
+ }
+#endif
+
+ /*
+ * Look for weight, width and slant names in the style value
+ */
+ for (st = 0; FcPatternGetString (pat, FC_STYLE, st, &style) == FcResultMatch; st++)
+ {
+ if (weight == -1)
+ {
+ weight = FcContainsWeight (style);
+ if (FcDebug() & FC_DBG_SCANV)
+ printf ("\tStyle %s maps to weight %d\n", style, weight);
+ }
+ if (width == -1)
+ {
+ width = FcContainsWidth (style);
+ if (FcDebug() & FC_DBG_SCANV)
+ printf ("\tStyle %s maps to width %d\n", style, width);
+ }
+ if (slant == -1)
+ {
+ slant = FcContainsSlant (style);
+ if (FcDebug() & FC_DBG_SCANV)
+ printf ("\tStyle %s maps to slant %d\n", style, slant);
+ }
+ }
+ /*
+ * Pull default values from the FreeType flags if more
+ * specific values not found above
+ */
+ if (slant == -1)
+ {
+ slant = FC_SLANT_ROMAN;
+ if (face->style_flags & FT_STYLE_FLAG_ITALIC)
+ slant = FC_SLANT_ITALIC;
+ }
+
+ if (weight == -1)
+ {
+ weight = FC_WEIGHT_MEDIUM;
+ if (face->style_flags & FT_STYLE_FLAG_BOLD)
+ weight = FC_WEIGHT_BOLD;
+ }
+
+ if (width == -1)
+ width = FC_WIDTH_NORMAL;
+
+ if (foundry == 0)
+ foundry = "unknown";
+
+ if (!FcPatternAddInteger (pat, FC_SLANT, slant))
+ goto bail1;
+
+ if (!FcPatternAddInteger (pat, FC_WEIGHT, weight))
+ goto bail1;
+
+ if (!FcPatternAddInteger (pat, FC_WIDTH, width))
+ goto bail1;
+
+ if (!FcPatternAddString (pat, FC_FOUNDRY, foundry))
+ goto bail1;
+
+ /*
+ * Compute the unicode coverage for the font
+ */
+ cs = FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
+ if (!cs)
+ goto bail1;
+
+#if HAVE_FT_GET_BDF_PROPERTY
+ /* For PCF fonts, override the computed spacing with the one from
+ the property */
+ if(MY_Get_BDF_Property(face, "SPACING", &prop) == 0 &&
+ prop.type == BDF_PROPERTY_TYPE_ATOM) {
+ if(!strcmp(prop.u.atom, "c") || !strcmp(prop.u.atom, "C"))
+ spacing = FC_CHARCELL;
+ else if(!strcmp(prop.u.atom, "m") || !strcmp(prop.u.atom, "M"))
+ spacing = FC_MONO;
+ else if(!strcmp(prop.u.atom, "p") || !strcmp(prop.u.atom, "P"))
+ spacing = FC_PROPORTIONAL;
+ }
+#endif
+
+ /*
+ * Skip over PCF fonts that have no encoded characters; they're
+ * usually just Unicode fonts transcoded to some legacy encoding
+ */
+ if (FcCharSetCount (cs) == 0)
+ {
+ if (!strcmp(FT_MODULE_CLASS(&face->driver->root)->module_name, "pcf"))
+ goto bail2;
+ }
+
+ if (!FcPatternAddCharSet (pat, FC_CHARSET, cs))
+ goto bail2;
+
+ ls = FcFreeTypeLangSet (cs, exclusiveLang);
+ if (!ls)
+ goto bail2;
+
+ if (!FcPatternAddLangSet (pat, FC_LANG, ls))
+ {
+ FcLangSetDestroy (ls);
+ goto bail2;
+ }
+
+ FcLangSetDestroy (ls);
+
+ if (spacing != FC_PROPORTIONAL)
+ if (!FcPatternAddInteger (pat, FC_SPACING, spacing))
+ goto bail2;
+
+ if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
+ {
+ for (i = 0; i < face->num_fixed_sizes; i++)
+ if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
+ FcGetPixelSize (face, i)))
+ goto bail1;
+ if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
+ goto bail1;
+#if HAVE_FT_GET_BDF_PROPERTY
+ if(face->num_fixed_sizes == 1) {
+ int rc;
+ int value;
+ BDF_PropertyRec prop;
+
+ rc = MY_Get_BDF_Property(face, "POINT_SIZE", &prop);
+ if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
+ value = prop.u.integer;
+ else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL)
+ value = prop.u.cardinal;
+ else
+ goto nevermind;
+ if(!FcPatternAddDouble(pat, FC_SIZE, value / 10.0))
+ goto nevermind;
+
+ rc = MY_Get_BDF_Property(face, "RESOLUTION_Y", &prop);
+ if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
+ value = prop.u.integer;
+ else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL)
+ value = prop.u.cardinal;
+ else
+ goto nevermind;
+ if(!FcPatternAddDouble(pat, FC_DPI, (double)value))
+ goto nevermind;
+
+ }
+ nevermind:
+ ;
+#endif
+ }
+#if HAVE_FT_GET_X11_FONT_FORMAT
+ /*
+ * Use the (not well documented or supported) X-specific function
+ * from FreeType to figure out the font format
+ */
+ {
+ const char *font_format = FT_Get_X11_Font_Format (face);
+ if (font_format)
+ FcPatternAddString (pat, FC_FONTFORMAT, font_format);
+ }
+#endif
+
+ /*
+ * Drop our reference to the charset
+ */
+ FcCharSetDestroy (cs);
+
+ /*
+ * Deallocate family/style values
+ */
+
+ FT_Done_Face (face);
+ FT_Done_FreeType (ftLibrary);
+ return pat;
+
+bail2:
+ FcCharSetDestroy (cs);
+bail1:
+ FcPatternDestroy (pat);
+bail0:
+ FT_Done_Face (face);
+bail:
+ FT_Done_FreeType (ftLibrary);
+ return 0;
+}
+
+
+/*
+ * For our purposes, this approximation is sufficient
+ */
+#if !HAVE_FT_GET_NEXT_CHAR
+#define FT_Get_Next_Char(face, ucs4, gi) ((ucs4) >= 0xffffff ? \
+ (*(gi) = 0), 0 : \
+ (*(gi) = 1), (ucs4) + 1)
+#warning "No FT_Get_Next_Char: Please install freetype version 2.1.0 or newer"
+#endif
+
+typedef struct _FcCharEnt {
+ FcChar16 bmp;
+ unsigned char encode;
+} FcCharEnt;
+
+struct _FcCharMap {
+ const FcCharEnt *ent;
+ int nent;
+};
+
+typedef struct _FcFontDecode {
+ FT_Encoding encoding;
+ const FcCharMap *map;
+ FcChar32 max;
+} FcFontDecode;
+
+static const FcCharEnt AppleRomanEnt[] = {
+ { 0x0020, 0x20 }, /* SPACE */
+ { 0x0021, 0x21 }, /* EXCLAMATION MARK */
+ { 0x0022, 0x22 }, /* QUOTATION MARK */
+ { 0x0023, 0x23 }, /* NUMBER SIGN */
+ { 0x0024, 0x24 }, /* DOLLAR SIGN */
+ { 0x0025, 0x25 }, /* PERCENT SIGN */
+ { 0x0026, 0x26 }, /* AMPERSAND */
+ { 0x0027, 0x27 }, /* APOSTROPHE */
+ { 0x0028, 0x28 }, /* LEFT PARENTHESIS */
+ { 0x0029, 0x29 }, /* RIGHT PARENTHESIS */
+ { 0x002A, 0x2A }, /* ASTERISK */
+ { 0x002B, 0x2B }, /* PLUS SIGN */
+ { 0x002C, 0x2C }, /* COMMA */
+ { 0x002D, 0x2D }, /* HYPHEN-MINUS */
+ { 0x002E, 0x2E }, /* FULL STOP */
+ { 0x002F, 0x2F }, /* SOLIDUS */
+ { 0x0030, 0x30 }, /* DIGIT ZERO */
+ { 0x0031, 0x31 }, /* DIGIT ONE */
+ { 0x0032, 0x32 }, /* DIGIT TWO */
+ { 0x0033, 0x33 }, /* DIGIT THREE */
+ { 0x0034, 0x34 }, /* DIGIT FOUR */
+ { 0x0035, 0x35 }, /* DIGIT FIVE */
+ { 0x0036, 0x36 }, /* DIGIT SIX */
+ { 0x0037, 0x37 }, /* DIGIT SEVEN */
+ { 0x0038, 0x38 }, /* DIGIT EIGHT */
+ { 0x0039, 0x39 }, /* DIGIT NINE */
+ { 0x003A, 0x3A }, /* COLON */
+ { 0x003B, 0x3B }, /* SEMICOLON */
+ { 0x003C, 0x3C }, /* LESS-THAN SIGN */
+ { 0x003D, 0x3D }, /* EQUALS SIGN */
+ { 0x003E, 0x3E }, /* GREATER-THAN SIGN */
+ { 0x003F, 0x3F }, /* QUESTION MARK */
+ { 0x0040, 0x40 }, /* COMMERCIAL AT */
+ { 0x0041, 0x41 }, /* LATIN CAPITAL LETTER A */
+ { 0x0042, 0x42 }, /* LATIN CAPITAL LETTER B */
+ { 0x0043, 0x43 }, /* LATIN CAPITAL LETTER C */
+ { 0x0044, 0x44 }, /* LATIN CAPITAL LETTER D */
+ { 0x0045, 0x45 }, /* LATIN CAPITAL LETTER E */
+ { 0x0046, 0x46 }, /* LATIN CAPITAL LETTER F */
+ { 0x0047, 0x47 }, /* LATIN CAPITAL LETTER G */
+ { 0x0048, 0x48 }, /* LATIN CAPITAL LETTER H */
+ { 0x0049, 0x49 }, /* LATIN CAPITAL LETTER I */
+ { 0x004A, 0x4A }, /* LATIN CAPITAL LETTER J */
+ { 0x004B, 0x4B }, /* LATIN CAPITAL LETTER K */
+ { 0x004C, 0x4C }, /* LATIN CAPITAL LETTER L */
+ { 0x004D, 0x4D }, /* LATIN CAPITAL LETTER M */
+ { 0x004E, 0x4E }, /* LATIN CAPITAL LETTER N */
+ { 0x004F, 0x4F }, /* LATIN CAPITAL LETTER O */
+ { 0x0050, 0x50 }, /* LATIN CAPITAL LETTER P */
+ { 0x0051, 0x51 }, /* LATIN CAPITAL LETTER Q */
+ { 0x0052, 0x52 }, /* LATIN CAPITAL LETTER R */
+ { 0x0053, 0x53 }, /* LATIN CAPITAL LETTER S */
+ { 0x0054, 0x54 }, /* LATIN CAPITAL LETTER T */
+ { 0x0055, 0x55 }, /* LATIN CAPITAL LETTER U */
+ { 0x0056, 0x56 }, /* LATIN CAPITAL LETTER V */
+ { 0x0057, 0x57 }, /* LATIN CAPITAL LETTER W */
+ { 0x0058, 0x58 }, /* LATIN CAPITAL LETTER X */
+ { 0x0059, 0x59 }, /* LATIN CAPITAL LETTER Y */
+ { 0x005A, 0x5A }, /* LATIN CAPITAL LETTER Z */
+ { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET */
+ { 0x005C, 0x5C }, /* REVERSE SOLIDUS */
+ { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET */
+ { 0x005E, 0x5E }, /* CIRCUMFLEX ACCENT */
+ { 0x005F, 0x5F }, /* LOW LINE */
+ { 0x0060, 0x60 }, /* GRAVE ACCENT */
+ { 0x0061, 0x61 }, /* LATIN SMALL LETTER A */
+ { 0x0062, 0x62 }, /* LATIN SMALL LETTER B */
+ { 0x0063, 0x63 }, /* LATIN SMALL LETTER C */
+ { 0x0064, 0x64 }, /* LATIN SMALL LETTER D */
+ { 0x0065, 0x65 }, /* LATIN SMALL LETTER E */
+ { 0x0066, 0x66 }, /* LATIN SMALL LETTER F */
+ { 0x0067, 0x67 }, /* LATIN SMALL LETTER G */
+ { 0x0068, 0x68 }, /* LATIN SMALL LETTER H */
+ { 0x0069, 0x69 }, /* LATIN SMALL LETTER I */
+ { 0x006A, 0x6A }, /* LATIN SMALL LETTER J */
+ { 0x006B, 0x6B }, /* LATIN SMALL LETTER K */
+ { 0x006C, 0x6C }, /* LATIN SMALL LETTER L */
+ { 0x006D, 0x6D }, /* LATIN SMALL LETTER M */
+ { 0x006E, 0x6E }, /* LATIN SMALL LETTER N */
+ { 0x006F, 0x6F }, /* LATIN SMALL LETTER O */
+ { 0x0070, 0x70 }, /* LATIN SMALL LETTER P */
+ { 0x0071, 0x71 }, /* LATIN SMALL LETTER Q */
+ { 0x0072, 0x72 }, /* LATIN SMALL LETTER R */
+ { 0x0073, 0x73 }, /* LATIN SMALL LETTER S */
+ { 0x0074, 0x74 }, /* LATIN SMALL LETTER T */
+ { 0x0075, 0x75 }, /* LATIN SMALL LETTER U */
+ { 0x0076, 0x76 }, /* LATIN SMALL LETTER V */
+ { 0x0077, 0x77 }, /* LATIN SMALL LETTER W */
+ { 0x0078, 0x78 }, /* LATIN SMALL LETTER X */
+ { 0x0079, 0x79 }, /* LATIN SMALL LETTER Y */
+ { 0x007A, 0x7A }, /* LATIN SMALL LETTER Z */
+ { 0x007B, 0x7B }, /* LEFT CURLY BRACKET */
+ { 0x007C, 0x7C }, /* VERTICAL LINE */
+ { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET */
+ { 0x007E, 0x7E }, /* TILDE */
+ { 0x00A0, 0xCA }, /* NO-BREAK SPACE */
+ { 0x00A1, 0xC1 }, /* INVERTED EXCLAMATION MARK */
+ { 0x00A2, 0xA2 }, /* CENT SIGN */
+ { 0x00A3, 0xA3 }, /* POUND SIGN */
+ { 0x00A5, 0xB4 }, /* YEN SIGN */
+ { 0x00A7, 0xA4 }, /* SECTION SIGN */
+ { 0x00A8, 0xAC }, /* DIAERESIS */
+ { 0x00A9, 0xA9 }, /* COPYRIGHT SIGN */
+ { 0x00AA, 0xBB }, /* FEMININE ORDINAL INDICATOR */
+ { 0x00AB, 0xC7 }, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
+ { 0x00AC, 0xC2 }, /* NOT SIGN */
+ { 0x00AE, 0xA8 }, /* REGISTERED SIGN */
+ { 0x00AF, 0xF8 }, /* MACRON */
+ { 0x00B0, 0xA1 }, /* DEGREE SIGN */
+ { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN */
+ { 0x00B4, 0xAB }, /* ACUTE ACCENT */
+ { 0x00B5, 0xB5 }, /* MICRO SIGN */
+ { 0x00B6, 0xA6 }, /* PILCROW SIGN */
+ { 0x00B7, 0xE1 }, /* MIDDLE DOT */
+ { 0x00B8, 0xFC }, /* CEDILLA */
+ { 0x00BA, 0xBC }, /* MASCULINE ORDINAL INDICATOR */
+ { 0x00BB, 0xC8 }, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
+ { 0x00BF, 0xC0 }, /* INVERTED QUESTION MARK */
+ { 0x00C0, 0xCB }, /* LATIN CAPITAL LETTER A WITH GRAVE */
+ { 0x00C1, 0xE7 }, /* LATIN CAPITAL LETTER A WITH ACUTE */
+ { 0x00C2, 0xE5 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
+ { 0x00C3, 0xCC }, /* LATIN CAPITAL LETTER A WITH TILDE */
+ { 0x00C4, 0x80 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
+ { 0x00C5, 0x81 }, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
+ { 0x00C6, 0xAE }, /* LATIN CAPITAL LETTER AE */
+ { 0x00C7, 0x82 }, /* LATIN CAPITAL LETTER C WITH CEDILLA */
+ { 0x00C8, 0xE9 }, /* LATIN CAPITAL LETTER E WITH GRAVE */
+ { 0x00C9, 0x83 }, /* LATIN CAPITAL LETTER E WITH ACUTE */
+ { 0x00CA, 0xE6 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
+ { 0x00CB, 0xE8 }, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
+ { 0x00CC, 0xED }, /* LATIN CAPITAL LETTER I WITH GRAVE */
+ { 0x00CD, 0xEA }, /* LATIN CAPITAL LETTER I WITH ACUTE */
+ { 0x00CE, 0xEB }, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
+ { 0x00CF, 0xEC }, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
+ { 0x00D1, 0x84 }, /* LATIN CAPITAL LETTER N WITH TILDE */
+ { 0x00D2, 0xF1 }, /* LATIN CAPITAL LETTER O WITH GRAVE */
+ { 0x00D3, 0xEE }, /* LATIN CAPITAL LETTER O WITH ACUTE */
+ { 0x00D4, 0xEF }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
+ { 0x00D5, 0xCD }, /* LATIN CAPITAL LETTER O WITH TILDE */
+ { 0x00D6, 0x85 }, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
+ { 0x00D8, 0xAF }, /* LATIN CAPITAL LETTER O WITH STROKE */
+ { 0x00D9, 0xF4 }, /* LATIN CAPITAL LETTER U WITH GRAVE */
+ { 0x00DA, 0xF2 }, /* LATIN CAPITAL LETTER U WITH ACUTE */
+ { 0x00DB, 0xF3 }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
+ { 0x00DC, 0x86 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
+ { 0x00DF, 0xA7 }, /* LATIN SMALL LETTER SHARP S */
+ { 0x00E0, 0x88 }, /* LATIN SMALL LETTER A WITH GRAVE */
+ { 0x00E1, 0x87 }, /* LATIN SMALL LETTER A WITH ACUTE */
+ { 0x00E2, 0x89 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
+ { 0x00E3, 0x8B }, /* LATIN SMALL LETTER A WITH TILDE */
+ { 0x00E4, 0x8A }, /* LATIN SMALL LETTER A WITH DIAERESIS */
+ { 0x00E5, 0x8C }, /* LATIN SMALL LETTER A WITH RING ABOVE */
+ { 0x00E6, 0xBE }, /* LATIN SMALL LETTER AE */
+ { 0x00E7, 0x8D }, /* LATIN SMALL LETTER C WITH CEDILLA */
+ { 0x00E8, 0x8F }, /* LATIN SMALL LETTER E WITH GRAVE */
+ { 0x00E9, 0x8E }, /* LATIN SMALL LETTER E WITH ACUTE */
+ { 0x00EA, 0x90 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */
+ { 0x00EB, 0x91 }, /* LATIN SMALL LETTER E WITH DIAERESIS */
+ { 0x00EC, 0x93 }, /* LATIN SMALL LETTER I WITH GRAVE */
+ { 0x00ED, 0x92 }, /* LATIN SMALL LETTER I WITH ACUTE */
+ { 0x00EE, 0x94 }, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
+ { 0x00EF, 0x95 }, /* LATIN SMALL LETTER I WITH DIAERESIS */
+ { 0x00F1, 0x96 }, /* LATIN SMALL LETTER N WITH TILDE */
+ { 0x00F2, 0x98 }, /* LATIN SMALL LETTER O WITH GRAVE */
+ { 0x00F3, 0x97 }, /* LATIN SMALL LETTER O WITH ACUTE */
+ { 0x00F4, 0x99 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
+ { 0x00F5, 0x9B }, /* LATIN SMALL LETTER O WITH TILDE */
+ { 0x00F6, 0x9A }, /* LATIN SMALL LETTER O WITH DIAERESIS */
+ { 0x00F7, 0xD6 }, /* DIVISION SIGN */
+ { 0x00F8, 0xBF }, /* LATIN SMALL LETTER O WITH STROKE */
+ { 0x00F9, 0x9D }, /* LATIN SMALL LETTER U WITH GRAVE */
+ { 0x00FA, 0x9C }, /* LATIN SMALL LETTER U WITH ACUTE */
+ { 0x00FB, 0x9E }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
+ { 0x00FC, 0x9F }, /* LATIN SMALL LETTER U WITH DIAERESIS */
+ { 0x00FF, 0xD8 }, /* LATIN SMALL LETTER Y WITH DIAERESIS */
+ { 0x0131, 0xF5 }, /* LATIN SMALL LETTER DOTLESS I */
+ { 0x0152, 0xCE }, /* LATIN CAPITAL LIGATURE OE */
+ { 0x0153, 0xCF }, /* LATIN SMALL LIGATURE OE */
+ { 0x0178, 0xD9 }, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
+ { 0x0192, 0xC4 }, /* LATIN SMALL LETTER F WITH HOOK */
+ { 0x02C6, 0xF6 }, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
+ { 0x02C7, 0xFF }, /* CARON */
+ { 0x02D8, 0xF9 }, /* BREVE */
+ { 0x02D9, 0xFA }, /* DOT ABOVE */
+ { 0x02DA, 0xFB }, /* RING ABOVE */
+ { 0x02DB, 0xFE }, /* OGONEK */
+ { 0x02DC, 0xF7 }, /* SMALL TILDE */
+ { 0x02DD, 0xFD }, /* DOUBLE ACUTE ACCENT */
+ { 0x03A9, 0xBD }, /* GREEK CAPITAL LETTER OMEGA */
+ { 0x03C0, 0xB9 }, /* GREEK SMALL LETTER PI */
+ { 0x2013, 0xD0 }, /* EN DASH */
+ { 0x2014, 0xD1 }, /* EM DASH */
+ { 0x2018, 0xD4 }, /* LEFT SINGLE QUOTATION MARK */
+ { 0x2019, 0xD5 }, /* RIGHT SINGLE QUOTATION MARK */
+ { 0x201A, 0xE2 }, /* SINGLE LOW-9 QUOTATION MARK */
+ { 0x201C, 0xD2 }, /* LEFT DOUBLE QUOTATION MARK */
+ { 0x201D, 0xD3 }, /* RIGHT DOUBLE QUOTATION MARK */
+ { 0x201E, 0xE3 }, /* DOUBLE LOW-9 QUOTATION MARK */
+ { 0x2020, 0xA0 }, /* DAGGER */
+ { 0x2021, 0xE0 }, /* DOUBLE DAGGER */
+ { 0x2022, 0xA5 }, /* BULLET */
+ { 0x2026, 0xC9 }, /* HORIZONTAL ELLIPSIS */
+ { 0x2030, 0xE4 }, /* PER MILLE SIGN */
+ { 0x2039, 0xDC }, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
+ { 0x203A, 0xDD }, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
+ { 0x2044, 0xDA }, /* FRACTION SLASH */
+ { 0x20AC, 0xDB }, /* EURO SIGN */
+ { 0x2122, 0xAA }, /* TRADE MARK SIGN */
+ { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL */
+ { 0x2206, 0xC6 }, /* INCREMENT */
+ { 0x220F, 0xB8 }, /* N-ARY PRODUCT */
+ { 0x2211, 0xB7 }, /* N-ARY SUMMATION */
+ { 0x221A, 0xC3 }, /* SQUARE ROOT */
+ { 0x221E, 0xB0 }, /* INFINITY */
+ { 0x222B, 0xBA }, /* INTEGRAL */
+ { 0x2248, 0xC5 }, /* ALMOST EQUAL TO */
+ { 0x2260, 0xAD }, /* NOT EQUAL TO */
+ { 0x2264, 0xB2 }, /* LESS-THAN OR EQUAL TO */
+ { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO */
+ { 0x25CA, 0xD7 }, /* LOZENGE */
+ { 0xF8FF, 0xF0 }, /* Apple logo */
+ { 0xFB01, 0xDE }, /* LATIN SMALL LIGATURE FI */
+ { 0xFB02, 0xDF }, /* LATIN SMALL LIGATURE FL */
+};
+
+static const FcCharMap AppleRoman = {
+ AppleRomanEnt,
+ sizeof (AppleRomanEnt) / sizeof (AppleRomanEnt[0])
+};
+
+static const FcCharEnt AdobeSymbolEnt[] = {
+ { 0x0020, 0x20 }, /* SPACE # space */
+ { 0x0021, 0x21 }, /* EXCLAMATION MARK # exclam */
+ { 0x0023, 0x23 }, /* NUMBER SIGN # numbersign */
+ { 0x0025, 0x25 }, /* PERCENT SIGN # percent */
+ { 0x0026, 0x26 }, /* AMPERSAND # ampersand */
+ { 0x0028, 0x28 }, /* LEFT PARENTHESIS # parenleft */
+ { 0x0029, 0x29 }, /* RIGHT PARENTHESIS # parenright */
+ { 0x002B, 0x2B }, /* PLUS SIGN # plus */
+ { 0x002C, 0x2C }, /* COMMA # comma */
+ { 0x002E, 0x2E }, /* FULL STOP # period */
+ { 0x002F, 0x2F }, /* SOLIDUS # slash */
+ { 0x0030, 0x30 }, /* DIGIT ZERO # zero */
+ { 0x0031, 0x31 }, /* DIGIT ONE # one */
+ { 0x0032, 0x32 }, /* DIGIT TWO # two */
+ { 0x0033, 0x33 }, /* DIGIT THREE # three */
+ { 0x0034, 0x34 }, /* DIGIT FOUR # four */
+ { 0x0035, 0x35 }, /* DIGIT FIVE # five */
+ { 0x0036, 0x36 }, /* DIGIT SIX # six */
+ { 0x0037, 0x37 }, /* DIGIT SEVEN # seven */
+ { 0x0038, 0x38 }, /* DIGIT EIGHT # eight */
+ { 0x0039, 0x39 }, /* DIGIT NINE # nine */
+ { 0x003A, 0x3A }, /* COLON # colon */
+ { 0x003B, 0x3B }, /* SEMICOLON # semicolon */
+ { 0x003C, 0x3C }, /* LESS-THAN SIGN # less */
+ { 0x003D, 0x3D }, /* EQUALS SIGN # equal */
+ { 0x003E, 0x3E }, /* GREATER-THAN SIGN # greater */
+ { 0x003F, 0x3F }, /* QUESTION MARK # question */
+ { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET # bracketleft */
+ { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET # bracketright */
+ { 0x005F, 0x5F }, /* LOW LINE # underscore */
+ { 0x007B, 0x7B }, /* LEFT CURLY BRACKET # braceleft */
+ { 0x007C, 0x7C }, /* VERTICAL LINE # bar */
+ { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET # braceright */
+ { 0x00A0, 0x20 }, /* NO-BREAK SPACE # space */
+ { 0x00AC, 0xD8 }, /* NOT SIGN # logicalnot */
+ { 0x00B0, 0xB0 }, /* DEGREE SIGN # degree */
+ { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN # plusminus */
+ { 0x00B5, 0x6D }, /* MICRO SIGN # mu */
+ { 0x00D7, 0xB4 }, /* MULTIPLICATION SIGN # multiply */
+ { 0x00F7, 0xB8 }, /* DIVISION SIGN # divide */
+ { 0x0192, 0xA6 }, /* LATIN SMALL LETTER F WITH HOOK # florin */
+ { 0x0391, 0x41 }, /* GREEK CAPITAL LETTER ALPHA # Alpha */
+ { 0x0392, 0x42 }, /* GREEK CAPITAL LETTER BETA # Beta */
+ { 0x0393, 0x47 }, /* GREEK CAPITAL LETTER GAMMA # Gamma */
+ { 0x0394, 0x44 }, /* GREEK CAPITAL LETTER DELTA # Delta */
+ { 0x0395, 0x45 }, /* GREEK CAPITAL LETTER EPSILON # Epsilon */
+ { 0x0396, 0x5A }, /* GREEK CAPITAL LETTER ZETA # Zeta */
+ { 0x0397, 0x48 }, /* GREEK CAPITAL LETTER ETA # Eta */
+ { 0x0398, 0x51 }, /* GREEK CAPITAL LETTER THETA # Theta */
+ { 0x0399, 0x49 }, /* GREEK CAPITAL LETTER IOTA # Iota */
+ { 0x039A, 0x4B }, /* GREEK CAPITAL LETTER KAPPA # Kappa */
+ { 0x039B, 0x4C }, /* GREEK CAPITAL LETTER LAMDA # Lambda */
+ { 0x039C, 0x4D }, /* GREEK CAPITAL LETTER MU # Mu */
+ { 0x039D, 0x4E }, /* GREEK CAPITAL LETTER NU # Nu */
+ { 0x039E, 0x58 }, /* GREEK CAPITAL LETTER XI # Xi */
+ { 0x039F, 0x4F }, /* GREEK CAPITAL LETTER OMICRON # Omicron */
+ { 0x03A0, 0x50 }, /* GREEK CAPITAL LETTER PI # Pi */
+ { 0x03A1, 0x52 }, /* GREEK CAPITAL LETTER RHO # Rho */
+ { 0x03A3, 0x53 }, /* GREEK CAPITAL LETTER SIGMA # Sigma */
+ { 0x03A4, 0x54 }, /* GREEK CAPITAL LETTER TAU # Tau */
+ { 0x03A5, 0x55 }, /* GREEK CAPITAL LETTER UPSILON # Upsilon */
+ { 0x03A6, 0x46 }, /* GREEK CAPITAL LETTER PHI # Phi */
+ { 0x03A7, 0x43 }, /* GREEK CAPITAL LETTER CHI # Chi */
+ { 0x03A8, 0x59 }, /* GREEK CAPITAL LETTER PSI # Psi */
+ { 0x03A9, 0x57 }, /* GREEK CAPITAL LETTER OMEGA # Omega */
+ { 0x03B1, 0x61 }, /* GREEK SMALL LETTER ALPHA # alpha */
+ { 0x03B2, 0x62 }, /* GREEK SMALL LETTER BETA # beta */
+ { 0x03B3, 0x67 }, /* GREEK SMALL LETTER GAMMA # gamma */
+ { 0x03B4, 0x64 }, /* GREEK SMALL LETTER DELTA # delta */
+ { 0x03B5, 0x65 }, /* GREEK SMALL LETTER EPSILON # epsilon */
+ { 0x03B6, 0x7A }, /* GREEK SMALL LETTER ZETA # zeta */
+ { 0x03B7, 0x68 }, /* GREEK SMALL LETTER ETA # eta */
+ { 0x03B8, 0x71 }, /* GREEK SMALL LETTER THETA # theta */
+ { 0x03B9, 0x69 }, /* GREEK SMALL LETTER IOTA # iota */
+ { 0x03BA, 0x6B }, /* GREEK SMALL LETTER KAPPA # kappa */
+ { 0x03BB, 0x6C }, /* GREEK SMALL LETTER LAMDA # lambda */
+ { 0x03BC, 0x6D }, /* GREEK SMALL LETTER MU # mu */
+ { 0x03BD, 0x6E }, /* GREEK SMALL LETTER NU # nu */
+ { 0x03BE, 0x78 }, /* GREEK SMALL LETTER XI # xi */
+ { 0x03BF, 0x6F }, /* GREEK SMALL LETTER OMICRON # omicron */
+ { 0x03C0, 0x70 }, /* GREEK SMALL LETTER PI # pi */
+ { 0x03C1, 0x72 }, /* GREEK SMALL LETTER RHO # rho */
+ { 0x03C2, 0x56 }, /* GREEK SMALL LETTER FINAL SIGMA # sigma1 */
+ { 0x03C3, 0x73 }, /* GREEK SMALL LETTER SIGMA # sigma */
+ { 0x03C4, 0x74 }, /* GREEK SMALL LETTER TAU # tau */
+ { 0x03C5, 0x75 }, /* GREEK SMALL LETTER UPSILON # upsilon */
+ { 0x03C6, 0x66 }, /* GREEK SMALL LETTER PHI # phi */
+ { 0x03C7, 0x63 }, /* GREEK SMALL LETTER CHI # chi */
+ { 0x03C8, 0x79 }, /* GREEK SMALL LETTER PSI # psi */
+ { 0x03C9, 0x77 }, /* GREEK SMALL LETTER OMEGA # omega */
+ { 0x03D1, 0x4A }, /* GREEK THETA SYMBOL # theta1 */
+ { 0x03D2, 0xA1 }, /* GREEK UPSILON WITH HOOK SYMBOL # Upsilon1 */
+ { 0x03D5, 0x6A }, /* GREEK PHI SYMBOL # phi1 */
+ { 0x03D6, 0x76 }, /* GREEK PI SYMBOL # omega1 */
+ { 0x2022, 0xB7 }, /* BULLET # bullet */
+ { 0x2026, 0xBC }, /* HORIZONTAL ELLIPSIS # ellipsis */
+ { 0x2032, 0xA2 }, /* PRIME # minute */
+ { 0x2033, 0xB2 }, /* DOUBLE PRIME # second */
+ { 0x2044, 0xA4 }, /* FRACTION SLASH # fraction */
+ { 0x20AC, 0xA0 }, /* EURO SIGN # Euro */
+ { 0x2111, 0xC1 }, /* BLACK-LETTER CAPITAL I # Ifraktur */
+ { 0x2118, 0xC3 }, /* SCRIPT CAPITAL P # weierstrass */
+ { 0x211C, 0xC2 }, /* BLACK-LETTER CAPITAL R # Rfraktur */
+ { 0x2126, 0x57 }, /* OHM SIGN # Omega */
+ { 0x2135, 0xC0 }, /* ALEF SYMBOL # aleph */
+ { 0x2190, 0xAC }, /* LEFTWARDS ARROW # arrowleft */
+ { 0x2191, 0xAD }, /* UPWARDS ARROW # arrowup */
+ { 0x2192, 0xAE }, /* RIGHTWARDS ARROW # arrowright */
+ { 0x2193, 0xAF }, /* DOWNWARDS ARROW # arrowdown */
+ { 0x2194, 0xAB }, /* LEFT RIGHT ARROW # arrowboth */
+ { 0x21B5, 0xBF }, /* DOWNWARDS ARROW WITH CORNER LEFTWARDS # carriagereturn */
+ { 0x21D0, 0xDC }, /* LEFTWARDS DOUBLE ARROW # arrowdblleft */
+ { 0x21D1, 0xDD }, /* UPWARDS DOUBLE ARROW # arrowdblup */
+ { 0x21D2, 0xDE }, /* RIGHTWARDS DOUBLE ARROW # arrowdblright */
+ { 0x21D3, 0xDF }, /* DOWNWARDS DOUBLE ARROW # arrowdbldown */
+ { 0x21D4, 0xDB }, /* LEFT RIGHT DOUBLE ARROW # arrowdblboth */
+ { 0x2200, 0x22 }, /* FOR ALL # universal */
+ { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL # partialdiff */
+ { 0x2203, 0x24 }, /* THERE EXISTS # existential */
+ { 0x2205, 0xC6 }, /* EMPTY SET # emptyset */
+ { 0x2206, 0x44 }, /* INCREMENT # Delta */
+ { 0x2207, 0xD1 }, /* NABLA # gradient */
+ { 0x2208, 0xCE }, /* ELEMENT OF # element */
+ { 0x2209, 0xCF }, /* NOT AN ELEMENT OF # notelement */
+ { 0x220B, 0x27 }, /* CONTAINS AS MEMBER # suchthat */
+ { 0x220F, 0xD5 }, /* N-ARY PRODUCT # product */
+ { 0x2211, 0xE5 }, /* N-ARY SUMMATION # summation */
+ { 0x2212, 0x2D }, /* MINUS SIGN # minus */
+ { 0x2215, 0xA4 }, /* DIVISION SLASH # fraction */
+ { 0x2217, 0x2A }, /* ASTERISK OPERATOR # asteriskmath */
+ { 0x221A, 0xD6 }, /* SQUARE ROOT # radical */
+ { 0x221D, 0xB5 }, /* PROPORTIONAL TO # proportional */
+ { 0x221E, 0xA5 }, /* INFINITY # infinity */
+ { 0x2220, 0xD0 }, /* ANGLE # angle */
+ { 0x2227, 0xD9 }, /* LOGICAL AND # logicaland */
+ { 0x2228, 0xDA }, /* LOGICAL OR # logicalor */
+ { 0x2229, 0xC7 }, /* INTERSECTION # intersection */
+ { 0x222A, 0xC8 }, /* UNION # union */
+ { 0x222B, 0xF2 }, /* INTEGRAL # integral */
+ { 0x2234, 0x5C }, /* THEREFORE # therefore */
+ { 0x223C, 0x7E }, /* TILDE OPERATOR # similar */
+ { 0x2245, 0x40 }, /* APPROXIMATELY EQUAL TO # congruent */
+ { 0x2248, 0xBB }, /* ALMOST EQUAL TO # approxequal */
+ { 0x2260, 0xB9 }, /* NOT EQUAL TO # notequal */
+ { 0x2261, 0xBA }, /* IDENTICAL TO # equivalence */
+ { 0x2264, 0xA3 }, /* LESS-THAN OR EQUAL TO # lessequal */
+ { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO # greaterequal */
+ { 0x2282, 0xCC }, /* SUBSET OF # propersubset */
+ { 0x2283, 0xC9 }, /* SUPERSET OF # propersuperset */
+ { 0x2284, 0xCB }, /* NOT A SUBSET OF # notsubset */
+ { 0x2286, 0xCD }, /* SUBSET OF OR EQUAL TO # reflexsubset */
+ { 0x2287, 0xCA }, /* SUPERSET OF OR EQUAL TO # reflexsuperset */
+ { 0x2295, 0xC5 }, /* CIRCLED PLUS # circleplus */
+ { 0x2297, 0xC4 }, /* CIRCLED TIMES # circlemultiply */
+ { 0x22A5, 0x5E }, /* UP TACK # perpendicular */
+ { 0x22C5, 0xD7 }, /* DOT OPERATOR # dotmath */
+ { 0x2320, 0xF3 }, /* TOP HALF INTEGRAL # integraltp */
+ { 0x2321, 0xF5 }, /* BOTTOM HALF INTEGRAL # integralbt */
+ { 0x2329, 0xE1 }, /* LEFT-POINTING ANGLE BRACKET # angleleft */
+ { 0x232A, 0xF1 }, /* RIGHT-POINTING ANGLE BRACKET # angleright */
+ { 0x25CA, 0xE0 }, /* LOZENGE # lozenge */
+ { 0x2660, 0xAA }, /* BLACK SPADE SUIT # spade */
+ { 0x2663, 0xA7 }, /* BLACK CLUB SUIT # club */
+ { 0x2665, 0xA9 }, /* BLACK HEART SUIT # heart */
+ { 0x2666, 0xA8 }, /* BLACK DIAMOND SUIT # diamond */
+ { 0xF6D9, 0xD3 }, /* COPYRIGHT SIGN SERIF # copyrightserif (CUS) */
+ { 0xF6DA, 0xD2 }, /* REGISTERED SIGN SERIF # registerserif (CUS) */
+ { 0xF6DB, 0xD4 }, /* TRADE MARK SIGN SERIF # trademarkserif (CUS) */
+ { 0xF8E5, 0x60 }, /* RADICAL EXTENDER # radicalex (CUS) */
+ { 0xF8E6, 0xBD }, /* VERTICAL ARROW EXTENDER # arrowvertex (CUS) */
+ { 0xF8E7, 0xBE }, /* HORIZONTAL ARROW EXTENDER # arrowhorizex (CUS) */
+ { 0xF8E8, 0xE2 }, /* REGISTERED SIGN SANS SERIF # registersans (CUS) */
+ { 0xF8E9, 0xE3 }, /* COPYRIGHT SIGN SANS SERIF # copyrightsans (CUS) */
+ { 0xF8EA, 0xE4 }, /* TRADE MARK SIGN SANS SERIF # trademarksans (CUS) */
+ { 0xF8EB, 0xE6 }, /* LEFT PAREN TOP # parenlefttp (CUS) */
+ { 0xF8EC, 0xE7 }, /* LEFT PAREN EXTENDER # parenleftex (CUS) */
+ { 0xF8ED, 0xE8 }, /* LEFT PAREN BOTTOM # parenleftbt (CUS) */
+ { 0xF8EE, 0xE9 }, /* LEFT SQUARE BRACKET TOP # bracketlefttp (CUS) */
+ { 0xF8EF, 0xEA }, /* LEFT SQUARE BRACKET EXTENDER # bracketleftex (CUS) */
+ { 0xF8F0, 0xEB }, /* LEFT SQUARE BRACKET BOTTOM # bracketleftbt (CUS) */
+ { 0xF8F1, 0xEC }, /* LEFT CURLY BRACKET TOP # bracelefttp (CUS) */
+ { 0xF8F2, 0xED }, /* LEFT CURLY BRACKET MID # braceleftmid (CUS) */
+ { 0xF8F3, 0xEE }, /* LEFT CURLY BRACKET BOTTOM # braceleftbt (CUS) */
+ { 0xF8F4, 0xEF }, /* CURLY BRACKET EXTENDER # braceex (CUS) */
+ { 0xF8F5, 0xF4 }, /* INTEGRAL EXTENDER # integralex (CUS) */
+ { 0xF8F6, 0xF6 }, /* RIGHT PAREN TOP # parenrighttp (CUS) */
+ { 0xF8F7, 0xF7 }, /* RIGHT PAREN EXTENDER # parenrightex (CUS) */
+ { 0xF8F8, 0xF8 }, /* RIGHT PAREN BOTTOM # parenrightbt (CUS) */
+ { 0xF8F9, 0xF9 }, /* RIGHT SQUARE BRACKET TOP # bracketrighttp (CUS) */
+ { 0xF8FA, 0xFA }, /* RIGHT SQUARE BRACKET EXTENDER # bracketrightex (CUS) */
+ { 0xF8FB, 0xFB }, /* RIGHT SQUARE BRACKET BOTTOM # bracketrightbt (CUS) */
+ { 0xF8FC, 0xFC }, /* RIGHT CURLY BRACKET TOP # bracerighttp (CUS) */
+ { 0xF8FD, 0xFD }, /* RIGHT CURLY BRACKET MID # bracerightmid (CUS) */
+ { 0xF8FE, 0xFE }, /* RIGHT CURLY BRACKET BOTTOM # bracerightbt (CUS) */
+};
+
+static const FcCharMap AdobeSymbol = {
+ AdobeSymbolEnt,
+ sizeof (AdobeSymbolEnt) / sizeof (AdobeSymbolEnt[0]),
+};
+
+static const FcFontDecode fcFontDecoders[] = {
+ { ft_encoding_unicode, 0, (1 << 21) - 1 },
+ { ft_encoding_symbol, &AdobeSymbol, (1 << 16) - 1 },
+ { ft_encoding_apple_roman, &AppleRoman, (1 << 16) - 1 },
+};
+
+#define NUM_DECODE (sizeof (fcFontDecoders) / sizeof (fcFontDecoders[0]))
+
+static const FcChar32 prefer_unicode[] = {
+ 0x20ac, /* EURO SIGN */
+};
+
+#define NUM_PREFER_UNICODE (sizeof (prefer_unicode) / sizeof (prefer_unicode[0]))
+
+FcChar32
+FcFreeTypeUcs4ToPrivate (FcChar32 ucs4, const FcCharMap *map)
+{
+ int low, high, mid;
+ FcChar16 bmp;
+
+ low = 0;
+ high = map->nent - 1;
+ if (ucs4 < map->ent[low].bmp || map->ent[high].bmp < ucs4)
+ return ~0;
+ while (low <= high)
+ {
+ mid = (high + low) >> 1;
+ bmp = map->ent[mid].bmp;
+ if (ucs4 == bmp)
+ return (FT_ULong) map->ent[mid].encode;
+ if (ucs4 < bmp)
+ high = mid - 1;
+ else
+ low = mid + 1;
+ }
+ return ~0;
+}
+
+FcChar32
+FcFreeTypePrivateToUcs4 (FcChar32 private, const FcCharMap *map)
+{
+ int i;
+
+ for (i = 0; i < map->nent; i++)
+ if (map->ent[i].encode == private)
+ return (FcChar32) map->ent[i].bmp;
+ return ~0;
+}
+
+const FcCharMap *
+FcFreeTypeGetPrivateMap (FT_Encoding encoding)
+{
+ int i;
+
+ for (i = 0; i < NUM_DECODE; i++)
+ if (fcFontDecoders[i].encoding == encoding)
+ return fcFontDecoders[i].map;
+ return 0;
+}
+
+#include "../fc-glyphname/fcglyphname.h"
+
+static FcChar32
+FcHashGlyphName (const FcChar8 *name)
+{
+ FcChar32 h = 0;
+ FcChar8 c;
+
+ while ((c = *name++))
+ {
+ h = ((h << 1) | (h >> 31)) ^ c;
+ }
+ return h;
+}
+
+#if HAVE_FT_HAS_PS_GLYPH_NAMES
+/*
+ * Use Type1 glyph names for fonts which have reliable names
+ * and which export an Adobe Custom mapping
+ */
+static FcBool
+FcFreeTypeUseNames (FT_Face face)
+{
+ FT_Int map;
+
+ if (!FT_Has_PS_Glyph_Names (face))
+ return FcFalse;
+ for (map = 0; map < face->num_charmaps; map++)
+ if (face->charmaps[map]->encoding == ft_encoding_adobe_custom)
+ return FcTrue;
+ return FcFalse;
+}
+
+static FcChar8 *
+FcUcs4ToGlyphName (FcChar32 ucs4)
+{
+ int i = (int) (ucs4 % FC_GLYPHNAME_HASH);
+ int r = 0;
+ FcGlyphName *gn;
+
+ while ((gn = ucs_to_name[i]))
+ {
+ if (gn->ucs == ucs4)
+ return gn->name;
+ if (!r)
+ {
+ r = (int) (ucs4 % FC_GLYPHNAME_REHASH);
+ if (!r)
+ r = 1;
+ }
+ i += r;
+ if (i >= FC_GLYPHNAME_HASH)
+ i -= FC_GLYPHNAME_HASH;
+ }
+ return 0;
+}
+
+static FcChar32
+FcGlyphNameToUcs4 (FcChar8 *name)
+{
+ FcChar32 h = FcHashGlyphName (name);
+ int i = (int) (h % FC_GLYPHNAME_HASH);
+ int r = 0;
+ FcGlyphName *gn;
+
+ while ((gn = name_to_ucs[i]))
+ {
+ if (!strcmp ((char *) name, (char *) gn->name))
+ return gn->ucs;
+ if (!r)
+ {
+ r = (int) (h % FC_GLYPHNAME_REHASH);
+ if (!r)
+ r = 1;
+ }
+ i += r;
+ if (i >= FC_GLYPHNAME_HASH)
+ i -= FC_GLYPHNAME_HASH;
+ }
+ return 0xffff;
+}
+
+/*
+ * Search through a font for a glyph by name. This is
+ * currently a linear search as there doesn't appear to be
+ * any defined order within the font
+ */
+static FT_UInt
+FcFreeTypeGlyphNameIndex (FT_Face face, FcChar8 *name)
+{
+ FT_UInt gindex;
+ FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2];
+
+ for (gindex = 0; gindex < face->num_glyphs; gindex++)
+ {
+ if (FT_Get_Glyph_Name (face, gindex, name_buf, FC_GLYPHNAME_MAXLEN+1) == 0)
+ if (!strcmp ((char *) name, (char *) name_buf))
+ return gindex;
+ }
+ return 0;
+}
+#endif
+
+/*
+ * Map a UCS4 glyph to a glyph index. Use all available encoding
+ * tables to try and find one that works. This information is expected
+ * to be cached by higher levels, so performance isn't critical
+ */
+
+FT_UInt
+FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
+{
+ int initial, offset, decode;
+ FT_UInt glyphindex;
+ FcChar32 charcode;
+ int p;
+
+ initial = 0;
+ /*
+ * Find the current encoding
+ */
+ if (face->charmap)
+ {
+ for (; initial < NUM_DECODE; initial++)
+ if (fcFontDecoders[initial].encoding == face->charmap->encoding)
+ break;
+ if (initial == NUM_DECODE)
+ initial = 0;
+ }
+ for (p = 0; p < NUM_PREFER_UNICODE; p++)
+ if (ucs4 == prefer_unicode[p])
+ {
+ initial = 0;
+ break;
+ }
+ /*
+ * Check each encoding for the glyph, starting with the current one
+ */
+ for (offset = 0; offset < NUM_DECODE; offset++)
+ {
+ decode = (initial + offset) % NUM_DECODE;
+ if (!face->charmap || face->charmap->encoding != fcFontDecoders[decode].encoding)
+ if (FT_Select_Charmap (face, fcFontDecoders[decode].encoding) != 0)
+ continue;
+ if (fcFontDecoders[decode].map)
+ {
+ charcode = FcFreeTypeUcs4ToPrivate (ucs4, fcFontDecoders[decode].map);
+ if (charcode == ~0)
+ continue;
+ }
+ else
+ charcode = ucs4;
+ glyphindex = FT_Get_Char_Index (face, (FT_ULong) charcode);
+ if (glyphindex)
+ return glyphindex;
+ }
+#if HAVE_FT_HAS_PS_GLYPH_NAMES
+ /*
+ * Check postscript name table if present
+ */
+ if (FcFreeTypeUseNames (face))
+ {
+ FcChar8 *name = FcUcs4ToGlyphName (ucs4);
+ if (name)
+ {
+ glyphindex = FcFreeTypeGlyphNameIndex (face, name);
+ if (glyphindex)
+ return glyphindex;
+ }
+ }
+#endif
+ return 0;
+}
+
+static FcBool
+FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4,
+ FT_UInt glyph, FcBlanks *blanks,
+ FT_Pos *advance)
+{
+ FT_Int load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+ FT_GlyphSlot slot;
+
+ /*
+ * When using scalable fonts, only report those glyphs
+ * which can be scaled; otherwise those fonts will
+ * only be available at some sizes, and never when
+ * transformed. Avoid this by simply reporting bitmap-only
+ * glyphs as missing
+ */
+ if (face->face_flags & FT_FACE_FLAG_SCALABLE)
+ load_flags |= FT_LOAD_NO_BITMAP;
+
+ if (FT_Load_Glyph (face, glyph, load_flags))
+ return FcFalse;
+
+ slot = face->glyph;
+ if (!glyph)
+ return FcFalse;
+
+ *advance = slot->metrics.horiAdvance;
+
+ switch (slot->format) {
+ case ft_glyph_format_bitmap:
+ /*
+ * Bitmaps are assumed to be reasonable; if
+ * this proves to be a rash assumption, this
+ * code can be easily modified
+ */
+ return FcTrue;
+ case ft_glyph_format_outline:
+ /*
+ * Glyphs with contours are always OK
+ */
+ if (slot->outline.n_contours != 0)
+ return FcTrue;
+ /*
+ * Glyphs with no contours are only OK if
+ * they're members of the Blanks set specified
+ * in the configuration. If blanks isn't set,
+ * then allow any glyph to be blank
+ */
+ if (!blanks || FcBlanksIsMember (blanks, ucs4))
+ return FcTrue;
+ /* fall through ... */
+ default:
+ break;
+ }
+ return FcFalse;
+}
+
+#define FC_MIN(a,b) ((a) < (b) ? (a) : (b))
+#define FC_MAX(a,b) ((a) > (b) ? (a) : (b))
+#define FC_ABS(a) ((a) < 0 ? -(a) : (a))
+#define APPROXIMATELY_EQUAL(x,y) (FC_ABS ((x) - (y)) <= FC_MAX (FC_ABS (x), FC_ABS (y)) / 33)
+
+FcCharSet *
+FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
+{
+ FcChar32 page, off, max, ucs4;
+#ifdef CHECK
+ FcChar32 font_max = 0;
+#endif
+ FcCharSet *fcs;
+ FcCharLeaf *leaf;
+ const FcCharMap *map;
+ int o;
+ int i;
+ FT_UInt glyph;
+ FT_Pos advance, advance_one = 0, advance_two = 0;
+ FcBool has_advance = FcFalse, fixed_advance = FcTrue, dual_advance = FcFalse;
+
+ fcs = FcCharSetCreate ();
+ if (!fcs)
+ goto bail0;
+
+#ifdef CHECK
+ printf ("Family %s style %s\n", face->family_name, face->style_name);
+#endif
+ for (o = 0; o < NUM_DECODE; o++)
+ {
+ if (FT_Select_Charmap (face, fcFontDecoders[o].encoding) != 0)
+ continue;
+ map = fcFontDecoders[o].map;
+ if (map)
+ {
+ /*
+ * Non-Unicode tables are easy; there's a list of all possible
+ * characters
+ */
+ for (i = 0; i < map->nent; i++)
+ {
+ ucs4 = map->ent[i].bmp;
+ glyph = FT_Get_Char_Index (face, map->ent[i].encode);
+ if (glyph &&
+ FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
+ {
+ if (!has_advance)
+ {
+ has_advance = FcTrue;
+ advance_one = advance;
+ }
+ else if (!APPROXIMATELY_EQUAL (advance, advance_one))
+ {
+ if (fixed_advance)
+ {
+ dual_advance = FcTrue;
+ fixed_advance = FcFalse;
+ advance_two = advance;
+ }
+ else if (!APPROXIMATELY_EQUAL (advance, advance_two))
+ dual_advance = FcFalse;
+ }
+
+ leaf = FcCharSetFindLeafCreate (fcs, ucs4);
+ if (!leaf)
+ goto bail1;
+ leaf->map[(ucs4 & 0xff) >> 5] |= (1 << (ucs4 & 0x1f));
+#ifdef CHECK
+ if (ucs4 > font_max)
+ font_max = ucs4;
+#endif
+ }
+ }
+ }
+ else
+ {
+ FT_UInt gindex;
+
+ max = fcFontDecoders[o].max;
+ /*
+ * Find the first encoded character in the font
+ */
+ if (FT_Get_Char_Index (face, 0))
+ {
+ ucs4 = 0;
+ gindex = 1;
+ }
+ else
+ {
+ ucs4 = FT_Get_Next_Char (face, 0, &gindex);
+ if (!ucs4)
+ gindex = 0;
+ }
+
+ while (gindex)
+ {
+ page = ucs4 >> 8;
+ leaf = 0;
+ while ((ucs4 >> 8) == page)
+ {
+ glyph = FT_Get_Char_Index (face, ucs4);
+ if (glyph && FcFreeTypeCheckGlyph (face, ucs4,
+ glyph, blanks, &advance))
+ {
+ if (!has_advance)
+ {
+ has_advance = FcTrue;
+ advance_one = advance;
+ }
+ else if (!APPROXIMATELY_EQUAL (advance, advance_one))
+ {
+ if (fixed_advance)
+ {
+ dual_advance = FcTrue;
+ fixed_advance = FcFalse;
+ advance_two = advance;
+ }
+ else if (!APPROXIMATELY_EQUAL (advance, advance_two))
+ dual_advance = FcFalse;
+ }
+
+ if (!leaf)
+ {
+ leaf = FcCharSetFindLeafCreate (fcs, ucs4);
+ if (!leaf)
+ goto bail1;
+ }
+ off = ucs4 & 0xff;
+ leaf->map[off >> 5] |= (1 << (off & 0x1f));
+#ifdef CHECK
+ if (ucs4 > font_max)
+ font_max = ucs4;
+#endif
+ }
+ ucs4++;
+ }
+ ucs4 = FT_Get_Next_Char (face, ucs4 - 1, &gindex);
+ if (!ucs4)
+ gindex = 0;
+ }
+#ifdef CHECK
+ for (ucs4 = 0; ucs4 < 0x10000; ucs4++)
+ {
+ FcBool FT_Has, FC_Has;
+
+ FT_Has = FT_Get_Char_Index (face, ucs4) != 0;
+ FC_Has = FcCharSetHasChar (fcs, ucs4);
+ if (FT_Has != FC_Has)
+ {
+ printf ("0x%08x FT says %d FC says %d\n", ucs4, FT_Has, FC_Has);
+ }
+ }
+#endif
+ }
+ }
+#if HAVE_FT_HAS_PS_GLYPH_NAMES
+ /*
+ * Add mapping from PS glyph names if available
+ */
+ if (FcFreeTypeUseNames (face))
+ {
+ FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2];
+
+ for (glyph = 0; glyph < face->num_glyphs; glyph++)
+ {
+ if (FT_Get_Glyph_Name (face, glyph, name_buf, FC_GLYPHNAME_MAXLEN+1) == 0)
+ {
+ ucs4 = FcGlyphNameToUcs4 (name_buf);
+ if (ucs4 != 0xffff &&
+ FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
+ {
+ if (!has_advance)
+ {
+ has_advance = FcTrue;
+ advance_one = advance;
+ }
+ else if (!APPROXIMATELY_EQUAL (advance, advance_one))
+ {
+ if (fixed_advance)
+ {
+ dual_advance = FcTrue;
+ fixed_advance = FcFalse;
+ advance_two = advance;
+ }
+ else if (!APPROXIMATELY_EQUAL (advance, advance_two))
+ dual_advance = FcFalse;
+ }
+ leaf = FcCharSetFindLeafCreate (fcs, ucs4);
+ if (!leaf)
+ goto bail1;
+ leaf->map[(ucs4 & 0xff) >> 5] |= (1 << (ucs4 & 0x1f));
+#ifdef CHECK
+ if (ucs4 > font_max)
+ font_max = ucs4;
+#endif
+ }
+ }
+ }
+ }
+#endif
+#ifdef CHECK
+ printf ("%d glyphs %d encoded\n", (int) face->num_glyphs, FcCharSetCount (fcs));
+ for (ucs4 = 0; ucs4 <= font_max; ucs4++)
+ {
+ FcBool has_char = (glyph = FcFreeTypeCharIndex (face, ucs4)) != 0;
+ FcBool has_bit = FcCharSetHasChar (fcs, ucs4);
+
+ if (has_char && !has_bit)
+ {
+ if (!FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
+ printf ("Bitmap missing broken char 0x%x\n", ucs4);
+ else
+ printf ("Bitmap missing char 0x%x\n", ucs4);
+ }
+ else if (!has_char && has_bit)
+ printf ("Bitmap extra char 0x%x\n", ucs4);
+ }
+#endif
+ if (fixed_advance)
+ *spacing = FC_MONO;
+ else if (dual_advance && APPROXIMATELY_EQUAL (2 * FC_MIN (advance_one, advance_two), FC_MAX (advance_one, advance_two)))
+ *spacing = FC_DUAL;
+ else
+ *spacing = FC_PROPORTIONAL;
+ return fcs;
+bail1:
+ FcCharSetDestroy (fcs);
+bail0:
+ return 0;
+}
+
+FcCharSet *
+FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks)
+{
+ int spacing;
+
+ return FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
+}
+
+
+#define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' )
+#define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
+#define TTAG_SILF FT_MAKE_TAG( 'S', 'i', 'l', 'f')
+#define TT_Err_Ok FT_Err_Ok
+#define TT_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle
+#define TTO_Err_Empty_Script 0x1005
+#define TTO_Err_Invalid_SubTable 0x1001
+
+#define OTLAYOUT_HEAD "otlayout:"
+#define OTLAYOUT_HEAD_LEN 9
+#define OTLAYOUT_ID_LEN 4
+/* space + head + id */
+#define OTLAYOUT_LEN (1 + OTLAYOUT_HEAD_LEN + OTLAYOUT_ID_LEN)
+
+/*
+ * This is a bit generous; the registry has only lower case and space
+ * except for 'DFLT'.
+ */
+#define FcIsSpace(x) (040 == (x))
+#define FcIsValidScript(x) (FcIsLower(x) || FcIsUpper (x) || FcIsSpace(x))
+
+static void
+addtag(FcChar8 *complex, FT_ULong tag)
+{
+ FcChar8 tagstring[OTLAYOUT_ID_LEN + 1];
+
+ tagstring[0] = (FcChar8)(tag >> 24),
+ tagstring[1] = (FcChar8)(tag >> 16),
+ tagstring[2] = (FcChar8)(tag >> 8),
+ tagstring[3] = (FcChar8)(tag);
+ tagstring[4] = '\0';
+
+ /* skip tags which aren't alphabetic, under the assumption that
+ * they're probably broken
+ */
+ if (!FcIsValidScript(tagstring[0]) ||
+ !FcIsValidScript(tagstring[1]) ||
+ !FcIsValidScript(tagstring[2]) ||
+ !FcIsValidScript(tagstring[3]))
+ return;
+
+ if (*complex != '\0')
+ strcat (complex, " ");
+ strcat (complex, "otlayout:");
+ strcat (complex, tagstring);
+}
+
+static int
+compareulong (const void *a, const void *b)
+{
+ const FT_ULong *ua = (const FT_ULong *) a;
+ const FT_ULong *ub = (const FT_ULong *) b;
+ return *ua - *ub;
+}
+
+
+static FT_Error
+GetScriptTags(FT_Face face, FT_ULong tabletag, FT_ULong **stags, FT_UShort *script_count)
+{
+ FT_ULong cur_offset, new_offset, base_offset;
+ TT_Face tt_face = (TT_Face)face;
+ FT_Stream stream = face->stream;
+ FT_Error error;
+ FT_UShort n, p;
+ FT_Memory memory = stream->memory;
+
+ if ( !stream )
+ return TT_Err_Invalid_Face_Handle;
+
+ if (( error = tt_face->goto_table( tt_face, tabletag, stream, 0 ) ))
+ return error;
+
+ base_offset = FT_STREAM_POS();
+
+ /* skip version */
+
+ if ( FT_STREAM_SEEK( base_offset + 4L ) || FT_FRAME_ENTER( 2L ) )
+ return error;
+
+ new_offset = FT_GET_USHORT() + base_offset;
+
+ FT_FRAME_EXIT();
+
+ cur_offset = FT_STREAM_POS();
+
+ if ( FT_STREAM_SEEK( new_offset ) != TT_Err_Ok )
+ return error;
+
+ base_offset = FT_STREAM_POS();
+
+ if ( FT_FRAME_ENTER( 2L ) )
+ return error;
+
+ *script_count = FT_GET_USHORT();
+
+ FT_FRAME_EXIT();
+
+ if ( FT_SET_ERROR (FT_MEM_ALLOC_ARRAY( *stags, *script_count, FT_ULong )) )
+ return error;
+
+ p = 0;
+ for ( n = 0; n < *script_count; n++ )
+ {
+ if ( FT_FRAME_ENTER( 6L ) )
+ goto Fail;
+
+ (*stags)[p] = FT_GET_ULONG();
+ new_offset = FT_GET_USHORT() + base_offset;
+
+ FT_FRAME_EXIT();
+
+ cur_offset = FT_STREAM_POS();
+
+ if ( FT_STREAM_SEEK( new_offset ) )
+ goto Fail;
+
+ if ( error == TT_Err_Ok )
+ p++;
+ else if ( error != TTO_Err_Empty_Script )
+ goto Fail;
+
+ (void)FT_STREAM_SEEK( cur_offset );
+ }
+
+ if (!p)
+ {
+ error = TTO_Err_Invalid_SubTable;
+ goto Fail;
+ }
+
+ // sort the tag list before returning it
+ qsort(*stags, *script_count, sizeof(FT_ULong), compareulong);
+
+ return TT_Err_Ok;
+
+Fail:
+ *script_count = 0;
+ FT_FREE( *stags );
+ return error;
+}
+
+static FcChar8 *
+FcFontCapabilities(FT_Face face)
+{
+ FcBool issilgraphitefont = 0;
+ FT_Error err;
+ FT_ULong len = 0;
+ FT_ULong *gsubtags=NULL, *gpostags=NULL;
+ FT_UShort gsub_count=0, gpos_count=0;
+ FT_ULong maxsize;
+ FT_Memory memory = face->stream->memory;
+ FcChar8 *complex = NULL;
+ int indx1 = 0, indx2 = 0;
+
+ err = FT_Load_Sfnt_Table(face, TTAG_SILF, 0, 0, &len);
+ issilgraphitefont = ( err == FT_Err_Ok);
+
+ if (GetScriptTags(face, TTAG_GPOS, &gpostags, &gpos_count) != FT_Err_Ok)
+ gpos_count = 0;
+ if (GetScriptTags(face, TTAG_GSUB, &gsubtags, &gsub_count) != FT_Err_Ok)
+ gsub_count = 0;
+
+ if (!issilgraphitefont && !gsub_count && !gpos_count)
+ goto bail;
+
+ maxsize = (((FT_ULong) gpos_count + (FT_ULong) gsub_count) * OTLAYOUT_LEN +
+ (issilgraphitefont ? 13 : 0));
+ complex = malloc (sizeof (FcChar8) * maxsize);
+ if (!complex)
+ goto bail;
+
+ complex[0] = '\0';
+ if (issilgraphitefont)
+ strcpy(complex, "ttable:Silf ");
+
+ while ((indx1 < gsub_count) || (indx2 < gpos_count)) {
+ if (indx1 == gsub_count) {
+ addtag(complex, gpostags[indx2]);
+ indx2++;
+ } else if ((indx2 == gpos_count) || (gsubtags[indx1] < gpostags[indx2])) {
+ addtag(complex, gsubtags[indx1]);
+ indx1++;
+ } else if (gsubtags[indx1] == gpostags[indx2]) {
+ addtag(complex, gsubtags[indx1]);
+ indx1++;
+ indx2++;
+ } else {
+ addtag(complex, gpostags[indx2]);
+ indx2++;
+ }
+ }
+ if (FcDebug () & FC_DBG_SCANV)
+ printf("complex features in this font: %s\n", complex);
+bail:
+ FT_FREE(gsubtags);
+ FT_FREE(gpostags);
+ return complex;
+}
diff --git a/nx-X11/extras/fontconfig/src/fcfs.c b/nx-X11/extras/fontconfig/src/fcfs.c
new file mode 100644
index 000000000..b05688d97
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcfs.c
@@ -0,0 +1,82 @@
+/*
+ * $RCSId: $
+ *
+ * Copyright © 2000 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include "fcint.h"
+
+FcFontSet *
+FcFontSetCreate (void)
+{
+ FcFontSet *s;
+
+ s = (FcFontSet *) malloc (sizeof (FcFontSet));
+ if (!s)
+ return 0;
+ FcMemAlloc (FC_MEM_FONTSET, sizeof (FcFontSet));
+ s->nfont = 0;
+ s->sfont = 0;
+ s->fonts = 0;
+ return s;
+}
+
+void
+FcFontSetDestroy (FcFontSet *s)
+{
+ int i;
+
+ for (i = 0; i < s->nfont; i++)
+ FcPatternDestroy (s->fonts[i]);
+ if (s->fonts)
+ {
+ FcMemFree (FC_MEM_FONTPTR, s->sfont * sizeof (FcPattern *));
+ free (s->fonts);
+ }
+ FcMemFree (FC_MEM_FONTSET, sizeof (FcFontSet));
+ free (s);
+}
+
+FcBool
+FcFontSetAdd (FcFontSet *s, FcPattern *font)
+{
+ FcPattern **f;
+ int sfont;
+
+ if (s->nfont == s->sfont)
+ {
+ sfont = s->sfont + 32;
+ if (s->fonts)
+ f = (FcPattern **) realloc (s->fonts, sfont * sizeof (FcPattern *));
+ else
+ f = (FcPattern **) malloc (sfont * sizeof (FcPattern *));
+ if (!f)
+ return FcFalse;
+ if (s->sfont)
+ FcMemFree (FC_MEM_FONTPTR, s->sfont * sizeof (FcPattern *));
+ FcMemAlloc (FC_MEM_FONTPTR, sfont * sizeof (FcPattern *));
+ s->sfont = sfont;
+ s->fonts = f;
+ }
+ s->fonts[s->nfont++] = font;
+ return FcTrue;
+}
diff --git a/nx-X11/extras/fontconfig/src/fcinit.c b/nx-X11/extras/fontconfig/src/fcinit.c
new file mode 100644
index 000000000..c3f497bf6
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcinit.c
@@ -0,0 +1,265 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fcinit.c,v 1.7 2002/08/22 07:36:44 keithp Exp $
+ *
+ * Copyright © 2001 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include "fcint.h"
+
+static FcConfig *
+FcInitFallbackConfig (void)
+{
+ FcConfig *config;
+
+ config = FcConfigCreate ();
+ if (!config)
+ goto bail0;
+ if (!FcConfigAddDir (config, (FcChar8 *) FC_DEFAULT_FONTS))
+ goto bail1;
+ return config;
+
+bail1:
+ FcConfigDestroy (config);
+bail0:
+ return 0;
+}
+
+int
+FcGetVersion (void)
+{
+ return FC_VERSION;
+}
+
+/*
+ * Load the configuration files
+ */
+FcConfig *
+FcInitLoadConfig (void)
+{
+ FcConfig *config;
+
+ config = FcConfigCreate ();
+ if (!config)
+ return FcFalse;
+
+ if (!FcConfigParseAndLoad (config, 0, FcTrue))
+ {
+ FcConfigDestroy (config);
+ return FcInitFallbackConfig ();
+ }
+
+ return config;
+}
+
+/*
+ * Load the configuration files and scan for available fonts
+ */
+FcConfig *
+FcInitLoadConfigAndFonts (void)
+{
+ FcConfig *config = FcInitLoadConfig ();
+
+ if (!config)
+ return 0;
+ if (!FcConfigBuildFonts (config))
+ {
+ FcConfigDestroy (config);
+ return 0;
+ }
+ return config;
+}
+
+/*
+ * Initialize the default library configuration
+ */
+FcBool
+FcInit (void)
+{
+ FcConfig *config;
+
+ if (_fcConfig)
+ return FcTrue;
+ config = FcInitLoadConfigAndFonts ();
+ if (!config)
+ return FcTrue;
+ FcConfigSetCurrent (config);
+ if (FcDebug() & FC_DBG_MEMORY)
+ FcMemReport ();
+ return FcTrue;
+}
+
+/*
+ * Free all library-allocated data structures.
+ */
+void
+FcFini (void)
+{
+ if (_fcConfig)
+ FcConfigDestroy (_fcConfig);
+
+ FcPatternThawAll ();
+ FcCharSetThawAll ();
+}
+
+/*
+ * Reread the configuration and available font lists
+ */
+FcBool
+FcInitReinitialize (void)
+{
+ FcConfig *config;
+
+ config = FcInitLoadConfigAndFonts ();
+ if (!config)
+ return FcFalse;
+ FcConfigSetCurrent (config);
+ return FcTrue;
+}
+
+FcBool
+FcInitBringUptoDate (void)
+{
+ FcConfig *config = FcConfigGetCurrent ();
+ time_t now;
+
+ /*
+ * rescanInterval == 0 disables automatic up to date
+ */
+ if (config->rescanInterval == 0)
+ return FcTrue;
+ /*
+ * Check no more often than rescanInterval seconds
+ */
+ now = time (0);
+ if (config->rescanTime + config->rescanInterval - now > 0)
+ return FcTrue;
+ /*
+ * If up to date, don't reload configuration
+ */
+ if (FcConfigUptoDate (0))
+ return FcTrue;
+ return FcInitReinitialize ();
+}
+
+static struct {
+ char *name;
+ int alloc_count;
+ int alloc_mem;
+ int free_count;
+ int free_mem;
+} FcInUse[FC_MEM_NUM] = {
+ { "charset" },
+ { "charleaf" },
+ { "fontset" },
+ { "fontptr" },
+ { "objectset" },
+ { "objectptr" },
+ { "matrix" },
+ { "pattern" },
+ { "patelt" },
+ { "vallist" },
+ { "substate" },
+ { "string" },
+ { "listbuck" },
+ { "strset" },
+ { "strlist" },
+ { "config" },
+ { "langset" },
+ { "atomic" },
+ { "blanks" },
+ { "cache" },
+ { "strbuf" },
+ { "subst" },
+ { "objecttype" },
+ { "constant" },
+ { "test" },
+ { "expr" },
+ { "vstack" },
+ { "attr" },
+ { "pstack" },
+ { "staticstr" },
+};
+
+static int FcAllocCount, FcAllocMem;
+static int FcFreeCount, FcFreeMem;
+
+static int FcMemNotice = 1*1024*1024;
+
+static int FcAllocNotify, FcFreeNotify;
+
+void
+FcValueListReport (void);
+
+void
+FcMemReport (void)
+{
+ int i;
+ printf ("Fc Memory Usage:\n");
+ printf ("\t Which Alloc Free Active\n");
+ printf ("\t count bytes count bytes count bytes\n");
+ for (i = 0; i < FC_MEM_NUM; i++)
+ printf ("%16.16s%8d%8d%8d%8d%8d%8d\n",
+ FcInUse[i].name,
+ FcInUse[i].alloc_count, FcInUse[i].alloc_mem,
+ FcInUse[i].free_count, FcInUse[i].free_mem,
+ FcInUse[i].alloc_count - FcInUse[i].free_count,
+ FcInUse[i].alloc_mem - FcInUse[i].free_mem);
+ printf ("%16.16s%8d%8d%8d%8d%8d%8d\n",
+ "Total",
+ FcAllocCount, FcAllocMem,
+ FcFreeCount, FcFreeMem,
+ FcAllocCount - FcFreeCount,
+ FcAllocMem - FcFreeMem);
+ FcAllocNotify = 0;
+ FcFreeNotify = 0;
+ FcValueListReport ();
+}
+
+void
+FcMemAlloc (int kind, int size)
+{
+ if (FcDebug() & FC_DBG_MEMORY)
+ {
+ FcInUse[kind].alloc_count++;
+ FcInUse[kind].alloc_mem += size;
+ FcAllocCount++;
+ FcAllocMem += size;
+ FcAllocNotify += size;
+ if (FcAllocNotify > FcMemNotice)
+ FcMemReport ();
+ }
+}
+
+void
+FcMemFree (int kind, int size)
+{
+ if (FcDebug() & FC_DBG_MEMORY)
+ {
+ FcInUse[kind].free_count++;
+ FcInUse[kind].free_mem += size;
+ FcFreeCount++;
+ FcFreeMem += size;
+ FcFreeNotify += size;
+ if (FcFreeNotify > FcMemNotice)
+ FcMemReport ();
+ }
+}
diff --git a/nx-X11/extras/fontconfig/src/fcint.h b/nx-X11/extras/fontconfig/src/fcint.h
new file mode 100644
index 000000000..24bf246a5
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcint.h
@@ -0,0 +1,773 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fcint.h,v 1.27 2002/08/31 22:17:32 keithp Exp $
+ *
+ * Copyright © 2000 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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.
+ */
+
+#ifndef _FCINT_H_
+#define _FCINT_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <fontconfig/fontconfig.h>
+#include <fontconfig/fcprivate.h>
+#include <fontconfig/fcfreetype.h>
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+typedef struct _FcSymbolic {
+ const char *name;
+ int value;
+} FcSymbolic;
+
+#ifndef FC_CONFIG_PATH
+#define FC_CONFIG_PATH "fonts.conf"
+#endif
+
+#define FC_FONT_FILE_INVALID ((FcChar8 *) ".")
+#define FC_FONT_FILE_DIR ((FcChar8 *) ".dir")
+
+#ifdef _WIN32
+#define FC_SEARCH_PATH_SEPARATOR ';'
+#else
+#define FC_SEARCH_PATH_SEPARATOR ':'
+#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_MEMORY 512
+#define FC_DBG_CONFIG 1024
+
+#define FC_MEM_CHARSET 0
+#define FC_MEM_CHARLEAF 1
+#define FC_MEM_FONTSET 2
+#define FC_MEM_FONTPTR 3
+#define FC_MEM_OBJECTSET 4
+#define FC_MEM_OBJECTPTR 5
+#define FC_MEM_MATRIX 6
+#define FC_MEM_PATTERN 7
+#define FC_MEM_PATELT 8
+#define FC_MEM_VALLIST 9
+#define FC_MEM_SUBSTATE 10
+#define FC_MEM_STRING 11
+#define FC_MEM_LISTBUCK 12
+#define FC_MEM_STRSET 13
+#define FC_MEM_STRLIST 14
+#define FC_MEM_CONFIG 15
+#define FC_MEM_LANGSET 16
+#define FC_MEM_ATOMIC 17
+#define FC_MEM_BLANKS 18
+#define FC_MEM_CACHE 19
+#define FC_MEM_STRBUF 20
+#define FC_MEM_SUBST 21
+#define FC_MEM_OBJECTTYPE 22
+#define FC_MEM_CONSTANT 23
+#define FC_MEM_TEST 24
+#define FC_MEM_EXPR 25
+#define FC_MEM_VSTACK 26
+#define FC_MEM_ATTR 27
+#define FC_MEM_PSTACK 28
+#define FC_MEM_STATICSTR 29
+
+#define FC_MEM_NUM 30
+
+typedef enum _FcValueBinding {
+ FcValueBindingWeak, FcValueBindingStrong, FcValueBindingSame
+} FcValueBinding;
+
+typedef struct _FcValueList {
+ struct _FcValueList *next;
+ FcValue value;
+ FcValueBinding binding;
+} FcValueList;
+
+typedef struct _FcPatternElt {
+ const char *object;
+ FcValueList *values;
+} FcPatternElt;
+
+
+struct _FcPattern {
+ int num;
+ int size;
+ FcPatternElt *elts;
+ int ref;
+};
+
+typedef enum _FcOp {
+ FcOpInteger, FcOpDouble, FcOpString, FcOpMatrix, FcOpBool, FcOpCharSet,
+ FcOpNil,
+ FcOpField, FcOpConst,
+ FcOpAssign, FcOpAssignReplace,
+ FcOpPrependFirst, FcOpPrepend, FcOpAppend, FcOpAppendLast,
+ FcOpQuest,
+ FcOpOr, FcOpAnd, FcOpEqual, FcOpNotEqual,
+ FcOpContains, FcOpListing, FcOpNotContains,
+ FcOpLess, FcOpLessEqual, FcOpMore, FcOpMoreEqual,
+ FcOpPlus, FcOpMinus, FcOpTimes, FcOpDivide,
+ FcOpNot, FcOpComma, FcOpFloor, FcOpCeil, FcOpRound, FcOpTrunc,
+ FcOpInvalid
+} FcOp;
+
+typedef struct _FcExpr {
+ FcOp op;
+ union {
+ int ival;
+ double dval;
+ FcChar8 *sval;
+ FcMatrix *mval;
+ FcBool bval;
+ FcCharSet *cval;
+ char *field;
+ FcChar8 *constant;
+ struct {
+ struct _FcExpr *left, *right;
+ } tree;
+ } u;
+} FcExpr;
+
+typedef enum _FcQual {
+ FcQualAny, FcQualAll, FcQualFirst, FcQualNotFirst
+} FcQual;
+
+#define FcMatchDefault ((FcMatchKind) -1)
+
+typedef struct _FcTest {
+ struct _FcTest *next;
+ FcMatchKind kind;
+ FcQual qual;
+ const char *field;
+ FcOp op;
+ FcExpr *expr;
+} FcTest;
+
+typedef struct _FcEdit {
+ struct _FcEdit *next;
+ const char *field;
+ FcOp op;
+ FcExpr *expr;
+ FcValueBinding binding;
+} FcEdit;
+
+typedef struct _FcSubst {
+ struct _FcSubst *next;
+ FcTest *test;
+ FcEdit *edit;
+} FcSubst;
+
+typedef struct _FcCharLeaf {
+ FcChar32 map[256/32];
+} FcCharLeaf;
+
+#define FC_REF_CONSTANT -1
+
+struct _FcCharSet {
+ int ref; /* reference count */
+ int num; /* size of leaves and numbers arrays */
+ FcCharLeaf **leaves;
+ FcChar16 *numbers;
+};
+
+struct _FcStrSet {
+ int ref; /* reference count */
+ int num;
+ int size;
+ FcChar8 **strs;
+};
+
+struct _FcStrList {
+ FcStrSet *set;
+ int n;
+};
+
+typedef struct _FcStrBuf {
+ FcChar8 *buf;
+ FcBool allocated;
+ FcBool failed;
+ int len;
+ int size;
+} FcStrBuf;
+
+/*
+ * To map adobe glyph names to unicode values, a precomputed hash
+ * table is used
+ */
+
+typedef struct _FcGlyphName {
+ FcChar32 ucs; /* unicode value */
+ FcChar8 name[1]; /* name extends beyond struct */
+} FcGlyphName;
+
+/*
+ * To perform case-insensitive string comparisons, a table
+ * is used which holds three different kinds of folding data.
+ *
+ * The first is a range of upper case values mapping to a range
+ * of their lower case equivalents. Within each range, the offset
+ * between upper and lower case is constant.
+ *
+ * The second is a range of upper case values which are interleaved
+ * with their lower case equivalents.
+ *
+ * The third is a set of raw unicode values mapping to a list
+ * of unicode values for comparison purposes. This allows conversion
+ * of ß to "ss" so that SS, ss and ß all match. A separate array
+ * holds the list of unicode values for each entry.
+ *
+ * These are packed into a single table. Using a binary search,
+ * the appropriate entry can be located.
+ */
+
+#define FC_CASE_FOLD_RANGE 0
+#define FC_CASE_FOLD_EVEN_ODD 1
+#define FC_CASE_FOLD_FULL 2
+
+typedef struct _FcCaseFold {
+ FcChar32 upper;
+ FcChar16 method : 2;
+ FcChar16 count : 14;
+ short offset; /* lower - upper for RANGE, table id for FULL */
+} FcCaseFold;
+
+#define FC_MAX_FILE_LEN 4096
+
+/*
+ * The per-user ~/.fonts.cache-<version> file is loaded into
+ * this data structure. Each directory gets a substructure
+ * which is validated by comparing the directory timestamp with
+ * that saved in the cache. When valid, the entire directory cache
+ * can be immediately loaded without reading the directory. Otherwise,
+ * the files are checked individually; updated files are loaded into the
+ * cache which is then rewritten to the users home directory
+ */
+
+#define FC_GLOBAL_CACHE_DIR_HASH_SIZE 37
+#define FC_GLOBAL_CACHE_FILE_HASH_SIZE 67
+
+typedef struct _FcGlobalCacheInfo {
+ unsigned int hash;
+ FcChar8 *file;
+ time_t time;
+ FcBool referenced;
+} FcGlobalCacheInfo;
+
+typedef struct _FcGlobalCacheFile {
+ struct _FcGlobalCacheFile *next;
+ FcGlobalCacheInfo info;
+ int id;
+ FcChar8 *name;
+} FcGlobalCacheFile;
+
+typedef struct _FcGlobalCacheDir FcGlobalCacheDir;
+
+typedef struct _FcGlobalCacheSubdir {
+ struct _FcGlobalCacheSubdir *next;
+ FcGlobalCacheDir *ent;
+} FcGlobalCacheSubdir;
+
+struct _FcGlobalCacheDir {
+ struct _FcGlobalCacheDir *next;
+ FcGlobalCacheInfo info;
+ int len;
+ FcGlobalCacheFile *ents[FC_GLOBAL_CACHE_FILE_HASH_SIZE];
+ FcGlobalCacheSubdir *subdirs;
+};
+
+typedef struct _FcGlobalCache {
+ FcGlobalCacheDir *ents[FC_GLOBAL_CACHE_DIR_HASH_SIZE];
+ FcBool updated;
+ FcBool broken;
+ int entries;
+ int referenced;
+} FcGlobalCache;
+
+struct _FcAtomic {
+ FcChar8 *file; /* original file name */
+ FcChar8 *new; /* temp file name -- write data here */
+ FcChar8 *lck; /* lockfile name (used for locking) */
+ FcChar8 *tmp; /* tmpfile name (used for locking) */
+};
+
+struct _FcBlanks {
+ int nblank;
+ int sblank;
+ FcChar32 *blanks;
+};
+
+struct _FcConfig {
+ /*
+ * File names loaded from the configuration -- saved here as the
+ * cache file must be consulted before the directories are scanned,
+ * and those directives may occur in any order
+ */
+ FcStrSet *configDirs; /* directories to scan for fonts */
+ FcChar8 *cache; /* name of per-user cache file */
+ /*
+ * Set of allowed blank chars -- used to
+ * trim fonts of bogus glyphs
+ */
+ FcBlanks *blanks;
+ /*
+ * List of directories containing fonts,
+ * built by recursively scanning the set
+ * of configured directories
+ */
+ FcStrSet *fontDirs;
+ /*
+ * Names of all of the configuration files used
+ * to create this configuration
+ */
+ FcStrSet *configFiles; /* config files loaded */
+ /*
+ * Substitution instructions for patterns and fonts;
+ * maxObjects is used to allocate appropriate intermediate storage
+ * while performing a whole set of substitutions
+ */
+ FcSubst *substPattern; /* substitutions for patterns */
+ FcSubst *substFont; /* substitutions for fonts */
+ int maxObjects; /* maximum number of tests in all substs */
+ /*
+ * List of patterns used to control font file selection
+ */
+ FcStrSet *acceptGlobs;
+ FcStrSet *rejectGlobs;
+ FcFontSet *acceptPatterns;
+ FcFontSet *rejectPatterns;
+ /*
+ * The set of fonts loaded from the listed directories; the
+ * order within the set does not determine the font selection,
+ * except in the case of identical matches in which case earlier fonts
+ * match preferrentially
+ */
+ FcFontSet *fonts[FcSetApplication + 1];
+ /*
+ * Fontconfig can periodically rescan the system configuration
+ * and font directories. This rescanning occurs when font
+ * listing requests are made, but no more often than rescanInterval
+ * seconds apart.
+ */
+ time_t rescanTime; /* last time information was scanned */
+ int rescanInterval; /* interval between scans */
+};
+
+extern FcConfig *_fcConfig;
+
+typedef struct _FcCharMap FcCharMap;
+
+/* fcblanks.c */
+
+/* fccache.c */
+
+FcGlobalCache *
+FcGlobalCacheCreate (void);
+
+void
+FcGlobalCacheDestroy (FcGlobalCache *cache);
+
+FcBool
+FcGlobalCacheCheckTime (const FcChar8*file, FcGlobalCacheInfo *info);
+
+void
+FcGlobalCacheReferenced (FcGlobalCache *cache,
+ FcGlobalCacheInfo *info);
+
+void
+FcGlobalCacheReferenceSubdir (FcGlobalCache *cache,
+ const FcChar8 *dir);
+
+FcGlobalCacheDir *
+FcGlobalCacheDirGet (FcGlobalCache *cache,
+ const FcChar8 *dir,
+ int len,
+ FcBool create_missing);
+
+FcBool
+FcGlobalCacheScanDir (FcFontSet *set,
+ FcStrSet *dirs,
+ FcGlobalCache *cache,
+ const FcChar8 *dir,
+ FcConfig *config);
+
+FcGlobalCacheFile *
+FcGlobalCacheFileGet (FcGlobalCache *cache,
+ const FcChar8 *file,
+ int id,
+ int *count);
+
+
+void
+FcGlobalCacheLoad (FcGlobalCache *cache,
+ const FcChar8 *cache_file);
+
+FcBool
+FcGlobalCacheUpdate (FcGlobalCache *cache,
+ const FcChar8 *file,
+ int id,
+ const FcChar8 *name);
+
+FcBool
+FcGlobalCacheSave (FcGlobalCache *cache,
+ const FcChar8 *cache_file);
+
+FcBool
+FcDirCacheReadDir (FcFontSet *set,
+ FcStrSet *dirs,
+ const FcChar8 *dir,
+ FcConfig *config);
+
+FcBool
+FcDirCacheWriteDir (FcFontSet *set, FcStrSet *dirs, const FcChar8 *dir);
+
+/* fccfg.c */
+
+FcBool
+FcConfigAddConfigDir (FcConfig *config,
+ const FcChar8 *d);
+
+FcBool
+FcConfigAddFontDir (FcConfig *config,
+ const FcChar8 *d);
+
+FcBool
+FcConfigAddDir (FcConfig *config,
+ const FcChar8 *d);
+
+FcBool
+FcConfigAddConfigFile (FcConfig *config,
+ const FcChar8 *f);
+
+FcBool
+FcConfigSetCache (FcConfig *config,
+ const FcChar8 *c);
+
+FcBool
+FcConfigAddBlank (FcConfig *config,
+ FcChar32 blank);
+
+FcBool
+FcConfigAddEdit (FcConfig *config,
+ FcTest *test,
+ FcEdit *edit,
+ FcMatchKind kind);
+
+void
+FcConfigSetFonts (FcConfig *config,
+ FcFontSet *fonts,
+ FcSetName set);
+
+FcBool
+FcConfigCompareValue (const FcValue m,
+ FcOp op,
+ const FcValue v);
+
+FcBool
+FcConfigGlobAdd (FcConfig *config,
+ const FcChar8 *glob,
+ FcBool accept);
+
+FcBool
+FcConfigAcceptFilename (FcConfig *config,
+ const FcChar8 *filename);
+
+FcBool
+FcConfigPatternsAdd (FcConfig *config,
+ FcPattern *pattern,
+ FcBool accept);
+
+FcBool
+FcConfigAcceptFont (FcConfig *config,
+ const FcPattern *font);
+
+/* fccharset.c */
+FcCharSet *
+FcCharSetFreeze (FcCharSet *cs);
+
+void
+FcCharSetThawAll (void);
+
+FcBool
+FcNameUnparseCharSet (FcStrBuf *buf, const FcCharSet *c);
+
+FcCharSet *
+FcNameParseCharSet (FcChar8 *string);
+
+FcCharLeaf *
+FcCharSetFindLeafCreate (FcCharSet *fcs, FcChar32 ucs4);
+
+/* fcdbg.c */
+void
+FcValueListPrint (const FcValueList *l);
+
+void
+FcLangSetPrint (const FcLangSet *ls);
+
+void
+FcOpPrint (FcOp op);
+
+void
+FcTestPrint (const FcTest *test);
+
+void
+FcExprPrint (const FcExpr *expr);
+
+void
+FcEditPrint (const FcEdit *edit);
+
+void
+FcSubstPrint (const FcSubst *subst);
+
+int
+FcDebug (void);
+
+/* fcdir.c */
+
+FcBool
+FcFileIsDir (const FcChar8 *file);
+
+FcBool
+FcFileScanConfig (FcFontSet *set,
+ FcStrSet *dirs,
+ FcFileCache *cache,
+ FcBlanks *blanks,
+ const FcChar8 *file,
+ FcBool force,
+ FcConfig *config);
+
+FcBool
+FcDirScanConfig (FcFontSet *set,
+ FcStrSet *dirs,
+ FcFileCache *cache,
+ FcBlanks *blanks,
+ const FcChar8 *dir,
+ FcBool force,
+ FcConfig *config);
+
+/* fcfont.c */
+int
+FcFontDebug (void);
+
+/* fcfreetype.c */
+FcBool
+FcFreeTypeIsExclusiveLang (const FcChar8 *lang);
+
+FcBool
+FcFreeTypeHasLang (FcPattern *pattern, const FcChar8 *lang);
+
+FcChar32
+FcFreeTypeUcs4ToPrivate (FcChar32 ucs4, const FcCharMap *map);
+
+FcChar32
+FcFreeTypePrivateToUcs4 (FcChar32 private, const FcCharMap *map);
+
+const FcCharMap *
+FcFreeTypeGetPrivateMap (FT_Encoding encoding);
+
+/* fcfs.c */
+/* fcgram.y */
+int
+FcConfigparse (void);
+
+int
+FcConfigwrap (void);
+
+void
+FcConfigerror (char *fmt, ...);
+
+char *
+FcConfigSaveField (const char *field);
+
+void
+FcTestDestroy (FcTest *test);
+
+FcExpr *
+FcExprCreateInteger (int i);
+
+FcExpr *
+FcExprCreateDouble (double d);
+
+FcExpr *
+FcExprCreateString (const FcChar8 *s);
+
+FcExpr *
+FcExprCreateMatrix (const FcMatrix *m);
+
+FcExpr *
+FcExprCreateBool (FcBool b);
+
+FcExpr *
+FcExprCreateNil (void);
+
+FcExpr *
+FcExprCreateField (const char *field);
+
+FcExpr *
+FcExprCreateConst (const FcChar8 *constant);
+
+FcExpr *
+FcExprCreateOp (FcExpr *left, FcOp op, FcExpr *right);
+
+void
+FcExprDestroy (FcExpr *e);
+
+void
+FcEditDestroy (FcEdit *e);
+
+/* fcinit.c */
+
+void
+FcMemReport (void);
+
+void
+FcMemAlloc (int kind, int size);
+
+void
+FcMemFree (int kind, int size);
+
+/* fclang.c */
+FcLangSet *
+FcFreeTypeLangSet (const FcCharSet *charset,
+ const FcChar8 *exclusiveLang);
+
+FcLangResult
+FcLangCompare (const FcChar8 *s1, const FcChar8 *s2);
+
+const FcCharSet *
+FcCharSetForLang (const FcChar8 *lang);
+
+FcLangSet *
+FcLangSetPromote (const FcChar8 *lang);
+
+FcLangSet *
+FcNameParseLangSet (const FcChar8 *string);
+
+FcBool
+FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls);
+
+/* fclist.c */
+
+FcBool
+FcListPatternMatchAny (const FcPattern *p,
+ const FcPattern *font);
+
+/* fcmatch.c */
+
+/* fcname.c */
+
+FcBool
+FcNameBool (const FcChar8 *v, FcBool *result);
+
+/* fcpat.c */
+void
+FcValueListDestroy (FcValueList *l);
+
+FcPatternElt *
+FcPatternFindElt (const FcPattern *p, const char *object);
+
+FcPatternElt *
+FcPatternInsertElt (FcPattern *p, const char *object);
+
+FcBool
+FcPatternAddWithBinding (FcPattern *p,
+ const char *object,
+ FcValue value,
+ FcValueBinding binding,
+ FcBool append);
+
+FcPattern *
+FcPatternFreeze (FcPattern *p);
+
+void
+FcPatternThawAll (void);
+
+FcBool
+FcPatternAppend (FcPattern *p, FcPattern *s);
+
+const char *
+FcObjectStaticName (const char *name);
+
+/* fcrender.c */
+
+/* fcmatrix.c */
+
+extern const FcMatrix FcIdentityMatrix;
+
+void
+FcMatrixFree (FcMatrix *mat);
+
+/* fcstr.c */
+FcChar8 *
+FcStrPlus (const FcChar8 *s1, const FcChar8 *s2);
+
+void
+FcStrFree (FcChar8 *s);
+
+void
+FcStrBufInit (FcStrBuf *buf, FcChar8 *init, int size);
+
+void
+FcStrBufDestroy (FcStrBuf *buf);
+
+FcChar8 *
+FcStrBufDone (FcStrBuf *buf);
+
+FcBool
+FcStrBufChar (FcStrBuf *buf, FcChar8 c);
+
+FcBool
+FcStrBufString (FcStrBuf *buf, const FcChar8 *s);
+
+FcBool
+FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len);
+
+int
+FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2);
+
+const FcChar8 *
+FcStrContainsIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2);
+
+const FcChar8 *
+FcStrContainsIgnoreCase (const FcChar8 *s1, const FcChar8 *s2);
+
+FcBool
+FcStrUsesHome (const FcChar8 *s);
+
+FcChar8 *
+FcStrLastSlash (const FcChar8 *path);
+
+FcChar32
+FcStrHashIgnoreCase (const FcChar8 *s);
+
+#endif /* _FC_INT_H_ */
diff --git a/nx-X11/extras/fontconfig/src/fclang.c b/nx-X11/extras/fontconfig/src/fclang.c
new file mode 100644
index 000000000..fabf36a15
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fclang.c
@@ -0,0 +1,686 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fclang.c,v 1.7 2002/08/26 23:34:31 keithp Exp $
+ *
+ * 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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"
+
+typedef struct {
+ FcChar8 *lang;
+ FcCharSet charset;
+} FcLangCharSet;
+
+typedef struct {
+ int begin;
+ int end;
+} FcLangCharSetRange;
+
+#include "../fc-lang/fclang.h"
+
+struct _FcLangSet {
+ FcChar32 map[NUM_LANG_SET_MAP];
+ FcStrSet *extra;
+};
+
+#define FcLangSetBitSet(ls, id) ((ls)->map[(id)>>5] |= ((FcChar32) 1 << ((id) & 0x1f)))
+#define FcLangSetBitGet(ls, id) (((ls)->map[(id)>>5] >> ((id) & 0x1f)) & 1)
+
+FcLangSet *
+FcFreeTypeLangSet (const FcCharSet *charset,
+ const FcChar8 *exclusiveLang)
+{
+ int i;
+ FcChar32 missing;
+ const FcCharSet *exclusiveCharset = 0;
+ FcLangSet *ls;
+
+
+ if (exclusiveLang)
+ exclusiveCharset = FcCharSetForLang (exclusiveLang);
+ ls = FcLangSetCreate ();
+ if (!ls)
+ return 0;
+ for (i = 0; i < NUM_LANG_CHAR_SET; i++)
+ {
+ /*
+ * 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) &&
+ fcLangCharSets[i].charset.leaves != exclusiveCharset->leaves)
+ {
+ continue;
+ }
+ missing = FcCharSetSubtractCount (&fcLangCharSets[i].charset, charset);
+ if (FcDebug() & FC_DBG_SCANV)
+ {
+ if (missing && missing < 10)
+ {
+ FcCharSet *missed = FcCharSetSubtract (&fcLangCharSets[i].charset,
+ charset);
+ FcChar32 ucs4;
+ FcChar32 map[FC_CHARSET_MAP_SIZE];
+ FcChar32 next;
+
+ printf ("\n%s(%d) ", fcLangCharSets[i].lang, 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(%d) ", fcLangCharSets[i].lang, missing);
+ }
+ if (!missing)
+ FcLangSetBitSet (ls, i);
+ }
+
+ if (FcDebug() & FC_DBG_SCANV)
+ printf ("\n");
+
+
+ return ls;
+}
+
+#define FcLangEnd(c) ((c) == '-' || (c) == '\0')
+
+FcLangResult
+FcLangCompare (const FcChar8 *s1, const FcChar8 *s2)
+{
+ FcChar8 c1, c2;
+ FcLangResult result = FcLangDifferentLang;
+
+ for (;;)
+ {
+ c1 = *s1++;
+ c2 = *s2++;
+
+ c1 = FcToLower (c1);
+ c2 = FcToLower (c2);
+ if (c1 != c2)
+ {
+ if (FcLangEnd (c1) && FcLangEnd (c2))
+ result = FcLangDifferentCountry;
+ return result;
+ }
+ else if (!c1)
+ return FcLangEqual;
+ else if (c1 == '-')
+ result = FcLangDifferentCountry;
+ }
+}
+
+/*
+ * Return FcTrue when super contains sub.
+ *
+ * super contains sub if super and sub have the same
+ * language and either the same country or one
+ * is missing the country
+ */
+
+static FcBool
+FcLangContains (const FcChar8 *super, const FcChar8 *sub)
+{
+ FcChar8 c1, c2;
+
+ for (;;)
+ {
+ c1 = *super++;
+ c2 = *sub++;
+
+ c1 = FcToLower (c1);
+ c2 = FcToLower (c2);
+ if (c1 != c2)
+ {
+ /* see if super has a country while sub is mising one */
+ if (c1 == '-' && c2 == '\0')
+ return FcTrue;
+ /* see if sub has a country while super is mising one */
+ if (c1 == '\0' && c2 == '-')
+ return FcTrue;
+ return FcFalse;
+ }
+ else if (!c1)
+ return FcTrue;
+ }
+}
+
+const FcCharSet *
+FcCharSetForLang (const FcChar8 *lang)
+{
+ int i;
+ int country = -1;
+ for (i = 0; i < NUM_LANG_CHAR_SET; i++)
+ {
+ switch (FcLangCompare (lang, fcLangCharSets[i].lang)) {
+ case FcLangEqual:
+ return &fcLangCharSets[i].charset;
+ case FcLangDifferentCountry:
+ if (country == -1)
+ country = i;
+ default:
+ break;
+ }
+ }
+ if (country == -1)
+ return 0;
+ return &fcLangCharSets[i].charset;
+}
+
+FcLangSet *
+FcLangSetCreate (void)
+{
+ FcLangSet *ls;
+
+ ls = malloc (sizeof (FcLangSet));
+ if (!ls)
+ return 0;
+ FcMemAlloc (FC_MEM_LANGSET, sizeof (FcLangSet));
+ memset (ls->map, '\0', sizeof (ls->map));
+ ls->extra = 0;
+ return ls;
+}
+
+void
+FcLangSetDestroy (FcLangSet *ls)
+{
+ if (ls->extra)
+ FcStrSetDestroy (ls->extra);
+ FcMemFree (FC_MEM_LANGSET, sizeof (FcLangSet));
+ free (ls);
+}
+
+FcLangSet *
+FcLangSetCopy (const FcLangSet *ls)
+{
+ FcLangSet *new;
+
+ new = FcLangSetCreate ();
+ if (!new)
+ goto bail0;
+ memcpy (new->map, ls->map, sizeof (new->map));
+ if (ls->extra)
+ {
+ FcStrList *list;
+ FcChar8 *extra;
+
+ new->extra = FcStrSetCreate ();
+ if (!new->extra)
+ goto bail1;
+
+ list = FcStrListCreate (ls->extra);
+ if (!list)
+ goto bail1;
+
+ while ((extra = FcStrListNext (list)))
+ if (!FcStrSetAdd (new->extra, extra))
+ {
+ FcStrListDone (list);
+ goto bail1;
+ }
+ FcStrListDone (list);
+ }
+ return new;
+bail1:
+ FcLangSetDestroy (new);
+bail0:
+ return 0;
+}
+
+static int
+FcLangSetIndex (const FcChar8 *lang)
+{
+ int low, high, mid = 0;
+ int cmp = 0;
+ FcChar8 firstChar = FcToLower(lang[0]);
+ FcChar8 secondChar = firstChar ? FcToLower(lang[1]) : '\0';
+
+ if (firstChar < 'a')
+ {
+ low = 0;
+ high = fcLangCharSetRanges[0].begin;
+ }
+ else if(firstChar > 'z')
+ {
+ low = fcLangCharSetRanges[25].begin;
+ high = NUM_LANG_CHAR_SET - 1;
+ }
+ else
+ {
+ low = fcLangCharSetRanges[firstChar - 'a'].begin;
+ high = fcLangCharSetRanges[firstChar - 'a'].end;
+ /* no matches */
+ if (low > high)
+ return -low; /* next entry after where it would be */
+ }
+
+ while (low <= high)
+ {
+ mid = (high + low) >> 1;
+ if(fcLangCharSets[mid].lang[0] != firstChar)
+ cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang, lang);
+ else
+ { /* fast path for resolving 2-letter languages (by far the most common) after
+ * finding the first char (probably already true because of the hash table) */
+ cmp = fcLangCharSets[mid].lang[1] - secondChar;
+ if (cmp == 0 &&
+ (fcLangCharSets[mid].lang[2] != '\0' ||
+ lang[2] != '\0'))
+ {
+ cmp = FcStrCmpIgnoreCase(fcLangCharSets[mid].lang+2,
+ lang+2);
+ }
+ }
+ if (cmp == 0)
+ return mid;
+ if (cmp < 0)
+ low = mid + 1;
+ else
+ high = mid - 1;
+ }
+ if (cmp < 0)
+ mid++;
+ return -(mid + 1);
+}
+
+FcBool
+FcLangSetAdd (FcLangSet *ls, const FcChar8 *lang)
+{
+ int id;
+
+ id = FcLangSetIndex (lang);
+ if (id >= 0)
+ {
+ FcLangSetBitSet (ls, id);
+ return FcTrue;
+ }
+ if (!ls->extra)
+ {
+ ls->extra = FcStrSetCreate ();
+ if (!ls->extra)
+ return FcFalse;
+ }
+ return FcStrSetAdd (ls->extra, lang);
+}
+
+FcLangResult
+FcLangSetHasLang (const FcLangSet *ls, const FcChar8 *lang)
+{
+ int id;
+ FcLangResult best, r;
+ int i;
+
+ id = FcLangSetIndex (lang);
+ if (id < 0)
+ id = -id - 1;
+ else if (FcLangSetBitGet (ls, id))
+ return FcLangEqual;
+ best = FcLangDifferentLang;
+ for (i = id - 1; i >= 0; i--)
+ {
+ r = FcLangCompare (lang, fcLangCharSets[i].lang);
+ if (r == FcLangDifferentLang)
+ break;
+ if (FcLangSetBitGet (ls, i) && r < best)
+ best = r;
+ }
+ for (i = id; i < NUM_LANG_CHAR_SET; i++)
+ {
+ r = FcLangCompare (lang, fcLangCharSets[i].lang);
+ if (r == FcLangDifferentLang)
+ break;
+ if (FcLangSetBitGet (ls, i) && r < best)
+ best = r;
+ }
+ if (ls->extra)
+ {
+ FcStrList *list = FcStrListCreate (ls->extra);
+ FcChar8 *extra;
+ FcLangResult r;
+
+ if (list)
+ {
+ while (best > FcLangEqual && (extra = FcStrListNext (list)))
+ {
+ r = FcLangCompare (lang, extra);
+ if (r < best)
+ best = r;
+ }
+ FcStrListDone (list);
+ }
+ }
+ return best;
+}
+
+static FcLangResult
+FcLangSetCompareStrSet (const FcLangSet *ls, FcStrSet *set)
+{
+ FcStrList *list = FcStrListCreate (set);
+ FcLangResult r, best = FcLangDifferentLang;
+ FcChar8 *extra;
+
+ if (list)
+ {
+ while (best > FcLangEqual && (extra = FcStrListNext (list)))
+ {
+ r = FcLangSetHasLang (ls, extra);
+ if (r < best)
+ best = r;
+ }
+ FcStrListDone (list);
+ }
+ return best;
+}
+
+FcLangResult
+FcLangSetCompare (const FcLangSet *lsa, const FcLangSet *lsb)
+{
+ int i, j;
+ FcLangResult best, r;
+
+ for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ if (lsa->map[i] & lsb->map[i])
+ return FcLangEqual;
+ best = FcLangDifferentLang;
+ for (j = 0; j < NUM_COUNTRY_SET; j++)
+ for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ if ((lsa->map[i] & fcLangCountrySets[j][i]) &&
+ (lsb->map[i] & fcLangCountrySets[j][i]))
+ {
+ best = FcLangDifferentCountry;
+ break;
+ }
+ if (lsa->extra)
+ {
+ r = FcLangSetCompareStrSet (lsb, lsa->extra);
+ if (r < best)
+ best = r;
+ }
+ if (best > FcLangEqual && lsb->extra)
+ {
+ r = FcLangSetCompareStrSet (lsa, lsb->extra);
+ if (r < best)
+ best = r;
+ }
+ return best;
+}
+
+/*
+ * Used in computing values -- mustn't allocate any storage
+ */
+FcLangSet *
+FcLangSetPromote (const FcChar8 *lang)
+{
+ static FcLangSet ls;
+ static FcStrSet strs;
+ static FcChar8 *str;
+ int id;
+
+ memset (ls.map, '\0', sizeof (ls.map));
+ ls.extra = 0;
+ id = FcLangSetIndex (lang);
+ if (id > 0)
+ {
+ FcLangSetBitSet (&ls, id);
+ }
+ else
+ {
+ ls.extra = &strs;
+ strs.num = 1;
+ strs.size = 1;
+ strs.strs = &str;
+ strs.ref = 1;
+ str = (FcChar8 *) lang;
+ }
+ return &ls;
+}
+
+FcChar32
+FcLangSetHash (const FcLangSet *ls)
+{
+ FcChar32 h = 0;
+ int i;
+
+ for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ h ^= ls->map[i];
+ if (ls->extra)
+ h ^= ls->extra->num;
+ return h;
+}
+
+FcLangSet *
+FcNameParseLangSet (const FcChar8 *string)
+{
+ FcChar8 lang[32],c;
+ int i;
+ FcLangSet *ls;
+
+ ls = FcLangSetCreate ();
+ if (!ls)
+ goto bail0;
+
+ for(;;)
+ {
+ for(i = 0; i < 31;i++)
+ {
+ c = *string++;
+ if(c == '\0' || c == '|')
+ break; /* end of this code */
+ lang[i] = c;
+ }
+ lang[i] = '\0';
+ if (!FcLangSetAdd (ls, lang))
+ goto bail1;
+ if(c == '\0')
+ break;
+ }
+ return ls;
+bail1:
+ FcLangSetDestroy (ls);
+bail0:
+ return 0;
+}
+
+FcBool
+FcNameUnparseLangSet (FcStrBuf *buf, const FcLangSet *ls)
+{
+ int i, bit;
+ FcChar32 bits;
+ FcBool first = FcTrue;
+
+ for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ {
+ if ((bits = ls->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, fcLangCharSets[id].lang))
+ return FcFalse;
+ first = FcFalse;
+ }
+ }
+ }
+ if (ls->extra)
+ {
+ FcStrList *list = FcStrListCreate (ls->extra);
+ FcChar8 *extra;
+
+ if (!list)
+ return FcFalse;
+ while ((extra = FcStrListNext (list)))
+ {
+ if (!first)
+ if (!FcStrBufChar (buf, '|'))
+ return FcFalse;
+ if (!FcStrBufString (buf, extra))
+ return FcFalse;
+ first = FcFalse;
+ }
+ }
+ return FcTrue;
+}
+
+FcBool
+FcLangSetEqual (const FcLangSet *lsa, const FcLangSet *lsb)
+{
+ int i;
+
+ for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ {
+ if (lsa->map[i] != lsb->map[i])
+ return FcFalse;
+ }
+ if (!lsa->extra && !lsb->extra)
+ return FcTrue;
+ if (lsa->extra && lsb->extra)
+ return FcStrSetEqual (lsa->extra, lsb->extra);
+ return FcFalse;
+}
+
+static FcBool
+FcLangSetContainsLang (const FcLangSet *ls, const FcChar8 *lang)
+{
+ int id;
+ int i;
+
+ id = FcLangSetIndex (lang);
+ if (id < 0)
+ id = -id - 1;
+ else if (FcLangSetBitGet (ls, id))
+ return FcTrue;
+ /*
+ * search up and down among equal languages for a match
+ */
+ for (i = id - 1; i >= 0; i--)
+ {
+ if (FcLangCompare (fcLangCharSets[i].lang, lang) == FcLangDifferentLang)
+ break;
+ if (FcLangSetBitGet (ls, i) &&
+ FcLangContains (fcLangCharSets[i].lang, lang))
+ return FcTrue;
+ }
+ for (i = id; i < NUM_LANG_CHAR_SET; i++)
+ {
+ if (FcLangCompare (fcLangCharSets[i].lang, lang) == FcLangDifferentLang)
+ break;
+ if (FcLangSetBitGet (ls, i) &&
+ FcLangContains (fcLangCharSets[i].lang, lang))
+ return FcTrue;
+ }
+ if (ls->extra)
+ {
+ FcStrList *list = FcStrListCreate (ls->extra);
+ FcChar8 *extra;
+
+ if (list)
+ {
+ while ((extra = FcStrListNext (list)))
+ {
+ if (FcLangContains (extra, lang))
+ break;
+ }
+ FcStrListDone (list);
+ if (extra)
+ return FcTrue;
+ }
+ }
+ return FcFalse;
+}
+
+/*
+ * return FcTrue if lsa contains every language in lsb
+ */
+FcBool
+FcLangSetContains (const FcLangSet *lsa, const FcLangSet *lsb)
+{
+ int i, j;
+ FcChar32 missing;
+
+ if (FcDebug() & FC_DBG_MATCHV)
+ {
+ printf ("FcLangSet "); FcLangSetPrint (lsa);
+ printf (" contains "); FcLangSetPrint (lsb);
+ printf ("\n");
+ }
+ /*
+ * check bitmaps for missing language support
+ */
+ for (i = 0; i < NUM_LANG_SET_MAP; i++)
+ {
+ missing = lsb->map[i] & ~lsa->map[i];
+ if (missing)
+ {
+ for (j = 0; j < 32; j++)
+ if (missing & (1 << j))
+ {
+ if (!FcLangSetContainsLang (lsa,
+ fcLangCharSets[i*32 + j].lang))
+ {
+ if (FcDebug() & FC_DBG_MATCHV)
+ printf ("\tMissing bitmap %s\n", fcLangCharSets[i*32+j].lang);
+ return FcFalse;
+ }
+ }
+ }
+ }
+ if (lsb->extra)
+ {
+ FcStrList *list = FcStrListCreate (lsb->extra);
+ FcChar8 *extra;
+
+ if (list)
+ {
+ while ((extra = FcStrListNext (list)))
+ {
+ if (!FcLangSetContainsLang (lsa, extra))
+ {
+ if (FcDebug() & FC_DBG_MATCHV)
+ printf ("\tMissing string %s\n", extra);
+ break;
+ }
+ }
+ FcStrListDone (list);
+ if (extra)
+ return FcFalse;
+ }
+ }
+ return FcTrue;
+}
diff --git a/nx-X11/extras/fontconfig/src/fclist.c b/nx-X11/extras/fontconfig/src/fclist.c
new file mode 100644
index 000000000..ec47ddcab
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fclist.c
@@ -0,0 +1,499 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fclist.c,v 1.11tsi Exp $
+ *
+ * Copyright © 2000 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include "fcint.h"
+
+FcObjectSet *
+FcObjectSetCreate (void)
+{
+ FcObjectSet *os;
+
+ os = (FcObjectSet *) malloc (sizeof (FcObjectSet));
+ if (!os)
+ return 0;
+ FcMemAlloc (FC_MEM_OBJECTSET, sizeof (FcObjectSet));
+ os->nobject = 0;
+ os->sobject = 0;
+ os->objects = 0;
+ return os;
+}
+
+FcBool
+FcObjectSetAdd (FcObjectSet *os, const char *object)
+{
+ int s;
+ const char **objects;
+ int high, low, mid, c;
+
+ if (os->nobject == os->sobject)
+ {
+ s = os->sobject + 4;
+ if (os->objects)
+ objects = (const char **) realloc ((void *) os->objects,
+ s * sizeof (const char *));
+ else
+ objects = (const char **) malloc (s * sizeof (const char *));
+ if (!objects)
+ return FcFalse;
+ if (os->sobject)
+ FcMemFree (FC_MEM_OBJECTPTR, os->sobject * sizeof (const char *));
+ FcMemAlloc (FC_MEM_OBJECTPTR, s * sizeof (const char *));
+ os->objects = objects;
+ os->sobject = s;
+ }
+ high = os->nobject - 1;
+ low = 0;
+ mid = 0;
+ c = 1;
+ object = FcObjectStaticName (object);
+ while (low <= high)
+ {
+ mid = (low + high) >> 1;
+ c = os->objects[mid] - object;
+ if (c == 0)
+ return FcTrue;
+ if (c < 0)
+ low = mid + 1;
+ else
+ high = mid - 1;
+ }
+ if (c < 0)
+ mid++;
+ memmove (os->objects + mid + 1, os->objects + mid,
+ (os->nobject - mid) * sizeof (const char *));
+ os->objects[mid] = object;
+ os->nobject++;
+ return FcTrue;
+}
+
+void
+FcObjectSetDestroy (FcObjectSet *os)
+{
+ if (os->objects)
+ {
+ FcMemFree (FC_MEM_OBJECTPTR, os->sobject * sizeof (const char *));
+ free ((void *) os->objects);
+ }
+ FcMemFree (FC_MEM_OBJECTSET, sizeof (FcObjectSet));
+ free (os);
+}
+
+FcObjectSet *
+FcObjectSetVaBuild (const char *first, va_list va)
+{
+ FcObjectSet *ret;
+
+ FcObjectSetVapBuild (ret, first, va);
+ return ret;
+}
+
+FcObjectSet *
+FcObjectSetBuild (const char *first, ...)
+{
+ va_list va;
+ FcObjectSet *os;
+
+ va_start (va, first);
+ FcObjectSetVapBuild (os, first, va);
+ va_end (va);
+ return os;
+}
+
+/*
+ * Font must have a containing value for every value in the pattern
+ */
+static FcBool
+FcListValueListMatchAny (FcValueList *patOrig, /* pattern */
+ FcValueList *fntOrig) /* font */
+{
+ FcValueList *pat, *fnt;
+
+ for (pat = patOrig; pat; pat = pat->next)
+ {
+ for (fnt = fntOrig; fnt; fnt = fnt->next)
+ {
+ /*
+ * make sure the font 'contains' the pattern.
+ * (OpListing is OpContains except for strings
+ * where it requires an exact match)
+ */
+ if (FcConfigCompareValue (fnt->value,
+ FcOpListing,
+ pat->value))
+ break;
+ }
+ if (!fnt)
+ return FcFalse;
+ }
+ return FcTrue;
+}
+
+static FcBool
+FcListValueListEqual (FcValueList *v1orig,
+ FcValueList *v2orig)
+{
+ FcValueList *v1, *v2;
+
+ for (v1 = v1orig; v1; v1 = v1->next)
+ {
+ for (v2 = v2orig; v2; v2 = v2->next)
+ if (FcValueEqual (v1->value, v2->value))
+ break;
+ if (!v2)
+ return FcFalse;
+ }
+ for (v2 = v2orig; v2; v2 = v2->next)
+ {
+ for (v1 = v1orig; v1; v1 = v1->next)
+ if (FcValueEqual (v1->value, v2->value))
+ break;
+ if (!v1)
+ return FcFalse;
+ }
+ return FcTrue;
+}
+
+static FcBool
+FcListPatternEqual (FcPattern *p1,
+ FcPattern *p2,
+ FcObjectSet *os)
+{
+ int i;
+ FcPatternElt *e1, *e2;
+
+ for (i = 0; i < os->nobject; i++)
+ {
+ e1 = FcPatternFindElt (p1, os->objects[i]);
+ e2 = FcPatternFindElt (p2, os->objects[i]);
+ if (!e1 && !e2)
+ continue;
+ if (!e1 || !e2)
+ return FcFalse;
+ if (!FcListValueListEqual (e1->values, e2->values))
+ return FcFalse;
+ }
+ return FcTrue;
+}
+
+/*
+ * FcTrue iff all objects in "p" match "font"
+ */
+
+FcBool
+FcListPatternMatchAny (const FcPattern *p,
+ const FcPattern *font)
+{
+ int i;
+ FcPatternElt *e;
+
+ for (i = 0; i < p->num; i++)
+ {
+ e = FcPatternFindElt (font, p->elts[i].object);
+ if (!e)
+ return FcFalse;
+ if (!FcListValueListMatchAny (p->elts[i].values, /* pat elts */
+ e->values)) /* font elts */
+ return FcFalse;
+ }
+ return FcTrue;
+}
+
+static FcChar32
+FcListMatrixHash (const FcMatrix *m)
+{
+ int xx = (int) (m->xx * 100),
+ xy = (int) (m->xy * 100),
+ yx = (int) (m->yx * 100),
+ yy = (int) (m->yy * 100);
+
+ return ((FcChar32) xx) ^ ((FcChar32) xy) ^ ((FcChar32) yx) ^ ((FcChar32) yy);
+}
+
+static FcChar32
+FcListValueHash (FcValue v)
+{
+ switch (v.type) {
+ case FcTypeVoid:
+ return 0;
+ case FcTypeInteger:
+ return (FcChar32) v.u.i;
+ case FcTypeDouble:
+ return (FcChar32) (int) v.u.d;
+ case FcTypeString:
+ return FcStrHashIgnoreCase (v.u.s);
+ case FcTypeBool:
+ return (FcChar32) v.u.b;
+ case FcTypeMatrix:
+ return FcListMatrixHash (v.u.m);
+ case FcTypeCharSet:
+ return FcCharSetCount (v.u.c);
+ case FcTypeFTFace:
+ return (long) v.u.f;
+ case FcTypeLangSet:
+ return FcLangSetHash (v.u.l);
+ }
+ return 0;
+}
+
+static FcChar32
+FcListValueListHash (FcValueList *list)
+{
+ FcChar32 h = 0;
+
+ while (list)
+ {
+ h = h ^ FcListValueHash (list->value);
+ list = list->next;
+ }
+ return h;
+}
+
+static FcChar32
+FcListPatternHash (FcPattern *font,
+ FcObjectSet *os)
+{
+ int n;
+ FcPatternElt *e;
+ FcChar32 h = 0;
+
+ for (n = 0; n < os->nobject; n++)
+ {
+ e = FcPatternFindElt (font, os->objects[n]);
+ if (e)
+ h = h ^ FcListValueListHash (e->values);
+ }
+ return h;
+}
+
+typedef struct _FcListBucket {
+ struct _FcListBucket *next;
+ FcChar32 hash;
+ FcPattern *pattern;
+} FcListBucket;
+
+#define FC_LIST_HASH_SIZE 4099
+
+typedef struct _FcListHashTable {
+ int entries;
+ FcListBucket *buckets[FC_LIST_HASH_SIZE];
+} FcListHashTable;
+
+static void
+FcListHashTableInit (FcListHashTable *table)
+{
+ table->entries = 0;
+ memset (table->buckets, '\0', sizeof (table->buckets));
+}
+
+static void
+FcListHashTableCleanup (FcListHashTable *table)
+{
+ int i;
+ FcListBucket *bucket, *next;
+
+ for (i = 0; i < FC_LIST_HASH_SIZE; i++)
+ {
+ for (bucket = table->buckets[i]; bucket; bucket = next)
+ {
+ next = bucket->next;
+ FcPatternDestroy (bucket->pattern);
+ FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket));
+ free (bucket);
+ }
+ table->buckets[i] = 0;
+ }
+ table->entries = 0;
+}
+
+static FcBool
+FcListAppend (FcListHashTable *table,
+ FcPattern *font,
+ FcObjectSet *os)
+{
+ int o;
+ FcPatternElt *e;
+ FcValueList *v;
+ FcChar32 hash;
+ FcListBucket **prev, *bucket;
+
+ hash = FcListPatternHash (font, os);
+ for (prev = &table->buckets[hash % FC_LIST_HASH_SIZE];
+ (bucket = *prev); prev = &(bucket->next))
+ {
+ if (bucket->hash == hash &&
+ FcListPatternEqual (bucket->pattern, font, os))
+ return FcTrue;
+ }
+ bucket = (FcListBucket *) malloc (sizeof (FcListBucket));
+ if (!bucket)
+ goto bail0;
+ FcMemAlloc (FC_MEM_LISTBUCK, sizeof (FcListBucket));
+ bucket->next = 0;
+ bucket->hash = hash;
+ bucket->pattern = FcPatternCreate ();
+ if (!bucket->pattern)
+ goto bail1;
+
+ for (o = 0; o < os->nobject; o++)
+ {
+ e = FcPatternFindElt (font, os->objects[o]);
+ if (e)
+ {
+ for (v = e->values; v; v = v->next)
+ {
+ if (!FcPatternAdd (bucket->pattern,
+ os->objects[o],
+ v->value, FcTrue))
+ goto bail2;
+ }
+ }
+ }
+ *prev = bucket;
+ ++table->entries;
+
+ return FcTrue;
+
+bail2:
+ FcPatternDestroy (bucket->pattern);
+bail1:
+ FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket));
+ free (bucket);
+bail0:
+ return FcFalse;
+}
+
+FcFontSet *
+FcFontSetList (FcConfig *config,
+ FcFontSet **sets,
+ int nsets,
+ FcPattern *p,
+ FcObjectSet *os)
+{
+ FcFontSet *ret;
+ FcFontSet *s;
+ int f;
+ int set;
+ FcListHashTable table;
+ int i;
+ FcListBucket *bucket;
+
+ if (!config)
+ {
+ if (!FcInitBringUptoDate ())
+ goto bail0;
+
+ config = FcConfigGetCurrent ();
+ if (!config)
+ goto bail0;
+ }
+ FcListHashTableInit (&table);
+ /*
+ * Walk all available fonts adding those that
+ * match to the hash table
+ */
+ for (set = 0; set < nsets; set++)
+ {
+ s = sets[set];
+ if (!s)
+ continue;
+ for (f = 0; f < s->nfont; f++)
+ if (FcListPatternMatchAny (p, /* pattern */
+ s->fonts[f])) /* font */
+ if (!FcListAppend (&table, s->fonts[f], os))
+ goto bail1;
+ }
+#if 0
+ {
+ int max = 0;
+ int full = 0;
+ int ents = 0;
+ int len;
+ for (i = 0; i < FC_LIST_HASH_SIZE; i++)
+ {
+ if ((bucket = table.buckets[i]))
+ {
+ len = 0;
+ for (; bucket; bucket = bucket->next)
+ {
+ ents++;
+ len++;
+ }
+ if (len > max)
+ max = len;
+ full++;
+ }
+ }
+ printf ("used: %d max: %d avg: %g\n", full, max,
+ (double) ents / FC_LIST_HASH_SIZE);
+ }
+#endif
+ /*
+ * Walk the hash table and build
+ * a font set
+ */
+ ret = FcFontSetCreate ();
+ if (!ret)
+ goto bail0;
+ for (i = 0; i < FC_LIST_HASH_SIZE; i++)
+ while ((bucket = table.buckets[i]))
+ {
+ if (!FcFontSetAdd (ret, bucket->pattern))
+ goto bail2;
+ table.buckets[i] = bucket->next;
+ FcMemFree (FC_MEM_LISTBUCK, sizeof (FcListBucket));
+ free (bucket);
+ }
+
+ return ret;
+
+bail2:
+ FcFontSetDestroy (ret);
+bail1:
+ FcListHashTableCleanup (&table);
+bail0:
+ return 0;
+}
+
+FcFontSet *
+FcFontList (FcConfig *config,
+ FcPattern *p,
+ FcObjectSet *os)
+{
+ FcFontSet *sets[2];
+ int nsets;
+
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return 0;
+ }
+ nsets = 0;
+ if (config->fonts[FcSetSystem])
+ sets[nsets++] = config->fonts[FcSetSystem];
+ if (config->fonts[FcSetApplication])
+ sets[nsets++] = config->fonts[FcSetApplication];
+ return FcFontSetList (config, sets, nsets, p, os);
+}
diff --git a/nx-X11/extras/fontconfig/src/fcmatch.c b/nx-X11/extras/fontconfig/src/fcmatch.c
new file mode 100644
index 000000000..9a6b35fba
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcmatch.c
@@ -0,0 +1,852 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fcmatch.c,v 1.20 2002/08/31 22:17:32 keithp Exp $
+ *
+ * Copyright © 2000 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <string.h>
+#include <ctype.h>
+#include "fcint.h"
+#include <stdio.h>
+
+static double
+FcCompareNumber (char *object, FcValue value1, FcValue value2)
+{
+ double v1, v2, v;
+
+ switch (value1.type) {
+ case FcTypeInteger:
+ v1 = (double) value1.u.i;
+ break;
+ case FcTypeDouble:
+ v1 = value1.u.d;
+ break;
+ default:
+ return -1.0;
+ }
+ switch (value2.type) {
+ case FcTypeInteger:
+ v2 = (double) value2.u.i;
+ break;
+ case FcTypeDouble:
+ v2 = value2.u.d;
+ break;
+ default:
+ return -1.0;
+ }
+ v = v2 - v1;
+ if (v < 0)
+ v = -v;
+ return (double) v;
+}
+
+static double
+FcCompareString (char *object, FcValue value1, FcValue value2)
+{
+ if (value2.type != FcTypeString || value1.type != FcTypeString)
+ return -1.0;
+ return (double) FcStrCmpIgnoreCase (value1.u.s, value2.u.s) != 0;
+}
+
+static double
+FcCompareFamily (char *object, FcValue value1, FcValue value2)
+{
+ if (value2.type != FcTypeString || value1.type != FcTypeString)
+ return -1.0;
+ return (double) FcStrCmpIgnoreBlanksAndCase (value1.u.s, value2.u.s) != 0;
+}
+
+static double
+FcCompareLang (char *object, FcValue value1, FcValue value2)
+{
+ FcLangResult result;
+
+ switch (value1.type) {
+ case FcTypeLangSet:
+ switch (value2.type) {
+ case FcTypeLangSet:
+ result = FcLangSetCompare (value1.u.l, value2.u.l);
+ break;
+ case FcTypeString:
+ result = FcLangSetHasLang (value1.u.l, value2.u.s);
+ break;
+ default:
+ return -1.0;
+ }
+ break;
+ case FcTypeString:
+ switch (value2.type) {
+ case FcTypeLangSet:
+ result = FcLangSetHasLang (value2.u.l, value1.u.s);
+ break;
+ case FcTypeString:
+ result = FcLangCompare (value1.u.s, value2.u.s);
+ break;
+ default:
+ return -1.0;
+ }
+ break;
+ default:
+ return -1.0;
+ }
+ switch (result) {
+ case FcLangEqual:
+ return 0;
+ case FcLangDifferentCountry:
+ return 1;
+ case FcLangDifferentLang:
+ default:
+ return 2;
+ }
+}
+
+static double
+FcCompareBool (char *object, FcValue value1, FcValue value2)
+{
+ if (value2.type != FcTypeBool || value1.type != FcTypeBool)
+ return -1.0;
+ return (double) value2.u.b != value1.u.b;
+}
+
+static double
+FcCompareCharSet (char *object, FcValue value1, FcValue value2)
+{
+ if (value2.type != FcTypeCharSet || value1.type != FcTypeCharSet)
+ return -1.0;
+ return (double) FcCharSetSubtractCount (value1.u.c, value2.u.c);
+}
+
+static double
+FcCompareSize (char *object, FcValue value1, FcValue value2)
+{
+ double v1, v2, v;
+
+ switch (value1.type) {
+ case FcTypeInteger:
+ v1 = value1.u.i;
+ break;
+ case FcTypeDouble:
+ v1 = value1.u.d;
+ break;
+ default:
+ return -1;
+ }
+ switch (value2.type) {
+ case FcTypeInteger:
+ v2 = value2.u.i;
+ break;
+ case FcTypeDouble:
+ v2 = value2.u.d;
+ break;
+ default:
+ return -1;
+ }
+ if (v2 == 0)
+ return 0;
+ v = v2 - v1;
+ if (v < 0)
+ v = -v;
+ return v;
+}
+
+typedef struct _FcMatcher {
+ char *object;
+ double (*compare) (char *object, FcValue value1, FcValue value2);
+ int strong, weak;
+} FcMatcher;
+
+/*
+ * Order is significant, it defines the precedence of
+ * each value, earlier values are more significant than
+ * later values
+ */
+static FcMatcher _FcMatchers [] = {
+ { FC_FOUNDRY, FcCompareString, 0, 0 },
+#define MATCH_FOUNDRY 0
+#define MATCH_FOUNDRY_INDEX 0
+
+ { FC_CHARSET, FcCompareCharSet, 1, 1 },
+#define MATCH_CHARSET 1
+#define MATCH_CHARSET_INDEX 1
+
+ { FC_FAMILY, FcCompareFamily, 2, 4 },
+#define MATCH_FAMILY 2
+#define MATCH_FAMILY_STRONG_INDEX 2
+#define MATCH_FAMILY_WEAK_INDEX 4
+
+ { FC_LANG, FcCompareLang, 3, 3 },
+#define MATCH_LANG 3
+#define MATCH_LANG_INDEX 3
+
+ { FC_SPACING, FcCompareNumber, 5, 5 },
+#define MATCH_SPACING 4
+#define MATCH_SPACING_INDEX 5
+
+ { FC_PIXEL_SIZE, FcCompareSize, 6, 6 },
+#define MATCH_PIXEL_SIZE 5
+#define MATCH_PIXEL_SIZE_INDEX 6
+
+ { FC_STYLE, FcCompareString, 7, 7 },
+#define MATCH_STYLE 6
+#define MATCH_STYLE_INDEX 7
+
+ { FC_SLANT, FcCompareNumber, 8, 8 },
+#define MATCH_SLANT 7
+#define MATCH_SLANT_INDEX 8
+
+ { FC_WEIGHT, FcCompareNumber, 9, 9 },
+#define MATCH_WEIGHT 8
+#define MATCH_WEIGHT_INDEX 9
+
+ { FC_WIDTH, FcCompareNumber, 10, 10 },
+#define MATCH_WIDTH 9
+#define MATCH_WIDTH_INDEX 10
+
+ { FC_ANTIALIAS, FcCompareBool, 11, 11 },
+#define MATCH_ANTIALIAS 10
+#define MATCH_ANTIALIAS_INDEX 11
+
+ { FC_RASTERIZER, FcCompareString, 12, 12 },
+#define MATCH_RASTERIZER 11
+#define MATCH_RASTERIZER_INDEX 12
+
+ { FC_OUTLINE, FcCompareBool, 13, 13 },
+#define MATCH_OUTLINE 12
+#define MATCH_OUTLINE_INDEX 13
+
+ { FC_FONTVERSION, FcCompareNumber, 14, 14 },
+#define MATCH_FONTVERSION 13
+#define MATCH_FONTVERSION_INDEX 14
+};
+
+#define NUM_MATCH_VALUES 15
+
+static FcBool
+FcCompareValueList (const char *object,
+ FcValueList *v1orig, /* pattern */
+ FcValueList *v2orig, /* target */
+ FcValue *bestValue,
+ double *value,
+ FcResult *result)
+{
+ FcValueList *v1, *v2;
+ double v, best, bestStrong, bestWeak;
+ int i;
+ int j;
+
+ /*
+ * Locate the possible matching entry by examining the
+ * first few characters in object
+ */
+ i = -1;
+ switch (FcToLower (object[0])) {
+ case 'f':
+ switch (FcToLower (object[1])) {
+ case 'o':
+ switch (FcToLower (object[2])) {
+ case 'u':
+ i = MATCH_FOUNDRY; break;
+ case 'n':
+ i = MATCH_FONTVERSION; break;
+ }
+ break;
+ case 'a':
+ i = MATCH_FAMILY; break;
+ }
+ break;
+ case 'c':
+ i = MATCH_CHARSET; break;
+ case 'a':
+ i = MATCH_ANTIALIAS; break;
+ case 'l':
+ i = MATCH_LANG; break;
+ case 's':
+ switch (FcToLower (object[1])) {
+ case 'p':
+ i = MATCH_SPACING; break;
+ case 't':
+ i = MATCH_STYLE; break;
+ case 'l':
+ i = MATCH_SLANT; break;
+ }
+ break;
+ case 'p':
+ i = MATCH_PIXEL_SIZE; break;
+ case 'w':
+ switch (FcToLower (object[1])) {
+ case 'i':
+ i = MATCH_WIDTH; break;
+ case 'e':
+ i = MATCH_WEIGHT; break;
+ }
+ break;
+ case 'r':
+ i = MATCH_RASTERIZER; break;
+ case 'o':
+ i = MATCH_OUTLINE; break;
+ }
+ if (i == -1 ||
+ FcStrCmpIgnoreCase ((FcChar8 *) _FcMatchers[i].object,
+ (FcChar8 *) object) != 0)
+ {
+ if (bestValue)
+ *bestValue = v2orig->value;
+ return FcTrue;
+ }
+#if 0
+ for (i = 0; i < NUM_MATCHER; i++)
+ {
+ if (!FcStrCmpIgnoreCase ((FcChar8 *) _FcMatchers[i].object,
+ (FcChar8 *) object))
+ break;
+ }
+ if (i == NUM_MATCHER)
+ {
+ if (bestValue)
+ *bestValue = v2orig->value;
+ return FcTrue;
+ }
+#endif
+ best = 1e99;
+ bestStrong = 1e99;
+ bestWeak = 1e99;
+ j = 0;
+ for (v1 = v1orig; v1; v1 = v1->next)
+ {
+ for (v2 = v2orig; v2; v2 = v2->next)
+ {
+ v = (*_FcMatchers[i].compare) (_FcMatchers[i].object,
+ v1->value,
+ v2->value);
+ if (v < 0)
+ {
+ *result = FcResultTypeMismatch;
+ return FcFalse;
+ }
+ if (FcDebug () & FC_DBG_MATCHV)
+ printf (" v %g j %d ", v, j);
+ v = v * 100 + j;
+ if (v < best)
+ {
+ if (bestValue)
+ *bestValue = v2->value;
+ best = v;
+ }
+ if (v1->binding == FcValueBindingStrong)
+ {
+ if (v < bestStrong)
+ bestStrong = v;
+ }
+ else
+ {
+ if (v < bestWeak)
+ bestWeak = v;
+ }
+ }
+ j++;
+ }
+ if (FcDebug () & FC_DBG_MATCHV)
+ {
+ printf (" %s: %g ", object, best);
+ FcValueListPrint (v1orig);
+ printf (", ");
+ FcValueListPrint (v2orig);
+ printf ("\n");
+ }
+ if (value)
+ {
+ int weak = _FcMatchers[i].weak;
+ int strong = _FcMatchers[i].strong;
+ if (weak == strong)
+ value[strong] += best;
+ else
+ {
+ value[weak] += bestWeak;
+ value[strong] += bestStrong;
+ }
+ }
+ return FcTrue;
+}
+
+/*
+ * Return a value indicating the distance between the two lists of
+ * values
+ */
+
+static FcBool
+FcCompare (FcPattern *pat,
+ FcPattern *fnt,
+ double *value,
+ FcResult *result)
+{
+ int i, i1, i2;
+
+ for (i = 0; i < NUM_MATCH_VALUES; i++)
+ value[i] = 0.0;
+
+ i1 = 0;
+ i2 = 0;
+ while (i1 < pat->num && i2 < fnt->num)
+ {
+ i = pat->elts[i1].object - fnt->elts[i2].object;
+ if (i > 0)
+ i2++;
+ else if (i < 0)
+ i1++;
+ else
+ {
+ if (!FcCompareValueList (pat->elts[i1].object,
+ pat->elts[i1].values,
+ fnt->elts[i2].values,
+ 0,
+ value,
+ result))
+ return FcFalse;
+ i1++;
+ i2++;
+ }
+ }
+ return FcTrue;
+#if 0
+ for (i1 = 0; i1 < pat->num; i1++)
+ {
+ for (i2 = 0; i2 < fnt->num; i2++)
+ {
+ if (!strcmp (pat->elts[i1].object, fnt->elts[i2].object))
+ {
+ break;
+ }
+ }
+ }
+ return FcTrue;
+#endif
+}
+
+FcPattern *
+FcFontRenderPrepare (FcConfig *config,
+ FcPattern *pat,
+ FcPattern *font)
+{
+ FcPattern *new;
+ int i;
+ FcPatternElt *fe, *pe;
+ FcValue v;
+ FcResult result;
+
+ new = FcPatternCreate ();
+ if (!new)
+ return 0;
+ for (i = 0; i < font->num; i++)
+ {
+ fe = &font->elts[i];
+ pe = FcPatternFindElt (pat, fe->object);
+ if (pe)
+ {
+ if (!FcCompareValueList (pe->object, pe->values,
+ fe->values, &v, 0, &result))
+ {
+ FcPatternDestroy (new);
+ return 0;
+ }
+ }
+ else
+ v = fe->values->value;
+ FcPatternAdd (new, fe->object, v, FcFalse);
+ }
+ for (i = 0; i < pat->num; i++)
+ {
+ pe = &pat->elts[i];
+ fe = FcPatternFindElt (font, pe->object);
+ if (!fe)
+ FcPatternAdd (new, pe->object, pe->values->value, FcTrue);
+ }
+ FcConfigSubstituteWithPat (config, new, pat, FcMatchFont);
+ return new;
+}
+
+FcPattern *
+FcFontSetMatch (FcConfig *config,
+ FcFontSet **sets,
+ int nsets,
+ FcPattern *p,
+ FcResult *result)
+{
+ double score[NUM_MATCH_VALUES], bestscore[NUM_MATCH_VALUES];
+ int f;
+ FcFontSet *s;
+ FcPattern *best;
+ int i;
+ int set;
+
+ for (i = 0; i < NUM_MATCH_VALUES; i++)
+ bestscore[i] = 0;
+ best = 0;
+ if (FcDebug () & FC_DBG_MATCH)
+ {
+ printf ("Match ");
+ FcPatternPrint (p);
+ }
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ {
+ *result = FcResultOutOfMemory;
+ return 0;
+ }
+ }
+ for (set = 0; set < nsets; set++)
+ {
+ s = sets[set];
+ if (!s)
+ continue;
+ for (f = 0; f < s->nfont; f++)
+ {
+ if (FcDebug () & FC_DBG_MATCHV)
+ {
+ printf ("Font %d ", f);
+ FcPatternPrint (s->fonts[f]);
+ }
+ if (!FcCompare (p, s->fonts[f], score, result))
+ return 0;
+ if (FcDebug () & FC_DBG_MATCHV)
+ {
+ printf ("Score");
+ for (i = 0; i < NUM_MATCH_VALUES; i++)
+ {
+ printf (" %g", score[i]);
+ }
+ printf ("\n");
+ }
+ for (i = 0; i < NUM_MATCH_VALUES; i++)
+ {
+ if (best && bestscore[i] < score[i])
+ break;
+ if (!best || score[i] < bestscore[i])
+ {
+ for (i = 0; i < NUM_MATCH_VALUES; i++)
+ bestscore[i] = score[i];
+ best = s->fonts[f];
+ break;
+ }
+ }
+ }
+ }
+ if (FcDebug () & FC_DBG_MATCH)
+ {
+ printf ("Best score");
+ for (i = 0; i < NUM_MATCH_VALUES; i++)
+ printf (" %g", bestscore[i]);
+ FcPatternPrint (best);
+ }
+ if (!best)
+ {
+ *result = FcResultNoMatch;
+ return 0;
+ }
+ return FcFontRenderPrepare (config, p, best);
+}
+
+FcPattern *
+FcFontMatch (FcConfig *config,
+ FcPattern *p,
+ FcResult *result)
+{
+ FcFontSet *sets[2];
+ int nsets;
+
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return 0;
+ }
+ nsets = 0;
+ if (config->fonts[FcSetSystem])
+ sets[nsets++] = config->fonts[FcSetSystem];
+ if (config->fonts[FcSetApplication])
+ sets[nsets++] = config->fonts[FcSetApplication];
+ return FcFontSetMatch (config, sets, nsets, p, result);
+}
+
+typedef struct _FcSortNode {
+ FcPattern *pattern;
+ double score[NUM_MATCH_VALUES];
+} FcSortNode;
+
+static int
+FcSortCompare (const void *aa, const void *ab)
+{
+ FcSortNode *a = *(FcSortNode **) aa;
+ FcSortNode *b = *(FcSortNode **) ab;
+ double *as = &a->score[0];
+ double *bs = &b->score[0];
+ double ad = 0, bd = 0;
+ int i;
+
+ i = NUM_MATCH_VALUES;
+ while (i-- && (ad = *as++) == (bd = *bs++))
+ ;
+ return ad < bd ? -1 : ad > bd ? 1 : 0;
+}
+
+static FcBool
+FcSortWalk (FcSortNode **n, int nnode, FcFontSet *fs, FcCharSet **cs, FcBool trim)
+{
+ FcCharSet *ncs;
+ FcSortNode *node;
+
+ while (nnode--)
+ {
+ node = *n++;
+ if (FcPatternGetCharSet (node->pattern, FC_CHARSET, 0, &ncs) ==
+ FcResultMatch)
+ {
+ /*
+ * If this font isn't a subset of the previous fonts,
+ * add it to the list
+ */
+ if (!trim || !*cs || !FcCharSetIsSubset (ncs, *cs))
+ {
+ if (*cs)
+ {
+ ncs = FcCharSetUnion (ncs, *cs);
+ if (!ncs)
+ return FcFalse;
+ FcCharSetDestroy (*cs);
+ }
+ else
+ ncs = FcCharSetCopy (ncs);
+ *cs = ncs;
+ FcPatternReference (node->pattern);
+ if (FcDebug () & FC_DBG_MATCH)
+ {
+ printf ("Add ");
+ FcPatternPrint (node->pattern);
+ }
+ if (!FcFontSetAdd (fs, node->pattern))
+ {
+ FcPatternDestroy (node->pattern);
+ return FcFalse;
+ }
+ }
+ }
+ }
+ return FcTrue;
+}
+
+void
+FcFontSetSortDestroy (FcFontSet *fs)
+{
+ FcFontSetDestroy (fs);
+}
+
+FcFontSet *
+FcFontSetSort (FcConfig *config,
+ FcFontSet **sets,
+ int nsets,
+ FcPattern *p,
+ FcBool trim,
+ FcCharSet **csp,
+ FcResult *result)
+{
+ FcFontSet *ret;
+ FcFontSet *s;
+ FcSortNode *nodes;
+ FcSortNode **nodeps, **nodep;
+ int nnodes;
+ FcSortNode *new;
+ FcCharSet *cs;
+ int set;
+ int f;
+ int i;
+ int nPatternLang;
+ FcBool *patternLangSat;
+ FcValue patternLang;
+
+ if (FcDebug () & FC_DBG_MATCH)
+ {
+ printf ("Sort ");
+ FcPatternPrint (p);
+ }
+ nnodes = 0;
+ for (set = 0; set < nsets; set++)
+ {
+ s = sets[set];
+ if (!s)
+ continue;
+ nnodes += s->nfont;
+ }
+ if (!nnodes)
+ goto bail0;
+
+ for (nPatternLang = 0;
+ FcPatternGet (p, FC_LANG, nPatternLang, &patternLang) == FcResultMatch;
+ nPatternLang++)
+ ;
+
+ /* freed below */
+ nodes = malloc (nnodes * sizeof (FcSortNode) +
+ nnodes * sizeof (FcSortNode *) +
+ nPatternLang * sizeof (FcBool));
+ if (!nodes)
+ goto bail0;
+ nodeps = (FcSortNode **) (nodes + nnodes);
+ patternLangSat = (FcBool *) (nodeps + nnodes);
+
+ new = nodes;
+ nodep = nodeps;
+ for (set = 0; set < nsets; set++)
+ {
+ s = sets[set];
+ if (!s)
+ continue;
+ for (f = 0; f < s->nfont; f++)
+ {
+ if (FcDebug () & FC_DBG_MATCHV)
+ {
+ printf ("Font %d ", f);
+ FcPatternPrint (s->fonts[f]);
+ }
+ new->pattern = s->fonts[f];
+ if (!FcCompare (p, new->pattern, new->score, result))
+ goto bail1;
+ if (FcDebug () & FC_DBG_MATCHV)
+ {
+ printf ("Score");
+ for (i = 0; i < NUM_MATCH_VALUES; i++)
+ {
+ printf (" %g", new->score[i]);
+ }
+ printf ("\n");
+ }
+ *nodep = new;
+ new++;
+ nodep++;
+ }
+ }
+
+ nnodes = new - nodes;
+
+ qsort (nodeps, nnodes, sizeof (FcSortNode *),
+ FcSortCompare);
+
+ for (i = 0; i < nPatternLang; i++)
+ patternLangSat[i] = FcFalse;
+
+ for (f = 0; f < nnodes; f++)
+ {
+ FcBool satisfies = FcFalse;
+ /*
+ * If this node matches any language, go check
+ * which ones and satisfy those entries
+ */
+ if (nodeps[f]->score[MATCH_LANG_INDEX] < nPatternLang)
+ {
+ for (i = 0; i < nPatternLang; i++)
+ {
+ FcValue nodeLang;
+
+ if (!patternLangSat[i] &&
+ FcPatternGet (p, FC_LANG, i, &patternLang) == FcResultMatch &&
+ FcPatternGet (nodeps[f]->pattern, FC_LANG, 0, &nodeLang) == FcResultMatch)
+ {
+ double compare = FcCompareLang (FC_LANG, patternLang,
+ nodeLang);
+ if (compare >= 0 && compare < 2)
+ {
+ if (FcDebug () & FC_DBG_MATCHV)
+ {
+ FcChar8 *family;
+ FcChar8 *style;
+
+ if (FcPatternGetString (nodeps[f]->pattern, FC_FAMILY, 0, &family) == FcResultMatch &&
+ FcPatternGetString (nodeps[f]->pattern, FC_STYLE, 0, &style) == FcResultMatch)
+ printf ("Font %s:%s matches language %d\n", family, style, i);
+ }
+ patternLangSat[i] = FcTrue;
+ satisfies = FcTrue;
+ break;
+ }
+ }
+ }
+ }
+ if (!satisfies)
+ nodeps[f]->score[MATCH_LANG_INDEX] = 1000.0;
+ }
+
+ /*
+ * Re-sort once the language issues have been settled
+ */
+ qsort (nodeps, nnodes, sizeof (FcSortNode *),
+ FcSortCompare);
+
+ ret = FcFontSetCreate ();
+ if (!ret)
+ goto bail1;
+
+ cs = 0;
+
+ if (!FcSortWalk (nodeps, nnodes, ret, &cs, trim))
+ goto bail2;
+
+ if (csp)
+ *csp = cs;
+ else
+ FcCharSetDestroy (cs);
+
+ free (nodes);
+
+ return ret;
+
+bail2:
+ if (cs)
+ FcCharSetDestroy (cs);
+ FcFontSetDestroy (ret);
+bail1:
+ free (nodes);
+bail0:
+ return 0;
+}
+
+FcFontSet *
+FcFontSort (FcConfig *config,
+ FcPattern *p,
+ FcBool trim,
+ FcCharSet **csp,
+ FcResult *result)
+{
+ FcFontSet *sets[2];
+ int nsets;
+
+ if (!config)
+ {
+ config = FcConfigGetCurrent ();
+ if (!config)
+ return 0;
+ }
+ nsets = 0;
+ if (config->fonts[FcSetSystem])
+ sets[nsets++] = config->fonts[FcSetSystem];
+ if (config->fonts[FcSetApplication])
+ sets[nsets++] = config->fonts[FcSetApplication];
+ return FcFontSetSort (config, sets, nsets, p, trim, csp, result);
+}
diff --git a/nx-X11/extras/fontconfig/src/fcmatrix.c b/nx-X11/extras/fontconfig/src/fcmatrix.c
new file mode 100644
index 000000000..863fe692c
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcmatrix.c
@@ -0,0 +1,117 @@
+/*
+ * $RCSId: $
+ *
+ * Copyright © 2000 Tuomas J. Lukka
+ *
+ * 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 Tuomas Lukka not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Tuomas Lukka makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * TUOMAS LUKKA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL TUOMAS LUKKA 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 <math.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "fcint.h"
+
+const FcMatrix FcIdentityMatrix = { 1, 0, 0, 1 };
+
+FcMatrix *
+FcMatrixCopy (const FcMatrix *mat)
+{
+ FcMatrix *r;
+ if(!mat)
+ return 0;
+ r = (FcMatrix *) malloc (sizeof (*r) );
+ if (!r)
+ return 0;
+ FcMemAlloc (FC_MEM_MATRIX, sizeof (FcMatrix));
+ *r = *mat;
+ return r;
+}
+
+void
+FcMatrixFree (FcMatrix *mat)
+{
+ if (mat != &FcIdentityMatrix)
+ {
+ FcMemFree (FC_MEM_MATRIX, sizeof (FcMatrix));
+ free (mat);
+ }
+}
+
+FcBool
+FcMatrixEqual (const FcMatrix *mat1, const FcMatrix *mat2)
+{
+ if(mat1 == mat2) return FcTrue;
+ if(mat1 == 0 || mat2 == 0) return FcFalse;
+ return mat1->xx == mat2->xx &&
+ mat1->xy == mat2->xy &&
+ mat1->yx == mat2->yx &&
+ mat1->yy == mat2->yy;
+}
+
+void
+FcMatrixMultiply (FcMatrix *result, const FcMatrix *a, const FcMatrix *b)
+{
+ FcMatrix r;
+
+ r.xx = a->xx * b->xx + a->xy * b->yx;
+ r.xy = a->xx * b->xy + a->xy * b->yy;
+ r.yx = a->yx * b->xx + a->yy * b->yx;
+ r.yy = a->yx * b->xy + a->yy * b->yy;
+ *result = r;
+}
+
+void
+FcMatrixRotate (FcMatrix *m, double c, double s)
+{
+ FcMatrix r;
+
+ /*
+ * X Coordinate system is upside down, swap to make
+ * rotations counterclockwise
+ */
+ r.xx = c;
+ r.xy = -s;
+ r.yx = s;
+ r.yy = c;
+ FcMatrixMultiply (m, &r, m);
+}
+
+void
+FcMatrixScale (FcMatrix *m, double sx, double sy)
+{
+ FcMatrix r;
+
+ r.xx = sx;
+ r.xy = 0;
+ r.yx = 0;
+ r.yy = sy;
+ FcMatrixMultiply (m, &r, m);
+}
+
+void
+FcMatrixShear (FcMatrix *m, double sh, double sv)
+{
+ FcMatrix r;
+
+ r.xx = 1;
+ r.xy = sh;
+ r.yx = sv;
+ r.yy = 1;
+ FcMatrixMultiply (m, &r, m);
+}
diff --git a/nx-X11/extras/fontconfig/src/fcname.c b/nx-X11/extras/fontconfig/src/fcname.c
new file mode 100644
index 000000000..3b9454dd4
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcname.c
@@ -0,0 +1,611 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fcname.c,v 1.15 2002/09/26 00:17:28 keithp Exp $
+ *
+ * Copyright © 2000 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include "fcint.h"
+
+static const FcObjectType _FcBaseObjectTypes[] = {
+ { FC_FAMILY, FcTypeString, },
+ { FC_FAMILYLANG, FcTypeString, },
+ { FC_STYLE, FcTypeString, },
+ { FC_STYLELANG, FcTypeString, },
+ { FC_FULLNAME, FcTypeString, },
+ { FC_FULLNAMELANG, FcTypeString, },
+ { FC_SLANT, FcTypeInteger, },
+ { FC_WEIGHT, FcTypeInteger, },
+ { FC_WIDTH, FcTypeInteger, },
+ { FC_SIZE, FcTypeDouble, },
+ { FC_ASPECT, FcTypeDouble, },
+ { FC_PIXEL_SIZE, FcTypeDouble, },
+ { FC_SPACING, FcTypeInteger, },
+ { FC_FOUNDRY, FcTypeString, },
+/* { FC_CORE, FcTypeBool, }, */
+ { FC_ANTIALIAS, FcTypeBool, },
+ { FC_HINT_STYLE, FcTypeInteger, },
+ { FC_HINTING, FcTypeBool, },
+ { FC_VERTICAL_LAYOUT, FcTypeBool, },
+ { FC_AUTOHINT, FcTypeBool, },
+ { FC_GLOBAL_ADVANCE, FcTypeBool, },
+/* { FC_XLFD, FcTypeString, }, */
+ { FC_FILE, FcTypeString, },
+ { FC_INDEX, FcTypeInteger, },
+ { FC_RASTERIZER, FcTypeString, },
+ { FC_OUTLINE, FcTypeBool, },
+ { FC_SCALABLE, FcTypeBool, },
+ { FC_DPI, FcTypeDouble },
+ { FC_RGBA, FcTypeInteger, },
+ { FC_SCALE, FcTypeDouble, },
+/* { FC_RENDER, FcTypeBool, },*/
+ { FC_MINSPACE, FcTypeBool, },
+ { FC_CHAR_WIDTH, FcTypeInteger },
+ { FC_CHAR_HEIGHT, FcTypeInteger },
+ { FC_MATRIX, FcTypeMatrix },
+ { FC_CHARSET, FcTypeCharSet },
+ { FC_LANG, FcTypeLangSet },
+ { FC_FONTVERSION, FcTypeInteger },
+ { FC_CAPABILITY, FcTypeString },
+ { FC_FONTFORMAT, FcTypeString },
+ { FC_EMBOLDEN, FcTypeBool },
+};
+
+#define NUM_OBJECT_TYPES (sizeof _FcBaseObjectTypes / sizeof _FcBaseObjectTypes[0])
+
+typedef struct _FcObjectTypeList FcObjectTypeList;
+
+struct _FcObjectTypeList {
+ const FcObjectTypeList *next;
+ const FcObjectType *types;
+ int ntypes;
+};
+
+static const FcObjectTypeList _FcBaseObjectTypesList = {
+ 0,
+ _FcBaseObjectTypes,
+ NUM_OBJECT_TYPES
+};
+
+static const FcObjectTypeList *_FcObjectTypes = &_FcBaseObjectTypesList;
+
+FcBool
+FcNameRegisterObjectTypes (const FcObjectType *types, int ntypes)
+{
+ FcObjectTypeList *l;
+
+ l = (FcObjectTypeList *) malloc (sizeof (FcObjectTypeList));
+ if (!l)
+ return FcFalse;
+ FcMemAlloc (FC_MEM_OBJECTTYPE, sizeof (FcObjectTypeList));
+ l->types = types;
+ l->ntypes = ntypes;
+ l->next = _FcObjectTypes;
+ _FcObjectTypes = l;
+ return FcTrue;
+}
+
+FcBool
+FcNameUnregisterObjectTypes (const FcObjectType *types, int ntypes)
+{
+ const FcObjectTypeList *l, **prev;
+
+ for (prev = &_FcObjectTypes;
+ (l = *prev);
+ prev = (const FcObjectTypeList **) &(l->next))
+ {
+ if (l->types == types && l->ntypes == ntypes)
+ {
+ *prev = l->next;
+ FcMemFree (FC_MEM_OBJECTTYPE, sizeof (FcObjectTypeList));
+ free ((void *) l);
+ return FcTrue;
+ }
+ }
+ return FcFalse;
+}
+
+const FcObjectType *
+FcNameGetObjectType (const char *object)
+{
+ int i;
+ const FcObjectTypeList *l;
+ const FcObjectType *t;
+
+ for (l = _FcObjectTypes; l; l = l->next)
+ {
+ for (i = 0; i < l->ntypes; i++)
+ {
+ t = &l->types[i];
+ if (!strcmp (object, t->object))
+ return t;
+ }
+ }
+ return 0;
+}
+
+static const FcConstant _FcBaseConstants[] = {
+ { (FcChar8 *) "thin", "weight", FC_WEIGHT_THIN, },
+ { (FcChar8 *) "extralight", "weight", FC_WEIGHT_EXTRALIGHT, },
+ { (FcChar8 *) "ultralight", "weight", FC_WEIGHT_EXTRALIGHT, },
+ { (FcChar8 *) "light", "weight", FC_WEIGHT_LIGHT, },
+ { (FcChar8 *) "book", "weight", FC_WEIGHT_BOOK, },
+ { (FcChar8 *) "regular", "weight", FC_WEIGHT_REGULAR, },
+ { (FcChar8 *) "medium", "weight", FC_WEIGHT_MEDIUM, },
+ { (FcChar8 *) "demibold", "weight", FC_WEIGHT_DEMIBOLD, },
+ { (FcChar8 *) "semibold", "weight", FC_WEIGHT_DEMIBOLD, },
+ { (FcChar8 *) "bold", "weight", FC_WEIGHT_BOLD, },
+ { (FcChar8 *) "extrabold", "weight", FC_WEIGHT_EXTRABOLD, },
+ { (FcChar8 *) "ultrabold", "weight", FC_WEIGHT_EXTRABOLD, },
+ { (FcChar8 *) "black", "weight", FC_WEIGHT_BLACK, },
+
+ { (FcChar8 *) "roman", "slant", FC_SLANT_ROMAN, },
+ { (FcChar8 *) "italic", "slant", FC_SLANT_ITALIC, },
+ { (FcChar8 *) "oblique", "slant", FC_SLANT_OBLIQUE, },
+
+ { (FcChar8 *) "ultracondensed", "width", FC_WIDTH_ULTRACONDENSED },
+ { (FcChar8 *) "extracondensed", "width", FC_WIDTH_EXTRACONDENSED },
+ { (FcChar8 *) "condensed", "width", FC_WIDTH_CONDENSED },
+ { (FcChar8 *) "semicondensed", "width", FC_WIDTH_SEMICONDENSED },
+ { (FcChar8 *) "normal", "width", FC_WIDTH_NORMAL },
+ { (FcChar8 *) "semiexpanded", "width", FC_WIDTH_SEMIEXPANDED },
+ { (FcChar8 *) "expanded", "width", FC_WIDTH_EXPANDED },
+ { (FcChar8 *) "extraexpanded", "width", FC_WIDTH_EXTRAEXPANDED },
+ { (FcChar8 *) "ultraexpanded", "width", FC_WIDTH_ULTRAEXPANDED },
+
+ { (FcChar8 *) "proportional", "spacing", FC_PROPORTIONAL, },
+ { (FcChar8 *) "dual", "spacing", FC_DUAL, },
+ { (FcChar8 *) "mono", "spacing", FC_MONO, },
+ { (FcChar8 *) "charcell", "spacing", FC_CHARCELL, },
+
+ { (FcChar8 *) "unknown", "rgba", FC_RGBA_UNKNOWN },
+ { (FcChar8 *) "rgb", "rgba", FC_RGBA_RGB, },
+ { (FcChar8 *) "bgr", "rgba", FC_RGBA_BGR, },
+ { (FcChar8 *) "vrgb", "rgba", FC_RGBA_VRGB },
+ { (FcChar8 *) "vbgr", "rgba", FC_RGBA_VBGR },
+ { (FcChar8 *) "none", "rgba", FC_RGBA_NONE },
+
+ { (FcChar8 *) "hintnone", "hintstyle", FC_HINT_NONE },
+ { (FcChar8 *) "hintslight", "hintstyle", FC_HINT_SLIGHT },
+ { (FcChar8 *) "hintmedium", "hintstyle", FC_HINT_MEDIUM },
+ { (FcChar8 *) "hintfull", "hintstyle", FC_HINT_FULL },
+};
+
+#define NUM_FC_CONSTANTS (sizeof _FcBaseConstants/sizeof _FcBaseConstants[0])
+
+typedef struct _FcConstantList FcConstantList;
+
+struct _FcConstantList {
+ const FcConstantList *next;
+ const FcConstant *consts;
+ int nconsts;
+};
+
+static const FcConstantList _FcBaseConstantList = {
+ 0,
+ _FcBaseConstants,
+ NUM_FC_CONSTANTS
+};
+
+static const FcConstantList *_FcConstants = &_FcBaseConstantList;
+
+FcBool
+FcNameRegisterConstants (const FcConstant *consts, int nconsts)
+{
+ FcConstantList *l;
+
+ l = (FcConstantList *) malloc (sizeof (FcConstantList));
+ if (!l)
+ return FcFalse;
+ FcMemAlloc (FC_MEM_CONSTANT, sizeof (FcConstantList));
+ l->consts = consts;
+ l->nconsts = nconsts;
+ l->next = _FcConstants;
+ _FcConstants = l;
+ return FcTrue;
+}
+
+FcBool
+FcNameUnregisterConstants (const FcConstant *consts, int nconsts)
+{
+ const FcConstantList *l, **prev;
+
+ for (prev = &_FcConstants;
+ (l = *prev);
+ prev = (const FcConstantList **) &(l->next))
+ {
+ if (l->consts == consts && l->nconsts == nconsts)
+ {
+ *prev = l->next;
+ FcMemFree (FC_MEM_CONSTANT, sizeof (FcConstantList));
+ free ((void *) l);
+ return FcTrue;
+ }
+ }
+ return FcFalse;
+}
+
+const FcConstant *
+FcNameGetConstant (FcChar8 *string)
+{
+ const FcConstantList *l;
+ int i;
+
+ for (l = _FcConstants; l; l = l->next)
+ {
+ for (i = 0; i < l->nconsts; i++)
+ if (!FcStrCmpIgnoreCase (string, l->consts[i].name))
+ return &l->consts[i];
+ }
+ return 0;
+}
+
+FcBool
+FcNameConstant (FcChar8 *string, int *result)
+{
+ const FcConstant *c;
+
+ if ((c = FcNameGetConstant(string)))
+ {
+ *result = c->value;
+ return FcTrue;
+ }
+ return FcFalse;
+}
+
+FcBool
+FcNameBool (const FcChar8 *v, FcBool *result)
+{
+ char c0, c1;
+
+ c0 = *v;
+ c0 = FcToLower (c0);
+ if (c0 == 't' || c0 == 'y' || c0 == '1')
+ {
+ *result = FcTrue;
+ return FcTrue;
+ }
+ if (c0 == 'f' || c0 == 'n' || c0 == '0')
+ {
+ *result = FcFalse;
+ return FcTrue;
+ }
+ if (c0 == 'o')
+ {
+ c1 = v[1];
+ c1 = FcToLower (c1);
+ if (c1 == 'n')
+ {
+ *result = FcTrue;
+ return FcTrue;
+ }
+ if (c1 == 'f')
+ {
+ *result = FcFalse;
+ return FcTrue;
+ }
+ }
+ return FcFalse;
+}
+
+static FcValue
+FcNameConvert (FcType type, FcChar8 *string, FcMatrix *m)
+{
+ FcValue v;
+
+ v.type = type;
+ switch (v.type) {
+ case FcTypeInteger:
+ if (!FcNameConstant (string, &v.u.i))
+ v.u.i = atoi ((char *) string);
+ break;
+ case FcTypeString:
+ v.u.s = string;
+ break;
+ case FcTypeBool:
+ if (!FcNameBool (string, &v.u.b))
+ v.u.b = FcFalse;
+ break;
+ case FcTypeDouble:
+ v.u.d = strtod ((char *) string, 0);
+ break;
+ case FcTypeMatrix:
+ v.u.m = m;
+ sscanf ((char *) string, "%lg %lg %lg %lg", &m->xx, &m->xy, &m->yx, &m->yy);
+ break;
+ case FcTypeCharSet:
+ v.u.c = FcNameParseCharSet (string);
+ break;
+ case FcTypeLangSet:
+ v.u.l = FcNameParseLangSet (string);
+ break;
+ default:
+ break;
+ }
+ return v;
+}
+
+static const FcChar8 *
+FcNameFindNext (const FcChar8 *cur, const char *delim, FcChar8 *save, FcChar8 *last)
+{
+ FcChar8 c;
+
+ while ((c = *cur))
+ {
+ if (c == '\\')
+ {
+ ++cur;
+ if (!(c = *cur))
+ break;
+ }
+ else if (strchr (delim, c))
+ break;
+ ++cur;
+ *save++ = c;
+ }
+ *save = 0;
+ *last = *cur;
+ if (*cur)
+ cur++;
+ return cur;
+}
+
+FcPattern *
+FcNameParse (const FcChar8 *name)
+{
+ FcChar8 *save;
+ FcPattern *pat;
+ double d;
+ FcChar8 *e;
+ FcChar8 delim;
+ FcValue v;
+ FcMatrix m;
+ const FcObjectType *t;
+ const FcConstant *c;
+
+ /* freed below */
+ save = malloc (strlen ((char *) name) + 1);
+ if (!save)
+ goto bail0;
+ pat = FcPatternCreate ();
+ if (!pat)
+ goto bail1;
+
+ for (;;)
+ {
+ name = FcNameFindNext (name, "-,:", save, &delim);
+ if (save[0])
+ {
+ if (!FcPatternAddString (pat, FC_FAMILY, save))
+ goto bail2;
+ }
+ if (delim != ',')
+ break;
+ }
+ if (delim == '-')
+ {
+ for (;;)
+ {
+ name = FcNameFindNext (name, "-,:", save, &delim);
+ d = strtod ((char *) save, (char **) &e);
+ if (e != save)
+ {
+ if (!FcPatternAddDouble (pat, FC_SIZE, d))
+ goto bail2;
+ }
+ if (delim != ',')
+ break;
+ }
+ }
+ while (delim == ':')
+ {
+ name = FcNameFindNext (name, "=_:", save, &delim);
+ if (save[0])
+ {
+ if (delim == '=' || delim == '_')
+ {
+ t = FcNameGetObjectType ((char *) save);
+ for (;;)
+ {
+ name = FcNameFindNext (name, ":,", save, &delim);
+ if (t)
+ {
+ v = FcNameConvert (t->type, save, &m);
+ if (!FcPatternAdd (pat, t->object, v, FcTrue))
+ {
+ switch (v.type) {
+ case FcTypeCharSet:
+ FcCharSetDestroy ((FcCharSet *) v.u.c);
+ break;
+ case FcTypeLangSet:
+ FcLangSetDestroy ((FcLangSet *) v.u.l);
+ break;
+ default:
+ break;
+ }
+ goto bail2;
+ }
+ switch (v.type) {
+ case FcTypeCharSet:
+ FcCharSetDestroy ((FcCharSet *) v.u.c);
+ break;
+ case FcTypeLangSet:
+ FcLangSetDestroy ((FcLangSet *) v.u.l);
+ break;
+ default:
+ break;
+ }
+ }
+ if (delim != ',')
+ break;
+ }
+ }
+ else
+ {
+ if ((c = FcNameGetConstant (save)))
+ {
+ if (!FcPatternAddInteger (pat, c->object, c->value))
+ goto bail2;
+ }
+ }
+ }
+ }
+
+ free (save);
+ return pat;
+
+bail2:
+ FcPatternDestroy (pat);
+bail1:
+ free (save);
+bail0:
+ return 0;
+}
+static FcBool
+FcNameUnparseString (FcStrBuf *buf,
+ const FcChar8 *string,
+ const FcChar8 *escape)
+{
+ FcChar8 c;
+ while ((c = *string++))
+ {
+ if (escape && strchr ((char *) escape, (char) c))
+ {
+ if (!FcStrBufChar (buf, escape[0]))
+ return FcFalse;
+ }
+ if (!FcStrBufChar (buf, c))
+ return FcFalse;
+ }
+ return FcTrue;
+}
+
+static FcBool
+FcNameUnparseValue (FcStrBuf *buf,
+ FcValue v,
+ FcChar8 *escape)
+{
+ FcChar8 temp[1024];
+
+ switch (v.type) {
+ case FcTypeVoid:
+ return FcTrue;
+ case FcTypeInteger:
+ sprintf ((char *) temp, "%d", v.u.i);
+ return FcNameUnparseString (buf, temp, 0);
+ case FcTypeDouble:
+ sprintf ((char *) temp, "%g", v.u.d);
+ return FcNameUnparseString (buf, temp, 0);
+ case FcTypeString:
+ return FcNameUnparseString (buf, v.u.s, escape);
+ case FcTypeBool:
+ return FcNameUnparseString (buf, v.u.b ? (FcChar8 *) "True" : (FcChar8 *) "False", 0);
+ case FcTypeMatrix:
+ sprintf ((char *) temp, "%g %g %g %g",
+ v.u.m->xx, v.u.m->xy, v.u.m->yx, v.u.m->yy);
+ return FcNameUnparseString (buf, temp, 0);
+ case FcTypeCharSet:
+ return FcNameUnparseCharSet (buf, v.u.c);
+ case FcTypeLangSet:
+ return FcNameUnparseLangSet (buf, v.u.l);
+ case FcTypeFTFace:
+ return FcTrue;
+ }
+ return FcFalse;
+}
+
+static FcBool
+FcNameUnparseValueList (FcStrBuf *buf,
+ FcValueList *v,
+ FcChar8 *escape)
+{
+ while (v)
+ {
+ if (!FcNameUnparseValue (buf, v->value, escape))
+ return FcFalse;
+ if ((v = v->next))
+ if (!FcNameUnparseString (buf, (FcChar8 *) ",", 0))
+ return FcFalse;
+ }
+ return FcTrue;
+}
+
+#define FC_ESCAPE_FIXED "\\-:,"
+#define FC_ESCAPE_VARIABLE "\\=_:,"
+
+FcChar8 *
+FcNameUnparse (FcPattern *pat)
+{
+ FcStrBuf buf;
+ FcChar8 buf_static[8192];
+ int i;
+ FcPatternElt *e;
+ const FcObjectTypeList *l;
+ const FcObjectType *o;
+
+ FcStrBufInit (&buf, buf_static, sizeof (buf_static));
+ e = FcPatternFindElt (pat, FC_FAMILY);
+ if (e)
+ {
+ if (!FcNameUnparseValueList (&buf, e->values, (FcChar8 *) FC_ESCAPE_FIXED))
+ goto bail0;
+ }
+ e = FcPatternFindElt (pat, FC_SIZE);
+ if (e)
+ {
+ if (!FcNameUnparseString (&buf, (FcChar8 *) "-", 0))
+ goto bail0;
+ if (!FcNameUnparseValueList (&buf, e->values, (FcChar8 *) FC_ESCAPE_FIXED))
+ goto bail0;
+ }
+ for (l = _FcObjectTypes; l; l = l->next)
+ {
+ for (i = 0; i < l->ntypes; i++)
+ {
+ o = &l->types[i];
+ if (!strcmp (o->object, FC_FAMILY) ||
+ !strcmp (o->object, FC_SIZE) ||
+ !strcmp (o->object, FC_FILE))
+ continue;
+
+ e = FcPatternFindElt (pat, o->object);
+ if (e)
+ {
+ if (!FcNameUnparseString (&buf, (FcChar8 *) ":", 0))
+ goto bail0;
+ if (!FcNameUnparseString (&buf, (FcChar8 *) o->object, (FcChar8 *) FC_ESCAPE_VARIABLE))
+ goto bail0;
+ if (!FcNameUnparseString (&buf, (FcChar8 *) "=", 0))
+ goto bail0;
+ if (!FcNameUnparseValueList (&buf, e->values,
+ (FcChar8 *) FC_ESCAPE_VARIABLE))
+ goto bail0;
+ }
+ }
+ }
+ return FcStrBufDone (&buf);
+bail0:
+ FcStrBufDestroy (&buf);
+ return 0;
+}
diff --git a/nx-X11/extras/fontconfig/src/fcpat.c b/nx-X11/extras/fontconfig/src/fcpat.c
new file mode 100644
index 000000000..c886c9258
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcpat.c
@@ -0,0 +1,1202 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fcpat.c,v 1.18 2002/09/18 17:11:46 tsi Exp $
+ *
+ * Copyright © 2000 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "fcint.h"
+
+FcPattern *
+FcPatternCreate (void)
+{
+ FcPattern *p;
+
+ p = (FcPattern *) malloc (sizeof (FcPattern));
+ if (!p)
+ return 0;
+ FcMemAlloc (FC_MEM_PATTERN, sizeof (FcPattern));
+ p->num = 0;
+ p->size = 0;
+ p->elts = 0;
+ p->ref = 1;
+ return p;
+}
+
+void
+FcValueDestroy (FcValue v)
+{
+ switch (v.type) {
+ case FcTypeString:
+ FcStrFree ((FcChar8 *) v.u.s);
+ break;
+ case FcTypeMatrix:
+ FcMatrixFree ((FcMatrix *) v.u.m);
+ break;
+ case FcTypeCharSet:
+ FcCharSetDestroy ((FcCharSet *) v.u.c);
+ break;
+ case FcTypeLangSet:
+ FcLangSetDestroy ((FcLangSet *) v.u.l);
+ break;
+ default:
+ break;
+ }
+}
+
+FcValue
+FcValueSave (FcValue v)
+{
+ switch (v.type) {
+ case FcTypeString:
+ v.u.s = FcStrCopy (v.u.s);
+ if (!v.u.s)
+ v.type = FcTypeVoid;
+ break;
+ case FcTypeMatrix:
+ v.u.m = FcMatrixCopy (v.u.m);
+ if (!v.u.m)
+ v.type = FcTypeVoid;
+ break;
+ case FcTypeCharSet:
+ v.u.c = FcCharSetCopy ((FcCharSet *) v.u.c);
+ if (!v.u.c)
+ v.type = FcTypeVoid;
+ break;
+ case FcTypeLangSet:
+ v.u.l = FcLangSetCopy (v.u.l);
+ if (!v.u.l)
+ v.type = FcTypeVoid;
+ break;
+ default:
+ break;
+ }
+ return v;
+}
+
+void
+FcValueListDestroy (FcValueList *l)
+{
+ FcValueList *next;
+ for (; l; l = next)
+ {
+ switch (l->value.type) {
+ case FcTypeString:
+ FcStrFree ((FcChar8 *) l->value.u.s);
+ break;
+ case FcTypeMatrix:
+ FcMatrixFree ((FcMatrix *) l->value.u.m);
+ break;
+ case FcTypeCharSet:
+ FcCharSetDestroy ((FcCharSet *) l->value.u.c);
+ break;
+ case FcTypeLangSet:
+ FcLangSetDestroy ((FcLangSet *) l->value.u.l);
+ break;
+ default:
+ break;
+ }
+ next = l->next;
+ FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
+ free (l);
+ }
+}
+
+FcBool
+FcValueEqual (FcValue va, FcValue vb)
+{
+ if (va.type != vb.type)
+ {
+ if (va.type == FcTypeInteger)
+ {
+ va.type = FcTypeDouble;
+ va.u.d = va.u.i;
+ }
+ if (vb.type == FcTypeInteger)
+ {
+ vb.type = FcTypeDouble;
+ vb.u.d = vb.u.i;
+ }
+ if (va.type != vb.type)
+ return FcFalse;
+ }
+ switch (va.type) {
+ case FcTypeVoid:
+ return FcTrue;
+ case FcTypeInteger:
+ return va.u.i == vb.u.i;
+ case FcTypeDouble:
+ return va.u.d == vb.u.d;
+ case FcTypeString:
+ return FcStrCmpIgnoreCase (va.u.s, vb.u.s) == 0;
+ case FcTypeBool:
+ return va.u.b == vb.u.b;
+ case FcTypeMatrix:
+ return FcMatrixEqual (va.u.m, vb.u.m);
+ case FcTypeCharSet:
+ return FcCharSetEqual (va.u.c, vb.u.c);
+ case FcTypeFTFace:
+ return va.u.f == vb.u.f;
+ case FcTypeLangSet:
+ return FcLangSetEqual (va.u.l, vb.u.l);
+ }
+ return FcFalse;
+}
+
+static FcChar32
+FcDoubleHash (double d)
+{
+ if (d < 0)
+ d = -d;
+ if (d > 0xffffffff)
+ d = 0xffffffff;
+ return (FcChar32) d;
+}
+
+static FcChar32
+FcStringHash (const FcChar8 *s)
+{
+ FcChar8 c;
+ FcChar32 h = 0;
+
+ if (s)
+ while ((c = *s++))
+ h = ((h << 1) | (h >> 31)) ^ c;
+ return h;
+}
+
+static FcChar32
+FcValueHash (FcValue v)
+{
+ switch (v.type) {
+ case FcTypeVoid:
+ return 0;
+ case FcTypeInteger:
+ return (FcChar32) v.u.i;
+ case FcTypeDouble:
+ return FcDoubleHash (v.u.d);
+ case FcTypeString:
+ return FcStringHash (v.u.s);
+ case FcTypeBool:
+ return (FcChar32) v.u.b;
+ case FcTypeMatrix:
+ return (FcDoubleHash (v.u.m->xx) ^
+ FcDoubleHash (v.u.m->xy) ^
+ FcDoubleHash (v.u.m->yx) ^
+ FcDoubleHash (v.u.m->yy));
+ case FcTypeCharSet:
+ return (FcChar32) v.u.c->num;
+ case FcTypeFTFace:
+ return FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->family_name) ^
+ FcStringHash ((const FcChar8 *) ((FT_Face) v.u.f)->style_name);
+ case FcTypeLangSet:
+ return FcLangSetHash (v.u.l);
+ }
+ return FcFalse;
+}
+
+static FcBool
+FcValueListEqual (FcValueList *la, FcValueList *lb)
+{
+ if (la == lb)
+ return FcTrue;
+
+ while (la && lb)
+ {
+ if (!FcValueEqual (la->value, lb->value))
+ return FcFalse;
+ la = la->next;
+ lb = lb->next;
+ }
+ if (la || lb)
+ return FcFalse;
+ return FcTrue;
+}
+
+static FcChar32
+FcValueListHash (FcValueList *l)
+{
+ FcChar32 hash = 0;
+
+ while (l)
+ {
+ hash = ((hash << 1) | (hash >> 31)) ^ FcValueHash (l->value);
+ l = l->next;
+ }
+ return hash;
+}
+
+void
+FcPatternDestroy (FcPattern *p)
+{
+ int i;
+
+ if (p->ref == FC_REF_CONSTANT || --p->ref > 0)
+ return;
+
+ for (i = 0; i < p->num; i++)
+ FcValueListDestroy (p->elts[i].values);
+
+ p->num = 0;
+ if (p->elts)
+ {
+ FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
+ free (p->elts);
+ p->elts = 0;
+ }
+ p->size = 0;
+ FcMemFree (FC_MEM_PATTERN, sizeof (FcPattern));
+ free (p);
+}
+
+#define FC_VALUE_LIST_HASH_SIZE 257
+#define FC_PATTERN_HASH_SIZE 67
+
+typedef struct _FcValueListEnt FcValueListEnt;
+
+struct _FcValueListEnt {
+ FcValueListEnt *next;
+ FcValueList *list;
+ FcChar32 hash, pad;
+};
+
+typedef union _FcValueListAlign {
+ FcValueListEnt ent;
+ FcValueList list;
+} FcValueListAlign;
+
+static int FcValueListFrozenCount[FcTypeLangSet + 1];
+static int FcValueListFrozenBytes[FcTypeLangSet + 1];
+static char *FcValueListFrozenName[] = {
+ "Void",
+ "Integer",
+ "Double",
+ "String",
+ "Bool",
+ "Matrix",
+ "CharSet",
+ "FTFace",
+ "LangSet"
+};
+
+void
+FcValueListReport (void);
+
+void
+FcValueListReport (void)
+{
+ FcType t;
+
+ printf ("Fc Frozen Values:\n");
+ printf ("\t%8s %9s %9s\n", "Type", "Count", "Bytes");
+ for (t = FcTypeVoid; t <= FcTypeLangSet; t++)
+ printf ("\t%8s %9d %9d\n", FcValueListFrozenName[t],
+ FcValueListFrozenCount[t], FcValueListFrozenBytes[t]);
+}
+
+static FcValueListEnt *
+FcValueListEntCreate (FcValueList *h)
+{
+ FcValueListAlign *ea;
+ FcValueListEnt *e;
+ FcValueList *l, *new;
+ int n;
+ int size;
+
+ n = 0;
+ for (l = h; l; l = l->next)
+ n++;
+ size = sizeof (FcValueListAlign) + n * sizeof (FcValueList);
+ FcValueListFrozenCount[h->value.type]++;
+ FcValueListFrozenBytes[h->value.type] += size;
+ ea = malloc (size);
+ if (!ea)
+ return 0;
+ FcMemAlloc (FC_MEM_VALLIST, size);
+ e = &ea->ent;
+ e->list = (FcValueList *) (ea + 1);
+ new = e->list;
+ for (l = h; l; l = l->next, new++)
+ {
+ if (l->value.type == FcTypeString)
+ {
+ new->value.type = FcTypeString;
+ new->value.u.s = FcObjectStaticName (l->value.u.s);
+ }
+ else
+ {
+ new->value = FcValueSave (l->value);
+ }
+ new->binding = l->binding;
+ if (l->next)
+ new->next = new + 1;
+ else
+ new->next = 0;
+ }
+ return e;
+}
+
+static void
+FcValueListEntDestroy (FcValueListEnt *e)
+{
+ FcValueList *l;
+
+ FcValueListFrozenCount[e->list->value.type]--;
+
+ /* XXX: We should perform these two operations with "size" as
+ computed in FcValueListEntCreate, but we don't have access to
+ that value here. Without this, the FcValueListFrozenBytes
+ values will be wrong as will the FcMemFree counts.
+
+ FcValueListFrozenBytes[e->list->value.type] -= size;
+ FcMemFree (FC_MEM_VALLIST, size);
+ */
+
+ for (l = e->list; l; l = l->next)
+ {
+ if (l->value.type != FcTypeString)
+ FcValueDestroy (l->value);
+ }
+ /* XXX: Are we being too chummy with the implementation here to
+ free(e) when it was actually the enclosing FcValueListAlign
+ that was allocated? */
+ free (e);
+}
+
+static int FcValueListTotal;
+static int FcValueListUsed;
+
+static FcValueListEnt *FcValueListHashTable[FC_VALUE_LIST_HASH_SIZE];
+
+static FcValueList *
+FcValueListFreeze (FcValueList *l)
+{
+ FcChar32 hash = FcValueListHash (l);
+ FcValueListEnt **bucket = &FcValueListHashTable[hash % FC_VALUE_LIST_HASH_SIZE];
+ FcValueListEnt *ent;
+
+ FcValueListTotal++;
+ for (ent = *bucket; ent; ent = ent->next)
+ {
+ if (ent->hash == hash && FcValueListEqual (ent->list, l))
+ return ent->list;
+ }
+
+ ent = FcValueListEntCreate (l);
+ if (!ent)
+ return 0;
+
+ FcValueListUsed++;
+ ent->hash = hash;
+ ent->next = *bucket;
+ *bucket = ent;
+ return ent->list;
+}
+
+static void
+FcValueListThawAll (void)
+{
+ int i;
+ FcValueListEnt *ent, *next;
+
+ for (i = 0; i < FC_VALUE_LIST_HASH_SIZE; i++)
+ {
+ for (ent = FcValueListHashTable[i]; ent; ent = next)
+ {
+ next = ent->next;
+ FcValueListEntDestroy (ent);
+ }
+ FcValueListHashTable[i] = 0;
+ }
+
+ FcValueListTotal = 0;
+ FcValueListUsed = 0;
+}
+
+static FcChar32
+FcPatternBaseHash (FcPattern *b)
+{
+ FcChar32 hash = b->num;
+ int i;
+
+ for (i = 0; i < b->num; i++)
+ hash = ((hash << 1) | (hash >> 31)) ^ ((long) b->elts[i].values);
+ return hash;
+}
+
+typedef struct _FcPatternEnt FcPatternEnt;
+
+struct _FcPatternEnt {
+ FcPatternEnt *next;
+ FcChar32 hash;
+ FcPattern pattern;
+};
+
+static int FcPatternTotal;
+static int FcPatternUsed;
+
+static FcPatternEnt *FcPatternHashTable[FC_VALUE_LIST_HASH_SIZE];
+
+static FcPattern *
+FcPatternBaseFreeze (FcPattern *b)
+{
+ FcChar32 hash = FcPatternBaseHash (b);
+ FcPatternEnt **bucket = &FcPatternHashTable[hash % FC_VALUE_LIST_HASH_SIZE];
+ FcPatternEnt *ent;
+ int i;
+ int size;
+
+ FcPatternTotal++;
+ for (ent = *bucket; ent; ent = ent->next)
+ {
+ if (ent->hash == hash && b->num == ent->pattern.num)
+ {
+ for (i = 0; i < b->num; i++)
+ {
+ if (b->elts[i].object != ent->pattern.elts[i].object)
+ break;
+ if (b->elts[i].values != ent->pattern.elts[i].values)
+ break;
+ }
+ if (i == b->num)
+ return &ent->pattern;
+ }
+ }
+
+ /*
+ * Compute size of pattern + elts
+ */
+ size = sizeof (FcPatternEnt) + b->num*sizeof (FcPatternElt);
+ ent = malloc (size);
+ if (!ent)
+ return 0;
+
+ FcMemAlloc (FC_MEM_PATTERN, size);
+ FcPatternUsed++;
+
+ ent->pattern.elts = (FcPatternElt *) (ent + 1);
+ ent->pattern.num = b->num;
+ ent->pattern.size = b->num;
+ ent->pattern.ref = FC_REF_CONSTANT;
+
+ for (i = 0; i < b->num; i++)
+ {
+ ent->pattern.elts[i].values = b->elts[i].values;
+ ent->pattern.elts[i].object = b->elts[i].object;
+ }
+
+ ent->hash = hash;
+ ent->next = *bucket;
+ *bucket = ent;
+ return &ent->pattern;
+}
+
+static void
+FcPatternBaseThawAll (void)
+{
+ int i;
+ FcPatternEnt *ent, *next;
+
+ for (i = 0; i < FC_VALUE_LIST_HASH_SIZE; i++)
+ {
+ for (ent = FcPatternHashTable[i]; ent; ent = next)
+ {
+ next = ent->next;
+ free (ent);
+ }
+ FcPatternHashTable[i] = 0;
+ }
+
+ FcPatternTotal = 0;
+ FcPatternUsed = 0;
+}
+
+FcPattern *
+FcPatternFreeze (FcPattern *p)
+{
+ FcPattern *b, *n = 0;
+ int size;
+ int i;
+
+ if (p->ref == FC_REF_CONSTANT)
+ return p;
+
+ size = sizeof (FcPattern) + p->num * sizeof (FcPatternElt);
+ b = (FcPattern *) malloc (size);
+ if (!b)
+ return 0;
+ FcMemAlloc (FC_MEM_PATTERN, size);
+ b->num = p->num;
+ b->size = b->num;
+ b->ref = 1;
+ b->elts = (FcPatternElt *) (b + 1);
+ /*
+ * Freeze object lists
+ */
+ for (i = 0; i < p->num; i++)
+ {
+ b->elts[i].object = p->elts[i].object;
+ b->elts[i].values = FcValueListFreeze (p->elts[i].values);
+ if (!b->elts[i].values)
+ goto bail;
+ }
+ /*
+ * Freeze base
+ */
+ n = FcPatternBaseFreeze (b);
+#ifdef CHATTY
+ if (FcDebug() & FC_DBG_MEMORY)
+ {
+ printf ("ValueLists: total %9d used %9d\n", FcValueListTotal, FcValueListUsed);
+ printf ("Patterns: total %9d used %9d\n", FcPatternTotal, FcPatternUsed);
+ }
+#endif
+bail:
+ free (b);
+#ifdef DEBUG
+ assert (FcPatternEqual (n, p));
+#endif
+ return n;
+}
+
+void
+FcPatternThawAll (void)
+{
+ FcPatternBaseThawAll ();
+ FcValueListThawAll ();
+}
+
+static int
+FcPatternPosition (const FcPattern *p, const char *object)
+{
+ int low, high, mid, c;
+
+ object = FcObjectStaticName(object);
+ low = 0;
+ high = p->num - 1;
+ c = 1;
+ mid = 0;
+ while (low <= high)
+ {
+ mid = (low + high) >> 1;
+ c = p->elts[mid].object - object;
+ if (c == 0)
+ return mid;
+ if (c < 0)
+ low = mid + 1;
+ else
+ high = mid - 1;
+ }
+ if (c < 0)
+ mid++;
+ return -(mid + 1);
+}
+
+FcPatternElt *
+FcPatternFindElt (const FcPattern *p, const char *object)
+{
+ int i = FcPatternPosition (p, object);
+ if (i < 0)
+ return 0;
+ return &p->elts[i];
+}
+
+FcPatternElt *
+FcPatternInsertElt (FcPattern *p, const char *object)
+{
+ int i;
+ FcPatternElt *e;
+
+ i = FcPatternPosition (p, object);
+ if (i < 0)
+ {
+ i = -i - 1;
+
+ /* grow array */
+ if (p->num + 1 >= p->size)
+ {
+ int s = p->size + 16;
+ if (p->elts)
+ e = (FcPatternElt *) realloc (p->elts, s * sizeof (FcPatternElt));
+ else
+ e = (FcPatternElt *) malloc (s * sizeof (FcPatternElt));
+ if (!e)
+ return FcFalse;
+ p->elts = e;
+ if (p->size)
+ FcMemFree (FC_MEM_PATELT, p->size * sizeof (FcPatternElt));
+ FcMemAlloc (FC_MEM_PATELT, s * sizeof (FcPatternElt));
+ while (p->size < s)
+ {
+ p->elts[p->size].object = 0;
+ p->elts[p->size].values = 0;
+ p->size++;
+ }
+ }
+
+ /* move elts up */
+ memmove (p->elts + i + 1,
+ p->elts + i,
+ sizeof (FcPatternElt) *
+ (p->num - i));
+
+ /* bump count */
+ p->num++;
+
+ p->elts[i].object = FcObjectStaticName (object);
+ p->elts[i].values = 0;
+ }
+
+ return &p->elts[i];
+}
+
+FcBool
+FcPatternEqual (const FcPattern *pa, const FcPattern *pb)
+{
+ int i;
+
+ if (pa == pb)
+ return FcTrue;
+
+ if (pa->num != pb->num)
+ return FcFalse;
+ for (i = 0; i < pa->num; i++)
+ {
+ if (pa->elts[i].object != pb->elts[i].object)
+ return FcFalse;
+ if (!FcValueListEqual (pa->elts[i].values, pb->elts[i].values))
+ return FcFalse;
+ }
+ return FcTrue;
+}
+
+FcChar32
+FcPatternHash (const FcPattern *p)
+{
+ int i;
+ FcChar32 h = 0;
+
+ for (i = 0; i < p->num; i++)
+ {
+ h = (((h << 1) | (h >> 31)) ^
+ FcStringHash ((const FcChar8 *) p->elts[i].object) ^
+ FcValueListHash (p->elts[i].values));
+ }
+ return h;
+}
+
+FcBool
+FcPatternEqualSubset (const FcPattern *pa, const FcPattern *pb, const FcObjectSet *os)
+{
+ FcPatternElt *ea, *eb;
+ int i;
+
+ for (i = 0; i < os->nobject; i++)
+ {
+ ea = FcPatternFindElt (pa, os->objects[i]);
+ eb = FcPatternFindElt (pb, os->objects[i]);
+ if (ea)
+ {
+ if (!eb)
+ return FcFalse;
+ if (!FcValueListEqual (ea->values, eb->values))
+ return FcFalse;
+ }
+ else
+ {
+ if (eb)
+ return FcFalse;
+ }
+ }
+ return FcTrue;
+}
+
+FcBool
+FcPatternAddWithBinding (FcPattern *p,
+ const char *object,
+ FcValue value,
+ FcValueBinding binding,
+ FcBool append)
+{
+ FcPatternElt *e;
+ FcValueList *new, **prev;
+
+ if (p->ref == FC_REF_CONSTANT)
+ goto bail0;
+
+ new = (FcValueList *) malloc (sizeof (FcValueList));
+ if (!new)
+ goto bail0;
+
+ FcMemAlloc (FC_MEM_VALLIST, sizeof (FcValueList));
+ /* dup string */
+ value = FcValueSave (value);
+ if (value.type == FcTypeVoid)
+ goto bail1;
+
+ new->value = value;
+ new->binding = binding;
+ new->next = 0;
+
+ e = FcPatternInsertElt (p, object);
+ if (!e)
+ goto bail2;
+
+ if (append)
+ {
+ for (prev = &e->values; *prev; prev = &(*prev)->next);
+ *prev = new;
+ }
+ else
+ {
+ new->next = e->values;
+ e->values = new;
+ }
+
+ return FcTrue;
+
+bail2:
+ switch (value.type) {
+ case FcTypeString:
+ FcStrFree ((FcChar8 *) value.u.s);
+ break;
+ case FcTypeMatrix:
+ FcMatrixFree ((FcMatrix *) value.u.m);
+ break;
+ case FcTypeCharSet:
+ FcCharSetDestroy ((FcCharSet *) value.u.c);
+ break;
+ case FcTypeLangSet:
+ FcLangSetDestroy ((FcLangSet *) value.u.l);
+ break;
+ default:
+ break;
+ }
+bail1:
+ FcMemFree (FC_MEM_VALLIST, sizeof (FcValueList));
+ free (new);
+bail0:
+ return FcFalse;
+}
+
+FcBool
+FcPatternAdd (FcPattern *p, const char *object, FcValue value, FcBool append)
+{
+ return FcPatternAddWithBinding (p, object, value, FcValueBindingStrong, append);
+}
+
+FcBool
+FcPatternAddWeak (FcPattern *p, const char *object, FcValue value, FcBool append)
+{
+ return FcPatternAddWithBinding (p, object, value, FcValueBindingWeak, append);
+}
+
+FcBool
+FcPatternDel (FcPattern *p, const char *object)
+{
+ FcPatternElt *e;
+ int i;
+
+ e = FcPatternFindElt (p, object);
+ if (!e)
+ return FcFalse;
+
+ i = e - p->elts;
+
+ /* destroy value */
+ FcValueListDestroy (e->values);
+
+ /* shuffle existing ones down */
+ memmove (e, e+1, (p->elts + p->num - (e + 1)) * sizeof (FcPatternElt));
+ p->num--;
+ p->elts[p->num].object = 0;
+ p->elts[p->num].values = 0;
+ return FcTrue;
+}
+
+FcBool
+FcPatternRemove (FcPattern *p, const char *object, int id)
+{
+ FcPatternElt *e;
+ FcValueList **prev, *l;
+
+ e = FcPatternFindElt (p, object);
+ if (!e)
+ return FcFalse;
+ for (prev = &e->values; (l = *prev); prev = &l->next)
+ {
+ if (!id)
+ {
+ *prev = l->next;
+ l->next = 0;
+ FcValueListDestroy (l);
+ if (!e->values)
+ FcPatternDel (p, object);
+ return FcTrue;
+ }
+ id--;
+ }
+ return FcFalse;
+}
+
+FcBool
+FcPatternAddInteger (FcPattern *p, const char *object, int i)
+{
+ FcValue v;
+
+ v.type = FcTypeInteger;
+ v.u.i = i;
+ return FcPatternAdd (p, object, v, FcTrue);
+}
+
+FcBool
+FcPatternAddDouble (FcPattern *p, const char *object, double d)
+{
+ FcValue v;
+
+ v.type = FcTypeDouble;
+ v.u.d = d;
+ return FcPatternAdd (p, object, v, FcTrue);
+}
+
+
+FcBool
+FcPatternAddString (FcPattern *p, const char *object, const FcChar8 *s)
+{
+ FcValue v;
+
+ v.type = FcTypeString;
+ v.u.s = s;
+ return FcPatternAdd (p, object, v, FcTrue);
+}
+
+FcBool
+FcPatternAddMatrix (FcPattern *p, const char *object, const FcMatrix *s)
+{
+ FcValue v;
+
+ v.type = FcTypeMatrix;
+ v.u.m = (FcMatrix *) s;
+ return FcPatternAdd (p, object, v, FcTrue);
+}
+
+
+FcBool
+FcPatternAddBool (FcPattern *p, const char *object, FcBool b)
+{
+ FcValue v;
+
+ v.type = FcTypeBool;
+ v.u.b = b;
+ return FcPatternAdd (p, object, v, FcTrue);
+}
+
+FcBool
+FcPatternAddCharSet (FcPattern *p, const char *object, const FcCharSet *c)
+{
+ FcValue v;
+
+ v.type = FcTypeCharSet;
+ v.u.c = (FcCharSet *) c;
+ return FcPatternAdd (p, object, v, FcTrue);
+}
+
+FcBool
+FcPatternAddFTFace (FcPattern *p, const char *object, const FT_Face f)
+{
+ FcValue v;
+
+ v.type = FcTypeFTFace;
+ v.u.f = (void *) f;
+ return FcPatternAdd (p, object, v, FcTrue);
+}
+
+FcBool
+FcPatternAddLangSet (FcPattern *p, const char *object, const FcLangSet *ls)
+{
+ FcValue v;
+
+ v.type = FcTypeLangSet;
+ v.u.l = (FcLangSet *) ls;
+ return FcPatternAdd (p, object, v, FcTrue);
+}
+
+FcResult
+FcPatternGet (const FcPattern *p, const char *object, int id, FcValue *v)
+{
+ FcPatternElt *e;
+ FcValueList *l;
+
+ e = FcPatternFindElt (p, object);
+ if (!e)
+ return FcResultNoMatch;
+ for (l = e->values; l; l = l->next)
+ {
+ if (!id)
+ {
+ *v = l->value;
+ return FcResultMatch;
+ }
+ id--;
+ }
+ return FcResultNoId;
+}
+
+FcResult
+FcPatternGetInteger (const FcPattern *p, const char *object, int id, int *i)
+{
+ FcValue v;
+ FcResult r;
+
+ r = FcPatternGet (p, object, id, &v);
+ if (r != FcResultMatch)
+ return r;
+ switch (v.type) {
+ case FcTypeDouble:
+ *i = (int) v.u.d;
+ break;
+ case FcTypeInteger:
+ *i = v.u.i;
+ break;
+ default:
+ return FcResultTypeMismatch;
+ }
+ return FcResultMatch;
+}
+
+FcResult
+FcPatternGetDouble (const FcPattern *p, const char *object, int id, double *d)
+{
+ FcValue v;
+ FcResult r;
+
+ r = FcPatternGet (p, object, id, &v);
+ if (r != FcResultMatch)
+ return r;
+ switch (v.type) {
+ case FcTypeDouble:
+ *d = v.u.d;
+ break;
+ case FcTypeInteger:
+ *d = (double) v.u.i;
+ break;
+ default:
+ return FcResultTypeMismatch;
+ }
+ return FcResultMatch;
+}
+
+FcResult
+FcPatternGetString (const FcPattern *p, const char *object, int id, FcChar8 ** s)
+{
+ FcValue v;
+ FcResult r;
+
+ r = FcPatternGet (p, object, id, &v);
+ if (r != FcResultMatch)
+ return r;
+ if (v.type != FcTypeString)
+ return FcResultTypeMismatch;
+ *s = (FcChar8 *) v.u.s;
+ return FcResultMatch;
+}
+
+FcResult
+FcPatternGetMatrix(const FcPattern *p, const char *object, int id, FcMatrix **m)
+{
+ FcValue v;
+ FcResult r;
+
+ r = FcPatternGet (p, object, id, &v);
+ if (r != FcResultMatch)
+ return r;
+ if (v.type != FcTypeMatrix)
+ return FcResultTypeMismatch;
+ *m = (FcMatrix *) v.u.m;
+ return FcResultMatch;
+}
+
+
+FcResult
+FcPatternGetBool(const FcPattern *p, const char *object, int id, FcBool *b)
+{
+ FcValue v;
+ FcResult r;
+
+ r = FcPatternGet (p, object, id, &v);
+ if (r != FcResultMatch)
+ return r;
+ if (v.type != FcTypeBool)
+ return FcResultTypeMismatch;
+ *b = v.u.b;
+ return FcResultMatch;
+}
+
+FcResult
+FcPatternGetCharSet(const FcPattern *p, const char *object, int id, FcCharSet **c)
+{
+ FcValue v;
+ FcResult r;
+
+ r = FcPatternGet (p, object, id, &v);
+ if (r != FcResultMatch)
+ return r;
+ if (v.type != FcTypeCharSet)
+ return FcResultTypeMismatch;
+ *c = (FcCharSet *) v.u.c;
+ return FcResultMatch;
+}
+
+FcResult
+FcPatternGetFTFace(const FcPattern *p, const char *object, int id, FT_Face *f)
+{
+ FcValue v;
+ FcResult r;
+
+ r = FcPatternGet (p, object, id, &v);
+ if (r != FcResultMatch)
+ return r;
+ if (v.type != FcTypeFTFace)
+ return FcResultTypeMismatch;
+ *f = (FT_Face) v.u.f;
+ return FcResultMatch;
+}
+
+FcResult
+FcPatternGetLangSet(const FcPattern *p, const char *object, int id, FcLangSet **ls)
+{
+ FcValue v;
+ FcResult r;
+
+ r = FcPatternGet (p, object, id, &v);
+ if (r != FcResultMatch)
+ return r;
+ if (v.type != FcTypeLangSet)
+ return FcResultTypeMismatch;
+ *ls = (FcLangSet *) v.u.l;
+ return FcResultMatch;
+}
+
+FcPattern *
+FcPatternDuplicate (const FcPattern *orig)
+{
+ FcPattern *new;
+ int i;
+ FcValueList *l;
+
+ new = FcPatternCreate ();
+ if (!new)
+ goto bail0;
+
+ for (i = 0; i < orig->num; i++)
+ {
+ for (l = orig->elts[i].values; l; l = l->next)
+ if (!FcPatternAdd (new, orig->elts[i].object, l->value, FcTrue))
+ goto bail1;
+ }
+
+ return new;
+
+bail1:
+ FcPatternDestroy (new);
+bail0:
+ return 0;
+}
+
+void
+FcPatternReference (FcPattern *p)
+{
+ if (p->ref != FC_REF_CONSTANT)
+ p->ref++;
+}
+
+FcPattern *
+FcPatternVaBuild (FcPattern *orig, va_list va)
+{
+ FcPattern *ret;
+
+ FcPatternVapBuild (ret, orig, va);
+ return ret;
+}
+
+FcPattern *
+FcPatternBuild (FcPattern *orig, ...)
+{
+ va_list va;
+
+ va_start (va, orig);
+ FcPatternVapBuild (orig, orig, va);
+ va_end (va);
+ return orig;
+}
+
+/*
+ * Add all of the elements in 's' to 'p'
+ */
+FcBool
+FcPatternAppend (FcPattern *p, FcPattern *s)
+{
+ int i;
+ FcPatternElt *e;
+ FcValueList *v;
+
+ for (i = 0; i < s->num; i++)
+ {
+ e = &s->elts[i];
+ for (v = e->values; v; v = v->next)
+ {
+ if (!FcPatternAddWithBinding (p, e->object,
+ v->value, v->binding, FcTrue))
+ return FcFalse;
+ }
+ }
+ return FcTrue;
+}
+
+const char *
+FcObjectStaticName (const char *name)
+{
+#define OBJECT_HASH_SIZE 31
+ static struct objectBucket {
+ struct objectBucket *next;
+ FcChar32 hash;
+ } *buckets[OBJECT_HASH_SIZE];
+ FcChar32 hash = FcStringHash ((const FcChar8 *) name);
+ struct objectBucket **p;
+ struct objectBucket *b;
+ int size;
+
+ for (p = &buckets[hash % OBJECT_HASH_SIZE]; (b = *p); p = &(b->next))
+ if (b->hash == hash && !strcmp (name, (char *) (b + 1)))
+ return (char *) (b + 1);
+ size = sizeof (struct objectBucket) + strlen (name) + 1;
+ b = malloc (size);
+ FcMemAlloc (FC_MEM_STATICSTR, size);
+ if (!b)
+ return NULL;
+ b->next = 0;
+ b->hash = hash;
+ strcpy ((char *) (b + 1), name);
+ *p = b;
+ return (char *) (b + 1);
+}
diff --git a/nx-X11/extras/fontconfig/src/fcstr.c b/nx-X11/extras/fontconfig/src/fcstr.c
new file mode 100644
index 000000000..730e44061
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcstr.c
@@ -0,0 +1,1000 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fcstr.c,v 1.10 2002/08/31 22:17:32 keithp Exp $
+ *
+ * Copyright © 2000 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include "fcint.h"
+
+FcChar8 *
+FcStrCopy (const FcChar8 *s)
+{
+ FcChar8 *r;
+
+ if (!s)
+ return 0;
+ r = (FcChar8 *) malloc (strlen ((char *) s) + 1);
+ if (!r)
+ return 0;
+ FcMemAlloc (FC_MEM_STRING, strlen ((char *) s) + 1);
+ strcpy ((char *) r, (char *) s);
+ return r;
+}
+
+FcChar8 *
+FcStrPlus (const FcChar8 *s1, const FcChar8 *s2)
+{
+ int l = strlen ((char *)s1) + strlen ((char *) s2) + 1;
+ FcChar8 *s = malloc (l);
+
+ if (!s)
+ return 0;
+ FcMemAlloc (FC_MEM_STRING, l);
+ strcpy ((char *) s, (char *) s1);
+ strcat ((char *) s, (char *) s2);
+ return s;
+}
+
+void
+FcStrFree (FcChar8 *s)
+{
+ FcMemFree (FC_MEM_STRING, strlen ((char *) s) + 1);
+ free (s);
+}
+
+
+#include "../fc-case/fccase.h"
+
+#define FcCaseFoldUpperCount(cf) \
+ ((cf)->method == FC_CASE_FOLD_FULL ? 1 : (cf)->count)
+
+#define FC_STR_CANON_BUF_LEN 1024
+
+typedef struct _FcCaseWalker {
+ const FcChar8 *read;
+ const FcChar8 *src;
+ int len;
+ FcChar8 utf8[FC_MAX_CASE_FOLD_CHARS + 1];
+} FcCaseWalker;
+
+static void
+FcStrCaseWalkerInit (const FcChar8 *src, FcCaseWalker *w)
+{
+ w->src = src;
+ w->read = 0;
+ w->len = strlen (src);
+}
+
+static FcChar8
+FcStrCaseWalkerLong (FcCaseWalker *w, FcChar8 r)
+{
+ FcChar32 ucs4;
+ int slen;
+
+ slen = FcUtf8ToUcs4 (w->src - 1, &ucs4, w->len + 1);
+ if (slen <= 0)
+ return r;
+ if (FC_MIN_FOLD_CHAR <= ucs4 && ucs4 <= FC_MAX_FOLD_CHAR)
+ {
+ int min = 0;
+ int max = FC_NUM_CASE_FOLD;
+
+ while (min <= max)
+ {
+ int mid = (min + max) >> 1;
+ FcChar32 low = fcCaseFold[mid].upper;
+ FcChar32 high = low + FcCaseFoldUpperCount (&fcCaseFold[mid]);
+
+ if (high <= ucs4)
+ min = mid + 1;
+ else if (ucs4 < low)
+ max = mid - 1;
+ else
+ {
+ const FcCaseFold *fold = &fcCaseFold[mid];
+ int dlen;
+
+ switch (fold->method) {
+ case FC_CASE_FOLD_EVEN_ODD:
+ if ((ucs4 & 1) != (fold->upper & 1))
+ return r;
+ /* fall through ... */
+ default:
+ dlen = FcUcs4ToUtf8 (ucs4 + fold->offset, w->utf8);
+ break;
+ case FC_CASE_FOLD_FULL:
+ dlen = fold->count;
+ memcpy (w->utf8, fcCaseFoldChars + fold->offset, dlen);
+ break;
+ }
+
+ /* consume rest of src utf-8 bytes */
+ w->src += slen - 1;
+ w->len -= slen - 1;
+
+ /* read from temp buffer */
+ w->utf8[dlen] = '\0';
+ w->read = w->utf8;
+ return *w->read++;
+ }
+ }
+ }
+ return r;
+}
+
+static FcChar8
+FcStrCaseWalkerNext (FcCaseWalker *w)
+{
+ FcChar8 r;
+
+ if (w->read)
+ {
+ if ((r = *w->read++))
+ return r;
+ w->read = 0;
+ }
+ r = *w->src++;
+ --w->len;
+
+ if ((r & 0xc0) == 0xc0)
+ return FcStrCaseWalkerLong (w, r);
+ if ('A' <= r && r <= 'Z')
+ r = r - 'A' + 'a';
+ return r;
+}
+
+static FcChar8
+FcStrCaseWalkerNextIgnoreBlanks (FcCaseWalker *w)
+{
+ FcChar8 r;
+
+ if (w->read)
+ {
+ if ((r = *w->read++))
+ return r;
+ w->read = 0;
+ }
+ do
+ {
+ r = *w->src++;
+ --w->len;
+ } while (r == ' ');
+
+ if ((r & 0xc0) == 0xc0)
+ return FcStrCaseWalkerLong (w, r);
+ if ('A' <= r && r <= 'Z')
+ r = r - 'A' + 'a';
+ return r;
+}
+
+FcChar8 *
+FcStrDowncase (const FcChar8 *s)
+{
+ FcCaseWalker w;
+ int len = 0;
+ FcChar8 *dst, *d;
+
+ FcStrCaseWalkerInit (s, &w);
+ while (FcStrCaseWalkerNext (&w))
+ len++;
+ d = dst = malloc (len + 1);
+ if (!d)
+ return 0;
+ FcMemAlloc (FC_MEM_STRING, len + 1);
+ FcStrCaseWalkerInit (s, &w);
+ while ((*d++ = FcStrCaseWalkerNext (&w)));
+ return dst;
+}
+
+int
+FcStrCmpIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
+{
+ FcCaseWalker w1, w2;
+ FcChar8 c1, c2;
+
+ if (s1 == s2) return 0;
+
+ FcStrCaseWalkerInit (s1, &w1);
+ FcStrCaseWalkerInit (s2, &w2);
+
+ for (;;)
+ {
+ c1 = FcStrCaseWalkerNext (&w1);
+ c2 = FcStrCaseWalkerNext (&w2);
+ if (!c1 || (c1 != c2))
+ break;
+ }
+ return (int) c1 - (int) c2;
+}
+
+int
+FcStrCmpIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
+{
+ FcCaseWalker w1, w2;
+ FcChar8 c1, c2;
+
+ if (s1 == s2) return 0;
+
+ FcStrCaseWalkerInit (s1, &w1);
+ FcStrCaseWalkerInit (s2, &w2);
+
+ for (;;)
+ {
+ c1 = FcStrCaseWalkerNextIgnoreBlanks (&w1);
+ c2 = FcStrCaseWalkerNextIgnoreBlanks (&w2);
+ if (!c1 || (c1 != c2))
+ break;
+ }
+ return (int) c1 - (int) c2;
+}
+
+int
+FcStrCmp (const FcChar8 *s1, const FcChar8 *s2)
+{
+ FcChar8 c1, c2;
+
+ if (s1 == s2)
+ return 0;
+ for (;;)
+ {
+ c1 = *s1++;
+ c2 = *s2++;
+ if (!c1 || c1 != c2)
+ break;
+ }
+ return (int) c1 - (int) c2;
+}
+
+/*
+ * Return a hash value for a string
+ */
+
+FcChar32
+FcStrHashIgnoreCase (const FcChar8 *s)
+{
+ FcChar32 h = 0;
+ FcCaseWalker w;
+ FcChar8 c;
+
+ FcStrCaseWalkerInit (s, &w);
+ while ((c = FcStrCaseWalkerNext (&w)))
+ h = ((h << 3) ^ (h >> 3)) ^ c;
+ return h;
+}
+
+/*
+ * Is the head of s1 equal to s2?
+ */
+
+static FcBool
+FcStrIsAtIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
+{
+ FcCaseWalker w1, w2;
+ FcChar8 c1, c2;
+
+ FcStrCaseWalkerInit (s1, &w1);
+ FcStrCaseWalkerInit (s2, &w2);
+
+ for (;;)
+ {
+ c1 = FcStrCaseWalkerNextIgnoreBlanks (&w1);
+ c2 = FcStrCaseWalkerNextIgnoreBlanks (&w2);
+ if (!c1 || (c1 != c2))
+ break;
+ }
+ return c1 == c2 || !c2;
+}
+
+/*
+ * Does s1 contain an instance of s2 (ignoring blanks and case)?
+ */
+
+const FcChar8 *
+FcStrContainsIgnoreBlanksAndCase (const FcChar8 *s1, const FcChar8 *s2)
+{
+ while (*s1)
+ {
+ if (FcStrIsAtIgnoreBlanksAndCase (s1, s2))
+ return s1;
+ s1++;
+ }
+ return 0;
+}
+
+/*
+ * Is the head of s1 equal to s2?
+ */
+
+static FcBool
+FcStrIsAtIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
+{
+ FcCaseWalker w1, w2;
+ FcChar8 c1, c2;
+
+ FcStrCaseWalkerInit (s1, &w1);
+ FcStrCaseWalkerInit (s2, &w2);
+
+ for (;;)
+ {
+ c1 = FcStrCaseWalkerNext (&w1);
+ c2 = FcStrCaseWalkerNext (&w2);
+ if (!c1 || (c1 != c2))
+ break;
+ }
+ return c1 == c2 || !c2;
+}
+
+/*
+ * Does s1 contain an instance of s2 (ignoring blanks and case)?
+ */
+
+const FcChar8 *
+FcStrContainsIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
+{
+ while (*s1)
+ {
+ if (FcStrIsAtIgnoreCase (s1, s2))
+ return s1;
+ s1++;
+ }
+ return 0;
+}
+
+const FcChar8 *
+FcStrStrIgnoreCase (const FcChar8 *s1, const FcChar8 *s2)
+{
+ FcCaseWalker w1, w2;
+ FcChar8 c1, c2;
+ const FcChar8 *cur;
+
+ if (!s1 || !s2)
+ return 0;
+
+ if (s1 == s2)
+ return s1;
+
+ FcStrCaseWalkerInit (s1, &w1);
+ FcStrCaseWalkerInit (s2, &w2);
+
+ c2 = FcStrCaseWalkerNext (&w2);
+
+ for (;;)
+ {
+ cur = w1.src;
+ c1 = FcStrCaseWalkerNext (&w1);
+ if (!c1)
+ break;
+ if (c1 == c2)
+ {
+ FcCaseWalker w1t = w1;
+ FcCaseWalker w2t = w2;
+ FcChar8 c1t, c2t;
+
+ for (;;)
+ {
+ c1t = FcStrCaseWalkerNext (&w1t);
+ c2t = FcStrCaseWalkerNext (&w2t);
+
+ if (!c2t)
+ return cur;
+ if (c2t != c1t)
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+const FcChar8 *
+FcStrStr (const FcChar8 *s1, const FcChar8 *s2)
+{
+ FcChar8 c1, c2;
+ const FcChar8 * p = s1;
+ const FcChar8 * b = s2;
+
+ if (!s1 || !s2)
+ return 0;
+
+ if (s1 == s2)
+ return s1;
+
+again:
+ c2 = *s2++;
+
+ if (!c2)
+ return 0;
+
+ for (;;)
+ {
+ p = s1;
+ c1 = *s1++;
+ if (!c1 || c1 == c2)
+ break;
+ }
+
+ if (c1 != c2)
+ return 0;
+
+ for (;;)
+ {
+ c1 = *s1;
+ c2 = *s2;
+ if (c1 && c2 && c1 != c2)
+ {
+ s1 = p + 1;
+ s2 = b;
+ goto again;
+ }
+ if (!c2)
+ return p;
+ if (!c1)
+ return 0;
+ ++ s1;
+ ++ s2;
+ }
+
+ return 0;
+}
+
+int
+FcUtf8ToUcs4 (const FcChar8 *src_orig,
+ FcChar32 *dst,
+ int len)
+{
+ const FcChar8 *src = src_orig;
+ FcChar8 s;
+ int extra;
+ FcChar32 result;
+
+ if (len == 0)
+ return 0;
+
+ s = *src++;
+ len--;
+
+ if (!(s & 0x80))
+ {
+ result = s;
+ extra = 0;
+ }
+ else if (!(s & 0x40))
+ {
+ return -1;
+ }
+ else if (!(s & 0x20))
+ {
+ result = s & 0x1f;
+ extra = 1;
+ }
+ else if (!(s & 0x10))
+ {
+ result = s & 0xf;
+ extra = 2;
+ }
+ else if (!(s & 0x08))
+ {
+ result = s & 0x07;
+ extra = 3;
+ }
+ else if (!(s & 0x04))
+ {
+ result = s & 0x03;
+ extra = 4;
+ }
+ else if ( ! (s & 0x02))
+ {
+ result = s & 0x01;
+ extra = 5;
+ }
+ else
+ {
+ return -1;
+ }
+ if (extra > len)
+ return -1;
+
+ while (extra--)
+ {
+ result <<= 6;
+ s = *src++;
+
+ if ((s & 0xc0) != 0x80)
+ return -1;
+
+ result |= s & 0x3f;
+ }
+ *dst = result;
+ return src - src_orig;
+}
+
+FcBool
+FcUtf8Len (const FcChar8 *string,
+ int len,
+ int *nchar,
+ int *wchar)
+{
+ int n;
+ int clen;
+ FcChar32 c;
+ FcChar32 max;
+
+ n = 0;
+ max = 0;
+ while (len)
+ {
+ clen = FcUtf8ToUcs4 (string, &c, len);
+ if (clen <= 0) /* malformed UTF8 string */
+ return FcFalse;
+ if (c > max)
+ max = c;
+ string += clen;
+ len -= clen;
+ n++;
+ }
+ *nchar = n;
+ if (max >= 0x10000)
+ *wchar = 4;
+ else if (max > 0x100)
+ *wchar = 2;
+ else
+ *wchar = 1;
+ return FcTrue;
+}
+
+int
+FcUcs4ToUtf8 (FcChar32 ucs4,
+ FcChar8 dest[FC_UTF8_MAX_LEN])
+{
+ int bits;
+ FcChar8 *d = dest;
+
+ if (ucs4 < 0x80) { *d++= ucs4; bits= -6; }
+ else if (ucs4 < 0x800) { *d++= ((ucs4 >> 6) & 0x1F) | 0xC0; bits= 0; }
+ else if (ucs4 < 0x10000) { *d++= ((ucs4 >> 12) & 0x0F) | 0xE0; bits= 6; }
+ else if (ucs4 < 0x200000) { *d++= ((ucs4 >> 18) & 0x07) | 0xF0; bits= 12; }
+ else if (ucs4 < 0x4000000) { *d++= ((ucs4 >> 24) & 0x03) | 0xF8; bits= 18; }
+ else if (ucs4 < 0x80000000) { *d++= ((ucs4 >> 30) & 0x01) | 0xFC; bits= 24; }
+ else return 0;
+
+ for ( ; bits >= 0; bits-= 6) {
+ *d++= ((ucs4 >> bits) & 0x3F) | 0x80;
+ }
+ return d - dest;
+}
+
+#define GetUtf16(src,endian) \
+ ((FcChar16) ((src)[endian == FcEndianBig ? 0 : 1] << 8) | \
+ (FcChar16) ((src)[endian == FcEndianBig ? 1 : 0]))
+
+int
+FcUtf16ToUcs4 (const FcChar8 *src_orig,
+ FcEndian endian,
+ FcChar32 *dst,
+ int len) /* in bytes */
+{
+ const FcChar8 *src = src_orig;
+ FcChar16 a, b;
+ FcChar32 result;
+
+ if (len < 2)
+ return 0;
+
+ a = GetUtf16 (src, endian); src += 2; len -= 2;
+
+ /*
+ * Check for surrogate
+ */
+ if ((a & 0xfc00) == 0xd800)
+ {
+ if (len < 2)
+ return 0;
+ b = GetUtf16 (src, endian); src += 2; len -= 2;
+ /*
+ * Check for invalid surrogate sequence
+ */
+ if ((b & 0xfc00) != 0xdc00)
+ return 0;
+ result = ((((FcChar32) a & 0x3ff) << 10) |
+ ((FcChar32) b & 0x3ff)) + 0x10000;
+ }
+ else
+ result = a;
+ *dst = result;
+ return src - src_orig;
+}
+
+FcBool
+FcUtf16Len (const FcChar8 *string,
+ FcEndian endian,
+ int len, /* in bytes */
+ int *nchar,
+ int *wchar)
+{
+ int n;
+ int clen;
+ FcChar32 c;
+ FcChar32 max;
+
+ n = 0;
+ max = 0;
+ while (len)
+ {
+ clen = FcUtf16ToUcs4 (string, endian, &c, len);
+ if (clen <= 0) /* malformed UTF8 string */
+ return FcFalse;
+ if (c > max)
+ max = c;
+ string += clen;
+ len -= clen;
+ n++;
+ }
+ *nchar = n;
+ if (max >= 0x10000)
+ *wchar = 4;
+ else if (max > 0x100)
+ *wchar = 2;
+ else
+ *wchar = 1;
+ return FcTrue;
+}
+
+void
+FcStrBufInit (FcStrBuf *buf, FcChar8 *init, int size)
+{
+ buf->buf = init;
+ buf->allocated = FcFalse;
+ buf->failed = FcFalse;
+ buf->len = 0;
+ buf->size = size;
+}
+
+void
+FcStrBufDestroy (FcStrBuf *buf)
+{
+ if (buf->allocated)
+ {
+ FcMemFree (FC_MEM_STRBUF, buf->size);
+ free (buf->buf);
+ FcStrBufInit (buf, 0, 0);
+ }
+}
+
+FcChar8 *
+FcStrBufDone (FcStrBuf *buf)
+{
+ FcChar8 *ret;
+
+ ret = malloc (buf->len + 1);
+ if (ret)
+ {
+ FcMemAlloc (FC_MEM_STRING, buf->len + 1);
+ memcpy (ret, buf->buf, buf->len);
+ ret[buf->len] = '\0';
+ }
+ FcStrBufDestroy (buf);
+ return ret;
+}
+
+FcBool
+FcStrBufChar (FcStrBuf *buf, FcChar8 c)
+{
+ if (buf->len == buf->size)
+ {
+ FcChar8 *new;
+ int size;
+
+ if (buf->allocated)
+ {
+ size = buf->size * 2;
+ new = realloc (buf->buf, size);
+ }
+ else
+ {
+ size = buf->size + 1024;
+ new = malloc (size);
+ if (new)
+ {
+ buf->allocated = FcTrue;
+ memcpy (new, buf->buf, buf->len);
+ }
+ }
+ if (!new)
+ {
+ buf->failed = FcTrue;
+ return FcFalse;
+ }
+ if (buf->size)
+ FcMemFree (FC_MEM_STRBUF, buf->size);
+ FcMemAlloc (FC_MEM_STRBUF, size);
+ buf->size = size;
+ buf->buf = new;
+ }
+ buf->buf[buf->len++] = c;
+ return FcTrue;
+}
+
+FcBool
+FcStrBufString (FcStrBuf *buf, const FcChar8 *s)
+{
+ FcChar8 c;
+ while ((c = *s++))
+ if (!FcStrBufChar (buf, c))
+ return FcFalse;
+ return FcTrue;
+}
+
+FcBool
+FcStrBufData (FcStrBuf *buf, const FcChar8 *s, int len)
+{
+ while (len-- > 0)
+ if (!FcStrBufChar (buf, *s++))
+ return FcFalse;
+ return FcTrue;
+}
+
+FcBool
+FcStrUsesHome (const FcChar8 *s)
+{
+ return *s == '~';
+}
+
+FcChar8 *
+FcStrCopyFilename (const FcChar8 *s)
+{
+ FcChar8 *new;
+
+ if (*s == '~')
+ {
+ FcChar8 *home = FcConfigHome ();
+ int size;
+ if (!home)
+ return 0;
+ size = strlen ((char *) home) + strlen ((char *) s);
+ new = (FcChar8 *) malloc (size);
+ if (!new)
+ return 0;
+ FcMemAlloc (FC_MEM_STRING, size);
+ strcpy ((char *) new, (char *) home);
+ strcat ((char *) new, (char *) s + 1);
+ }
+ else
+ {
+ int size = strlen ((char *) s) + 1;
+ new = (FcChar8 *) malloc (size);
+ if (!new)
+ return 0;
+ FcMemAlloc (FC_MEM_STRING, size);
+ strcpy ((char *) new, (const char *) s);
+ }
+ return new;
+}
+
+FcChar8 *
+FcStrLastSlash (const FcChar8 *path)
+{
+ FcChar8 *slash;
+
+ slash = (FcChar8 *) strrchr ((const char *) path, '/');
+#ifdef _WIN32
+ {
+ FcChar8 *backslash;
+
+ backslash = (FcChar8 *) strrchr ((const char *) path, '\\');
+ if (!slash || (backslash && backslash > slash))
+ slash = backslash;
+ }
+#endif
+
+ return slash;
+}
+
+FcChar8 *
+FcStrDirname (const FcChar8 *file)
+{
+ FcChar8 *slash;
+ FcChar8 *dir;
+
+ slash = FcStrLastSlash (file);
+ if (!slash)
+ return FcStrCopy ((FcChar8 *) ".");
+ dir = malloc ((slash - file) + 1);
+ if (!dir)
+ return 0;
+ FcMemAlloc (FC_MEM_STRING, (slash - file) + 1);
+ strncpy ((char *) dir, (const char *) file, slash - file);
+ dir[slash - file] = '\0';
+ return dir;
+}
+
+FcChar8 *
+FcStrBasename (const FcChar8 *file)
+{
+ FcChar8 *slash;
+
+ slash = FcStrLastSlash (file);
+ if (!slash)
+ return FcStrCopy (file);
+ return FcStrCopy (slash + 1);
+}
+
+FcStrSet *
+FcStrSetCreate (void)
+{
+ FcStrSet *set = malloc (sizeof (FcStrSet));
+ if (!set)
+ return 0;
+ FcMemAlloc (FC_MEM_STRSET, sizeof (FcStrSet));
+ set->ref = 1;
+ set->num = 0;
+ set->size = 0;
+ set->strs = 0;
+ return set;
+}
+
+static FcBool
+_FcStrSetAppend (FcStrSet *set, FcChar8 *s)
+{
+ if (FcStrSetMember (set, s))
+ {
+ FcStrFree (s);
+ return FcTrue;
+ }
+ if (set->num == set->size)
+ {
+ FcChar8 **strs = malloc ((set->size + 2) * sizeof (FcChar8 *));
+
+ if (!strs)
+ return FcFalse;
+ FcMemAlloc (FC_MEM_STRSET, (set->size + 2) * sizeof (FcChar8 *));
+ set->size = set->size + 1;
+ if (set->num)
+ memcpy (strs, set->strs, set->num * sizeof (FcChar8 *));
+ if (set->strs)
+ free (set->strs);
+ set->strs = strs;
+ }
+ set->strs[set->num++] = s;
+ set->strs[set->num] = 0;
+ return FcTrue;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+FcBool
+FcStrSetAddFilename (FcStrSet *set, const FcChar8 *s)
+{
+ FcChar8 *new = FcStrCopyFilename (s);
+ if (!new)
+ return FcFalse;
+ if (!_FcStrSetAppend (set, new))
+ {
+ FcStrFree (new);
+ return FcFalse;
+ }
+ return FcTrue;
+}
+
+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;
+}
+
+void
+FcStrSetDestroy (FcStrSet *set)
+{
+ if (--set->ref == 0)
+ {
+ int i;
+
+ for (i = 0; i < set->num; i++)
+ FcStrFree (set->strs[i]);
+ FcMemFree (FC_MEM_STRSET, (set->size) * sizeof (FcChar8 *));
+ if (set->strs)
+ free (set->strs);
+ FcMemFree (FC_MEM_STRSET, sizeof (FcStrSet));
+ free (set);
+ }
+}
+
+FcStrList *
+FcStrListCreate (FcStrSet *set)
+{
+ FcStrList *list;
+
+ list = malloc (sizeof (FcStrList));
+ if (!list)
+ return 0;
+ FcMemAlloc (FC_MEM_STRLIST, sizeof (FcStrList));
+ list->set = set;
+ set->ref++;
+ list->n = 0;
+ return list;
+}
+
+FcChar8 *
+FcStrListNext (FcStrList *list)
+{
+ if (list->n >= list->set->num)
+ return 0;
+ return list->set->strs[list->n++];
+}
+
+void
+FcStrListDone (FcStrList *list)
+{
+ FcStrSetDestroy (list->set);
+ FcMemFree (FC_MEM_STRLIST, sizeof (FcStrList));
+ free (list);
+}
diff --git a/nx-X11/extras/fontconfig/src/fcxml.c b/nx-X11/extras/fontconfig/src/fcxml.c
new file mode 100644
index 000000000..539e57faf
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fcxml.c
@@ -0,0 +1,2388 @@
+/*
+ * $RCSId: xc/lib/fontconfig/src/fcxml.c,v 1.21 2002/08/22 18:53:22 keithp Exp $
+ *
+ * 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 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.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 <stdarg.h>
+#include "fcint.h"
+#include <dirent.h>
+
+#ifndef HAVE_XMLPARSE_H
+#define HAVE_XMLPARSE_H 0
+#endif
+
+#if HAVE_XMLPARSE_H
+#include <xmlparse.h>
+#else
+#include <expat.h>
+#endif
+
+#ifdef _WIN32
+#define STRICT
+#include <windows.h>
+#undef STRICT
+#endif
+
+
+void
+FcTestDestroy (FcTest *test)
+{
+ if (test->next)
+ FcTestDestroy (test->next);
+ FcExprDestroy (test->expr);
+ FcStrFree ((FcChar8 *) test->field);
+ FcMemFree (FC_MEM_TEST, sizeof (FcTest));
+ free (test);
+}
+
+FcExpr *
+FcExprCreateInteger (int i)
+{
+ FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+ if (e)
+ {
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
+ e->op = FcOpInteger;
+ e->u.ival = i;
+ }
+ return e;
+}
+
+FcExpr *
+FcExprCreateDouble (double d)
+{
+ FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+ if (e)
+ {
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
+ e->op = FcOpDouble;
+ e->u.dval = d;
+ }
+ return e;
+}
+
+FcExpr *
+FcExprCreateString (const FcChar8 *s)
+{
+ FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+ if (e)
+ {
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
+ e->op = FcOpString;
+ e->u.sval = FcStrCopy (s);
+ }
+ return e;
+}
+
+FcExpr *
+FcExprCreateMatrix (const FcMatrix *m)
+{
+ FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+ if (e)
+ {
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
+ e->op = FcOpMatrix;
+ e->u.mval = FcMatrixCopy (m);
+ }
+ return e;
+}
+
+FcExpr *
+FcExprCreateBool (FcBool b)
+{
+ FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+ if (e)
+ {
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
+ e->op = FcOpBool;
+ e->u.bval = b;
+ }
+ return e;
+}
+
+FcExpr *
+FcExprCreateNil (void)
+{
+ FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+ if (e)
+ {
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
+ e->op = FcOpNil;
+ }
+ return e;
+}
+
+FcExpr *
+FcExprCreateField (const char *field)
+{
+ FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+ if (e)
+ {
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
+ e->op = FcOpField;
+ e->u.field = (char *) FcStrCopy ((FcChar8 *) field);
+ }
+ return e;
+}
+
+FcExpr *
+FcExprCreateConst (const FcChar8 *constant)
+{
+ FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+ if (e)
+ {
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
+ e->op = FcOpConst;
+ e->u.constant = FcStrCopy (constant);
+ }
+ return e;
+}
+
+FcExpr *
+FcExprCreateOp (FcExpr *left, FcOp op, FcExpr *right)
+{
+ FcExpr *e = (FcExpr *) malloc (sizeof (FcExpr));
+
+ if (e)
+ {
+ FcMemAlloc (FC_MEM_EXPR, sizeof (FcExpr));
+ e->op = op;
+ e->u.tree.left = left;
+ e->u.tree.right = right;
+ }
+ return e;
+}
+
+void
+FcExprDestroy (FcExpr *e)
+{
+ if (!e)
+ return;
+ switch (e->op) {
+ case FcOpInteger:
+ break;
+ case FcOpDouble:
+ break;
+ case FcOpString:
+ FcStrFree (e->u.sval);
+ break;
+ case FcOpMatrix:
+ FcMatrixFree (e->u.mval);
+ break;
+ case FcOpCharSet:
+ FcCharSetDestroy (e->u.cval);
+ break;
+ case FcOpBool:
+ break;
+ case FcOpField:
+ FcStrFree ((FcChar8 *) e->u.field);
+ break;
+ case FcOpConst:
+ FcStrFree (e->u.constant);
+ break;
+ case FcOpAssign:
+ case FcOpAssignReplace:
+ case FcOpPrepend:
+ case FcOpPrependFirst:
+ case FcOpAppend:
+ case FcOpAppendLast:
+ break;
+ case FcOpOr:
+ case FcOpAnd:
+ case FcOpEqual:
+ case FcOpNotEqual:
+ case FcOpLess:
+ case FcOpLessEqual:
+ case FcOpMore:
+ case FcOpMoreEqual:
+ case FcOpContains:
+ case FcOpListing:
+ case FcOpNotContains:
+ case FcOpPlus:
+ case FcOpMinus:
+ case FcOpTimes:
+ case FcOpDivide:
+ case FcOpQuest:
+ case FcOpComma:
+ FcExprDestroy (e->u.tree.right);
+ /* fall through */
+ case FcOpNot:
+ case FcOpFloor:
+ case FcOpCeil:
+ case FcOpRound:
+ case FcOpTrunc:
+ FcExprDestroy (e->u.tree.left);
+ break;
+ case FcOpNil:
+ case FcOpInvalid:
+ break;
+ }
+ FcMemFree (FC_MEM_EXPR, sizeof (FcExpr));
+ free (e);
+}
+
+void
+FcEditDestroy (FcEdit *e)
+{
+ if (e->next)
+ FcEditDestroy (e->next);
+ FcStrFree ((FcChar8 *) e->field);
+ if (e->expr)
+ FcExprDestroy (e->expr);
+ free (e);
+}
+
+char *
+FcConfigSaveField (const char *field)
+{
+ return (char *) FcStrCopy ((FcChar8 *) field);
+}
+
+typedef enum _FcElement {
+ FcElementNone,
+ FcElementFontconfig,
+ FcElementDir,
+ FcElementCache,
+ FcElementInclude,
+ FcElementConfig,
+ FcElementMatch,
+ FcElementAlias,
+
+ FcElementBlank,
+ FcElementRescan,
+
+ FcElementPrefer,
+ FcElementAccept,
+ FcElementDefault,
+ FcElementFamily,
+
+ FcElementSelectfont,
+ FcElementAcceptfont,
+ FcElementRejectfont,
+ FcElementGlob,
+ FcElementPattern,
+ FcElementPatelt,
+
+ FcElementTest,
+ FcElementEdit,
+ FcElementInt,
+ FcElementDouble,
+ FcElementString,
+ FcElementMatrix,
+ FcElementBool,
+ FcElementCharset,
+ FcElementName,
+ FcElementConst,
+ FcElementOr,
+ FcElementAnd,
+ FcElementEq,
+ FcElementNotEq,
+ FcElementLess,
+ FcElementLessEq,
+ FcElementMore,
+ FcElementMoreEq,
+ FcElementContains,
+ FcElementNotContains,
+ FcElementPlus,
+ FcElementMinus,
+ FcElementTimes,
+ FcElementDivide,
+ FcElementNot,
+ FcElementIf,
+ FcElementFloor,
+ FcElementCeil,
+ FcElementRound,
+ FcElementTrunc,
+ FcElementUnknown
+} FcElement;
+
+static FcElement
+FcElementMap (const XML_Char *name)
+{
+ static struct {
+ char *name;
+ FcElement element;
+ } fcElementMap[] = {
+ { "fontconfig", FcElementFontconfig },
+ { "dir", FcElementDir },
+ { "cache", FcElementCache },
+ { "include", FcElementInclude },
+ { "config", FcElementConfig },
+ { "match", FcElementMatch },
+ { "alias", FcElementAlias },
+
+ { "blank", FcElementBlank },
+ { "rescan", FcElementRescan },
+
+ { "prefer", FcElementPrefer },
+ { "accept", FcElementAccept },
+ { "default", FcElementDefault },
+ { "family", FcElementFamily },
+
+ { "selectfont", FcElementSelectfont },
+ { "acceptfont", FcElementAcceptfont },
+ { "rejectfont", FcElementRejectfont },
+ { "glob", FcElementGlob },
+ { "pattern", FcElementPattern },
+ { "patelt", FcElementPatelt },
+
+ { "test", FcElementTest },
+ { "edit", FcElementEdit },
+ { "int", FcElementInt },
+ { "double", FcElementDouble },
+ { "string", FcElementString },
+ { "matrix", FcElementMatrix },
+ { "bool", FcElementBool },
+ { "charset", FcElementCharset },
+ { "name", FcElementName },
+ { "const", FcElementConst },
+ { "or", FcElementOr },
+ { "and", FcElementAnd },
+ { "eq", FcElementEq },
+ { "not_eq", FcElementNotEq },
+ { "less", FcElementLess },
+ { "less_eq", FcElementLessEq },
+ { "more", FcElementMore },
+ { "more_eq", FcElementMoreEq },
+ { "contains", FcElementContains },
+ { "not_contains",FcElementNotContains },
+ { "plus", FcElementPlus },
+ { "minus", FcElementMinus },
+ { "times", FcElementTimes },
+ { "divide", FcElementDivide },
+ { "not", FcElementNot },
+ { "if", FcElementIf },
+ { "floor", FcElementFloor },
+ { "ceil", FcElementCeil },
+ { "round", FcElementRound },
+ { "trunc", FcElementTrunc },
+
+ { 0, 0 }
+ };
+
+ int i;
+ for (i = 0; fcElementMap[i].name; i++)
+ if (!strcmp ((char *) name, fcElementMap[i].name))
+ return fcElementMap[i].element;
+ return FcElementUnknown;
+}
+
+typedef struct _FcPStack {
+ struct _FcPStack *prev;
+ FcElement element;
+ FcChar8 **attr;
+ FcStrBuf str;
+} FcPStack;
+
+typedef enum _FcVStackTag {
+ FcVStackNone,
+
+ FcVStackString,
+ FcVStackFamily,
+ FcVStackField,
+ FcVStackConstant,
+ FcVStackGlob,
+ FcVStackPattern,
+
+ FcVStackPrefer,
+ FcVStackAccept,
+ FcVStackDefault,
+
+ FcVStackInteger,
+ FcVStackDouble,
+ FcVStackMatrix,
+ FcVStackBool,
+
+ FcVStackTest,
+ FcVStackExpr,
+ FcVStackEdit
+} FcVStackTag;
+
+typedef struct _FcVStack {
+ struct _FcVStack *prev;
+ FcPStack *pstack; /* related parse element */
+ FcVStackTag tag;
+ union {
+ FcChar8 *string;
+
+ int integer;
+ double _double;
+ FcMatrix *matrix;
+ FcBool bool;
+
+ FcTest *test;
+ FcQual qual;
+ FcOp op;
+ FcExpr *expr;
+ FcEdit *edit;
+
+ FcPattern *pattern;
+ } u;
+} FcVStack;
+
+typedef struct _FcConfigParse {
+ FcPStack *pstack;
+ FcVStack *vstack;
+ FcBool error;
+ const FcChar8 *name;
+ FcConfig *config;
+ XML_Parser parser;
+} FcConfigParse;
+
+typedef enum _FcConfigSeverity {
+ FcSevereInfo, FcSevereWarning, FcSevereError
+} FcConfigSeverity;
+
+static void
+FcConfigMessage (FcConfigParse *parse, FcConfigSeverity severe, char *fmt, ...)
+{
+ char *s = "unknown";
+ va_list args;
+
+ va_start (args, fmt);
+
+ switch (severe) {
+ case FcSevereInfo: s = "info"; break;
+ case FcSevereWarning: s = "warning"; break;
+ case FcSevereError: s = "error"; break;
+ }
+ if (parse)
+ {
+ if (parse->name)
+ fprintf (stderr, "Fontconfig %s: \"%s\", line %d: ", s,
+ parse->name, XML_GetCurrentLineNumber (parse->parser));
+ else
+ fprintf (stderr, "Fontconfig %s: line %d: ", s,
+ XML_GetCurrentLineNumber (parse->parser));
+ if (severe >= FcSevereError)
+ parse->error = FcTrue;
+ }
+ else
+ fprintf (stderr, "Fontconfig %s: ", s);
+ vfprintf (stderr, fmt, args);
+ fprintf (stderr, "\n");
+ va_end (args);
+}
+
+
+static char *
+FcTypeName (FcType type)
+{
+ switch (type) {
+ case FcTypeVoid:
+ return "void";
+ case FcTypeInteger:
+ case FcTypeDouble:
+ return "number";
+ case FcTypeString:
+ return "string";
+ case FcTypeBool:
+ return "bool";
+ case FcTypeMatrix:
+ return "matrix";
+ case FcTypeCharSet:
+ return "charset";
+ case FcTypeFTFace:
+ return "FT_Face";
+ case FcTypeLangSet:
+ return "langset";
+ default:
+ return "unknown";
+ }
+}
+
+static void
+FcTypecheckValue (FcConfigParse *parse, FcType value, FcType type)
+{
+ if (value == FcTypeInteger)
+ value = FcTypeDouble;
+ if (type == FcTypeInteger)
+ type = FcTypeDouble;
+ if (value != type)
+ {
+ if ((value == FcTypeLangSet && type == FcTypeString) ||
+ (value == FcTypeString && type == FcTypeLangSet))
+ return;
+ FcConfigMessage (parse, FcSevereWarning, "saw %s, expected %s",
+ FcTypeName (value), FcTypeName (type));
+ }
+}
+
+static void
+FcTypecheckExpr (FcConfigParse *parse, FcExpr *expr, FcType type)
+{
+ const FcObjectType *o;
+ const FcConstant *c;
+
+ switch (expr->op) {
+ case FcOpInteger:
+ case FcOpDouble:
+ FcTypecheckValue (parse, FcTypeDouble, type);
+ break;
+ case FcOpString:
+ FcTypecheckValue (parse, FcTypeString, type);
+ break;
+ case FcOpMatrix:
+ FcTypecheckValue (parse, FcTypeMatrix, type);
+ break;
+ case FcOpBool:
+ FcTypecheckValue (parse, FcTypeBool, type);
+ break;
+ case FcOpCharSet:
+ FcTypecheckValue (parse, FcTypeCharSet, type);
+ break;
+ case FcOpNil:
+ break;
+ case FcOpField:
+ o = FcNameGetObjectType (expr->u.field);
+ if (o)
+ FcTypecheckValue (parse, o->type, type);
+ break;
+ case FcOpConst:
+ c = FcNameGetConstant (expr->u.constant);
+ if (c)
+ {
+ o = FcNameGetObjectType (c->object);
+ if (o)
+ FcTypecheckValue (parse, o->type, type);
+ }
+ break;
+ case FcOpQuest:
+ FcTypecheckExpr (parse, expr->u.tree.left, FcTypeBool);
+ FcTypecheckExpr (parse, expr->u.tree.right->u.tree.left, type);
+ FcTypecheckExpr (parse, expr->u.tree.right->u.tree.right, type);
+ break;
+ case FcOpAssign:
+ case FcOpAssignReplace:
+ break;
+ case FcOpEqual:
+ case FcOpNotEqual:
+ case FcOpLess:
+ case FcOpLessEqual:
+ case FcOpMore:
+ case FcOpMoreEqual:
+ case FcOpContains:
+ case FcOpNotContains:
+ case FcOpListing:
+ FcTypecheckValue (parse, FcTypeBool, type);
+ break;
+ case FcOpComma:
+ case FcOpOr:
+ case FcOpAnd:
+ case FcOpPlus:
+ case FcOpMinus:
+ case FcOpTimes:
+ case FcOpDivide:
+ FcTypecheckExpr (parse, expr->u.tree.left, type);
+ FcTypecheckExpr (parse, expr->u.tree.right, type);
+ break;
+ case FcOpNot:
+ FcTypecheckValue (parse, FcTypeBool, type);
+ FcTypecheckExpr (parse, expr->u.tree.left, FcTypeBool);
+ break;
+ case FcOpFloor:
+ case FcOpCeil:
+ case FcOpRound:
+ case FcOpTrunc:
+ FcTypecheckValue (parse, FcTypeDouble, type);
+ FcTypecheckExpr (parse, expr->u.tree.left, FcTypeDouble);
+ break;
+ default:
+ break;
+ }
+}
+
+static FcTest *
+FcTestCreate (FcConfigParse *parse,
+ FcMatchKind kind,
+ FcQual qual,
+ const FcChar8 *field,
+ FcOp compare,
+ FcExpr *expr)
+{
+ FcTest *test = (FcTest *) malloc (sizeof (FcTest));
+
+ if (test)
+ {
+ const FcObjectType *o;
+
+ FcMemAlloc (FC_MEM_TEST, sizeof (FcTest));
+ test->next = 0;
+ test->kind = kind;
+ test->qual = qual;
+ test->field = (char *) FcStrCopy (field);
+ test->op = compare;
+ test->expr = expr;
+ o = FcNameGetObjectType (test->field);
+ if (o)
+ FcTypecheckExpr (parse, expr, o->type);
+ }
+ return test;
+}
+
+static FcEdit *
+FcEditCreate (FcConfigParse *parse,
+ const char *field,
+ FcOp op,
+ FcExpr *expr,
+ FcValueBinding binding)
+{
+ FcEdit *e = (FcEdit *) malloc (sizeof (FcEdit));
+
+ if (e)
+ {
+ const FcObjectType *o;
+
+ e->next = 0;
+ e->field = field; /* already saved in grammar */
+ e->op = op;
+ e->expr = expr;
+ e->binding = binding;
+ o = FcNameGetObjectType (e->field);
+ if (o)
+ FcTypecheckExpr (parse, expr, o->type);
+ }
+ return e;
+}
+
+static void
+FcVStackPush (FcConfigParse *parse, FcVStack *vstack)
+{
+ vstack->prev = parse->vstack;
+ vstack->pstack = parse->pstack ? parse->pstack->prev : 0;
+ parse->vstack = vstack;
+}
+
+static FcVStack *
+FcVStackCreate (void)
+{
+ FcVStack *new;
+
+ new = malloc (sizeof (FcVStack));
+ if (!new)
+ return 0;
+ FcMemAlloc (FC_MEM_VSTACK, sizeof (FcVStack));
+ new->tag = FcVStackNone;
+ new->prev = 0;
+ return new;
+}
+
+static void
+FcVStackDestroy (FcVStack *vstack)
+{
+ FcVStack *prev;
+
+ for (; vstack; vstack = prev)
+ {
+ prev = vstack->prev;
+ switch (vstack->tag) {
+ case FcVStackNone:
+ break;
+ case FcVStackString:
+ case FcVStackFamily:
+ case FcVStackField:
+ case FcVStackConstant:
+ case FcVStackGlob:
+ FcStrFree (vstack->u.string);
+ break;
+ case FcVStackPattern:
+ FcPatternDestroy (vstack->u.pattern);
+ break;
+ case FcVStackInteger:
+ case FcVStackDouble:
+ break;
+ case FcVStackMatrix:
+ FcMatrixFree (vstack->u.matrix);
+ break;
+ case FcVStackBool:
+ break;
+ case FcVStackTest:
+ FcTestDestroy (vstack->u.test);
+ break;
+ case FcVStackExpr:
+ case FcVStackPrefer:
+ case FcVStackAccept:
+ case FcVStackDefault:
+ FcExprDestroy (vstack->u.expr);
+ break;
+ case FcVStackEdit:
+ FcEditDestroy (vstack->u.edit);
+ break;
+ }
+ FcMemFree (FC_MEM_VSTACK, sizeof (FcVStack));
+ free (vstack);
+ }
+}
+
+static FcBool
+FcVStackPushString (FcConfigParse *parse, FcVStackTag tag, FcChar8 *string)
+{
+ FcVStack *vstack = FcVStackCreate ();
+ if (!vstack)
+ return FcFalse;
+ vstack->u.string = string;
+ vstack->tag = tag;
+ FcVStackPush (parse, vstack);
+ return FcTrue;
+}
+
+static FcBool
+FcVStackPushInteger (FcConfigParse *parse, int integer)
+{
+ FcVStack *vstack = FcVStackCreate ();
+ if (!vstack)
+ return FcFalse;
+ vstack->u.integer = integer;
+ vstack->tag = FcVStackInteger;
+ FcVStackPush (parse, vstack);
+ return FcTrue;
+}
+
+static FcBool
+FcVStackPushDouble (FcConfigParse *parse, double _double)
+{
+ FcVStack *vstack = FcVStackCreate ();
+ if (!vstack)
+ return FcFalse;
+ vstack->u._double = _double;
+ vstack->tag = FcVStackDouble;
+ FcVStackPush (parse, vstack);
+ return FcTrue;
+}
+
+static FcBool
+FcVStackPushMatrix (FcConfigParse *parse, FcMatrix *matrix)
+{
+ FcVStack *vstack = FcVStackCreate ();
+ if (!vstack)
+ return FcFalse;
+ matrix = FcMatrixCopy (matrix);
+ if (!matrix)
+ {
+ FcVStackDestroy (vstack);
+ return FcFalse;
+ }
+ vstack->u.matrix = matrix;
+ vstack->tag = FcVStackMatrix;
+ FcVStackPush (parse, vstack);
+ return FcTrue;
+}
+
+static FcBool
+FcVStackPushBool (FcConfigParse *parse, FcBool bool)
+{
+ FcVStack *vstack = FcVStackCreate ();
+ if (!vstack)
+ return FcFalse;
+ vstack->u.bool = bool;
+ vstack->tag = FcVStackBool;
+ FcVStackPush (parse, vstack);
+ return FcTrue;
+}
+
+static FcBool
+FcVStackPushTest (FcConfigParse *parse, FcTest *test)
+{
+ FcVStack *vstack = FcVStackCreate ();
+ if (!vstack)
+ return FcFalse;
+ vstack->u.test = test;
+ vstack->tag = FcVStackTest;
+ FcVStackPush (parse, vstack);
+ return FcTrue;
+}
+
+static FcBool
+FcVStackPushExpr (FcConfigParse *parse, FcVStackTag tag, FcExpr *expr)
+{
+ FcVStack *vstack = FcVStackCreate ();
+ if (!vstack)
+ return FcFalse;
+ vstack->u.expr = expr;
+ vstack->tag = tag;
+ FcVStackPush (parse, vstack);
+ return FcTrue;
+}
+
+static FcBool
+FcVStackPushEdit (FcConfigParse *parse, FcEdit *edit)
+{
+ FcVStack *vstack = FcVStackCreate ();
+ if (!vstack)
+ return FcFalse;
+ vstack->u.edit = edit;
+ vstack->tag = FcVStackEdit;
+ FcVStackPush (parse, vstack);
+ return FcTrue;
+}
+
+static FcBool
+FcVStackPushPattern (FcConfigParse *parse, FcPattern *pattern)
+{
+ FcVStack *vstack = FcVStackCreate ();
+ if (!vstack)
+ return FcFalse;
+ vstack->u.pattern = pattern;
+ vstack->tag = FcVStackPattern;
+ FcVStackPush (parse, vstack);
+ return FcTrue;
+}
+
+static FcVStack *
+FcVStackFetch (FcConfigParse *parse, int off)
+{
+ FcVStack *vstack;
+
+ for (vstack = parse->vstack; vstack && off-- > 0; vstack = vstack->prev);
+ return vstack;
+}
+
+static void
+FcVStackClear (FcConfigParse *parse)
+{
+ while (parse->vstack && parse->vstack->pstack == parse->pstack)
+ {
+ FcVStack *vstack = parse->vstack;
+ parse->vstack = vstack->prev;
+ vstack->prev = 0;
+ FcVStackDestroy (vstack);
+ }
+}
+
+static FcVStack *
+FcVStackPop (FcConfigParse *parse)
+{
+ FcVStack *vstack = parse->vstack;
+
+ if (!vstack || vstack->pstack != parse->pstack)
+ return 0;
+ parse->vstack = vstack->prev;
+ vstack->prev = 0;
+ return vstack;
+}
+
+static int
+FcVStackElements (FcConfigParse *parse)
+{
+ int h = 0;
+ FcVStack *vstack = parse->vstack;
+ while (vstack && vstack->pstack == parse->pstack)
+ {
+ h++;
+ vstack = vstack->prev;
+ }
+ return h;
+}
+
+static FcChar8 **
+FcConfigSaveAttr (const XML_Char **attr)
+{
+ int n;
+ int slen;
+ int i;
+ FcChar8 **new;
+ FcChar8 *s;
+
+ if (!attr)
+ return 0;
+ slen = 0;
+ for (i = 0; attr[i]; i++)
+ slen += strlen (attr[i]) + 1;
+ n = i;
+ new = malloc ((i + 1) * sizeof (FcChar8 *) + slen);
+ if (!new)
+ return 0;
+ FcMemAlloc (FC_MEM_ATTR, 1); /* size is too expensive */
+ s = (FcChar8 *) (new + (i + 1));
+ for (i = 0; attr[i]; i++)
+ {
+ new[i] = s;
+ strcpy ((char *) s, (char *) attr[i]);
+ s += strlen ((char *) s) + 1;
+ }
+ new[i] = 0;
+ return new;
+}
+
+static FcBool
+FcPStackPush (FcConfigParse *parse, FcElement element, const XML_Char **attr)
+{
+ FcPStack *new = malloc (sizeof (FcPStack));
+
+ if (!new)
+ return FcFalse;
+ FcMemAlloc (FC_MEM_PSTACK, sizeof (FcPStack));
+ new->prev = parse->pstack;
+ new->element = element;
+ if (attr)
+ {
+ new->attr = FcConfigSaveAttr (attr);
+ if (!new->attr)
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ }
+ else
+ new->attr = 0;
+ FcStrBufInit (&new->str, 0, 0);
+ parse->pstack = new;
+ return FcTrue;
+}
+
+static FcBool
+FcPStackPop (FcConfigParse *parse)
+{
+ FcPStack *old;
+
+ if (!parse->pstack)
+ {
+ FcConfigMessage (parse, FcSevereError, "mismatching element");
+ return FcFalse;
+ }
+ FcVStackClear (parse);
+ old = parse->pstack;
+ parse->pstack = old->prev;
+ FcStrBufDestroy (&old->str);
+ if (old->attr)
+ {
+ FcMemFree (FC_MEM_ATTR, 1); /* size is to expensive */
+ free (old->attr);
+ }
+ FcMemFree (FC_MEM_PSTACK, sizeof (FcPStack));
+ free (old);
+ return FcTrue;
+}
+
+static FcBool
+FcConfigInit (FcConfigParse *parse, const FcChar8 *name, FcConfig *config, XML_Parser parser)
+{
+ parse->pstack = 0;
+ parse->vstack = 0;
+ parse->error = FcFalse;
+ parse->name = name;
+ parse->config = config;
+ parse->parser = parser;
+ return FcTrue;
+}
+
+static void
+FcConfigCleanup (FcConfigParse *parse)
+{
+ while (parse->pstack)
+ FcPStackPop (parse);
+}
+
+static const FcChar8 *
+FcConfigGetAttribute (FcConfigParse *parse, char *attr)
+{
+ FcChar8 **attrs;
+ if (!parse->pstack)
+ return 0;
+
+ attrs = parse->pstack->attr;
+ while (*attrs)
+ {
+ if (!strcmp ((char *) *attrs, attr))
+ return attrs[1];
+ attrs += 2;
+ }
+ return 0;
+}
+
+static void
+FcStartElement(void *userData, const XML_Char *name, const XML_Char **attr)
+{
+ FcConfigParse *parse = userData;
+ FcElement element;
+
+ element = FcElementMap (name);
+ if (element == FcElementUnknown)
+ FcConfigMessage (parse, FcSevereWarning, "unknown element \"%s\"", name);
+
+ if (!FcPStackPush (parse, element, attr))
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ return;
+ }
+ return;
+}
+
+static void
+FcParseBlank (FcConfigParse *parse)
+{
+ int n = FcVStackElements (parse);
+ while (n-- > 0)
+ {
+ FcVStack *v = FcVStackFetch (parse, n);
+ if (v->tag != FcVStackInteger)
+ FcConfigMessage (parse, FcSevereError, "non-integer blank");
+ else
+ {
+ if (!parse->config->blanks)
+ {
+ parse->config->blanks = FcBlanksCreate ();
+ if (!parse->config->blanks)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ break;
+ }
+ }
+ if (!FcBlanksAdd (parse->config->blanks, v->u.integer))
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ break;
+ }
+ }
+ }
+}
+
+static void
+FcParseRescan (FcConfigParse *parse)
+{
+ int n = FcVStackElements (parse);
+ while (n-- > 0)
+ {
+ FcVStack *v = FcVStackFetch (parse, n);
+ if (v->tag != FcVStackInteger)
+ FcConfigMessage (parse, FcSevereWarning, "non-integer rescan");
+ else
+ parse->config->rescanInterval = v->u.integer;
+ }
+}
+
+static void
+FcParseInt (FcConfigParse *parse)
+{
+ FcChar8 *s, *end;
+ int l;
+
+ if (!parse->pstack)
+ return;
+ s = FcStrBufDone (&parse->pstack->str);
+ if (!s)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ return;
+ }
+ end = 0;
+ l = (int) strtol ((char *) s, (char **)&end, 0);
+ if (end != s + strlen ((char *) s))
+ FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid integer", s);
+ else
+ FcVStackPushInteger (parse, l);
+ FcStrFree (s);
+}
+
+/*
+ * idea copied from glib g_ascii_strtod with
+ * permission of the author (Alexander Larsson)
+ */
+
+#include <locale.h>
+
+static double
+FcStrtod (char *s, char **end)
+{
+ struct lconv *locale_data;
+ char *dot;
+ double v;
+
+ /*
+ * Have to swap the decimal point to match the current locale
+ * if that locale doesn't use 0x2e
+ */
+ if ((dot = strchr (s, 0x2e)) &&
+ (locale_data = localeconv ()) &&
+ (locale_data->decimal_point[0] != 0x2e ||
+ locale_data->decimal_point[1] != 0))
+ {
+ char buf[128];
+ int slen = strlen (s);
+ int dlen = strlen (locale_data->decimal_point);
+
+ if (slen + dlen > sizeof (buf))
+ {
+ if (end)
+ *end = s;
+ v = 0;
+ }
+ else
+ {
+ char *buf_end;
+ /* mantissa */
+ strncpy (buf, s, dot - s);
+ /* decimal point */
+ strcpy (buf + (dot - s), locale_data->decimal_point);
+ /* rest of number */
+ strcpy (buf + (dot - s) + dlen, dot + 1);
+ buf_end = 0;
+ v = strtod (buf, &buf_end);
+ if (buf_end) {
+ buf_end = s + (buf_end - buf);
+ if (buf_end > dot)
+ buf_end -= dlen - 1;
+ }
+ if (end)
+ *end = buf_end;
+ }
+ }
+ else
+ v = strtod (s, end);
+ return v;
+}
+
+static void
+FcParseDouble (FcConfigParse *parse)
+{
+ FcChar8 *s, *end;
+ double d;
+
+ if (!parse->pstack)
+ return;
+ s = FcStrBufDone (&parse->pstack->str);
+ if (!s)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ return;
+ }
+ end = 0;
+ d = FcStrtod ((char *) s, (char **)&end);
+ if (end != s + strlen ((char *) s))
+ FcConfigMessage (parse, FcSevereError, "\"%s\": not a valid double", s);
+ else
+ FcVStackPushDouble (parse, d);
+ FcStrFree (s);
+}
+
+static void
+FcParseString (FcConfigParse *parse, FcVStackTag tag)
+{
+ FcChar8 *s;
+
+ if (!parse->pstack)
+ return;
+ s = FcStrBufDone (&parse->pstack->str);
+ if (!s)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ return;
+ }
+ if (!FcVStackPushString (parse, tag, s))
+ FcStrFree (s);
+}
+
+static void
+FcParseMatrix (FcConfigParse *parse)
+{
+ FcVStack *vstack;
+ enum { m_done, m_xx, m_xy, m_yx, m_yy } matrix_state = m_yy;
+ FcMatrix m;
+
+ while ((vstack = FcVStackPop (parse)))
+ {
+ double v;
+ switch (vstack->tag) {
+ case FcVStackInteger:
+ v = vstack->u.integer;
+ break;
+ case FcVStackDouble:
+ v = vstack->u._double;
+ break;
+ default:
+ FcConfigMessage (parse, FcSevereError, "non-double matrix element");
+ v = 1.0;
+ break;
+ }
+ switch (matrix_state) {
+ case m_xx: m.xx = v; break;
+ case m_xy: m.xy = v; break;
+ case m_yx: m.yx = v; break;
+ case m_yy: m.yy = v; break;
+ default: break;
+ }
+ FcVStackDestroy (vstack);
+ matrix_state--;
+ }
+ if (matrix_state != m_done)
+ FcConfigMessage (parse, FcSevereError, "wrong number of matrix elements");
+ else
+ FcVStackPushMatrix (parse, &m);
+}
+
+static FcBool
+FcConfigLexBool (FcConfigParse *parse, const FcChar8 *bool)
+{
+ FcBool result = FcFalse;
+
+ if (!FcNameBool (bool, &result))
+ FcConfigMessage (parse, FcSevereWarning, "\"%s\" is not known boolean",
+ bool);
+ return result;
+}
+
+static void
+FcParseBool (FcConfigParse *parse)
+{
+ FcChar8 *s;
+
+ if (!parse->pstack)
+ return;
+ s = FcStrBufDone (&parse->pstack->str);
+ if (!s)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ return;
+ }
+ FcVStackPushBool (parse, FcConfigLexBool (parse, s));
+ FcStrFree (s);
+}
+
+static void
+FcParseFamilies (FcConfigParse *parse, FcVStackTag tag)
+{
+ FcVStack *vstack;
+ FcExpr *left, *expr = 0, *new;
+
+ while ((vstack = FcVStackPop (parse)))
+ {
+ if (vstack->tag != FcVStackFamily)
+ {
+ FcConfigMessage (parse, FcSevereWarning, "non-family");
+ FcVStackDestroy (vstack);
+ continue;
+ }
+ left = vstack->u.expr;
+ vstack->tag = FcVStackNone;
+ FcVStackDestroy (vstack);
+ if (expr)
+ {
+ new = FcExprCreateOp (left, FcOpComma, expr);
+ if (!new)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ FcExprDestroy (left);
+ FcExprDestroy (expr);
+ break;
+ }
+ expr = new;
+ }
+ else
+ expr = left;
+ }
+ if (expr)
+ {
+ if (!FcVStackPushExpr (parse, tag, expr))
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ if (expr)
+ FcExprDestroy (expr);
+ }
+ }
+}
+
+static void
+FcParseFamily (FcConfigParse *parse)
+{
+ FcChar8 *s;
+ FcExpr *expr;
+
+ if (!parse->pstack)
+ return;
+ s = FcStrBufDone (&parse->pstack->str);
+ if (!s)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ return;
+ }
+ expr = FcExprCreateString (s);
+ FcStrFree (s);
+ if (expr)
+ FcVStackPushExpr (parse, FcVStackFamily, expr);
+}
+
+static void
+FcParseAlias (FcConfigParse *parse)
+{
+ FcExpr *family = 0, *accept = 0, *prefer = 0, *def = 0, *new = 0;
+ FcEdit *edit = 0, *next;
+ FcVStack *vstack;
+ FcTest *test;
+
+ while ((vstack = FcVStackPop (parse)))
+ {
+ switch (vstack->tag) {
+ case FcVStackFamily:
+ if (family)
+ {
+ new = FcExprCreateOp (vstack->u.expr, FcOpComma, family);
+ if (!new)
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ else
+ family = new;
+ }
+ else
+ new = vstack->u.expr;
+ if (new)
+ {
+ family = new;
+ vstack->tag = FcVStackNone;
+ }
+ break;
+ case FcVStackPrefer:
+ if (prefer)
+ FcExprDestroy (prefer);
+ prefer = vstack->u.expr;
+ vstack->tag = FcVStackNone;
+ break;
+ case FcVStackAccept:
+ if (accept)
+ FcExprDestroy (accept);
+ accept = vstack->u.expr;
+ vstack->tag = FcVStackNone;
+ break;
+ case FcVStackDefault:
+ if (def)
+ FcExprDestroy (def);
+ def = vstack->u.expr;
+ vstack->tag = FcVStackNone;
+ break;
+ default:
+ FcConfigMessage (parse, FcSevereWarning, "bad alias");
+ break;
+ }
+ FcVStackDestroy (vstack);
+ }
+ if (!family)
+ {
+ FcConfigMessage (parse, FcSevereError, "missing family in alias");
+ if (prefer)
+ FcExprDestroy (prefer);
+ if (accept)
+ FcExprDestroy (accept);
+ if (def)
+ FcExprDestroy (def);
+ return;
+ }
+ if (prefer)
+ {
+ edit = FcEditCreate (parse,
+ FcConfigSaveField ("family"),
+ FcOpPrepend,
+ prefer,
+ FcValueBindingWeak);
+ if (edit)
+ edit->next = 0;
+ else
+ FcExprDestroy (prefer);
+ }
+ if (accept)
+ {
+ next = edit;
+ edit = FcEditCreate (parse,
+ FcConfigSaveField ("family"),
+ FcOpAppend,
+ accept,
+ FcValueBindingWeak);
+ if (edit)
+ edit->next = next;
+ else
+ FcExprDestroy (accept);
+ }
+ if (def)
+ {
+ next = edit;
+ edit = FcEditCreate (parse,
+ FcConfigSaveField ("family"),
+ FcOpAppendLast,
+ def,
+ FcValueBindingWeak);
+ if (edit)
+ edit->next = next;
+ else
+ FcExprDestroy (def);
+ }
+ if (edit)
+ {
+ test = FcTestCreate (parse, FcMatchPattern,
+ FcQualAny,
+ (FcChar8 *) FC_FAMILY,
+ FcOpEqual,
+ family);
+ if (test)
+ if (!FcConfigAddEdit (parse->config, test, edit, FcMatchPattern))
+ FcTestDestroy (test);
+ }
+ else
+ FcExprDestroy (family);
+}
+
+static FcExpr *
+FcPopExpr (FcConfigParse *parse)
+{
+ FcVStack *vstack = FcVStackPop (parse);
+ FcExpr *expr = 0;
+ if (!vstack)
+ return 0;
+ switch (vstack->tag) {
+ case FcVStackNone:
+ break;
+ case FcVStackString:
+ case FcVStackFamily:
+ expr = FcExprCreateString (vstack->u.string);
+ break;
+ case FcVStackField:
+ expr = FcExprCreateField ((char *) vstack->u.string);
+ break;
+ case FcVStackConstant:
+ expr = FcExprCreateConst (vstack->u.string);
+ break;
+ case FcVStackGlob:
+ /* XXX: What's the correct action here? (CDW) */
+ break;
+ case FcVStackPrefer:
+ case FcVStackAccept:
+ case FcVStackDefault:
+ expr = vstack->u.expr;
+ vstack->tag = FcVStackNone;
+ break;
+ case FcVStackInteger:
+ expr = FcExprCreateInteger (vstack->u.integer);
+ break;
+ case FcVStackDouble:
+ expr = FcExprCreateDouble (vstack->u._double);
+ break;
+ case FcVStackMatrix:
+ expr = FcExprCreateMatrix (vstack->u.matrix);
+ break;
+ case FcVStackBool:
+ expr = FcExprCreateBool (vstack->u.bool);
+ break;
+ case FcVStackTest:
+ break;
+ case FcVStackExpr:
+ expr = vstack->u.expr;
+ vstack->tag = FcVStackNone;
+ break;
+ case FcVStackEdit:
+ break;
+ default:
+ break;
+ }
+ FcVStackDestroy (vstack);
+ return expr;
+}
+
+/*
+ * This builds a tree of binary operations. Note
+ * that every operator is defined so that if only
+ * a single operand is contained, the value of the
+ * whole expression is the value of the operand.
+ *
+ * This code reduces in that case to returning that
+ * operand.
+ */
+static FcExpr *
+FcPopBinary (FcConfigParse *parse, FcOp op)
+{
+ FcExpr *left, *expr = 0, *new;
+
+ while ((left = FcPopExpr (parse)))
+ {
+ if (expr)
+ {
+ new = FcExprCreateOp (left, op, expr);
+ if (!new)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ FcExprDestroy (left);
+ FcExprDestroy (expr);
+ break;
+ }
+ expr = new;
+ }
+ else
+ expr = left;
+ }
+ return expr;
+}
+
+static void
+FcParseBinary (FcConfigParse *parse, FcOp op)
+{
+ FcExpr *expr = FcPopBinary (parse, op);
+ if (expr)
+ FcVStackPushExpr (parse, FcVStackExpr, expr);
+}
+
+/*
+ * This builds a a unary operator, it consumes only
+ * a single operand
+ */
+
+static FcExpr *
+FcPopUnary (FcConfigParse *parse, FcOp op)
+{
+ FcExpr *operand, *new = 0;
+
+ if ((operand = FcPopExpr (parse)))
+ {
+ new = FcExprCreateOp (operand, op, 0);
+ if (!new)
+ {
+ FcExprDestroy (operand);
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ }
+ }
+ return new;
+}
+
+static void
+FcParseUnary (FcConfigParse *parse, FcOp op)
+{
+ FcExpr *expr = FcPopUnary (parse, op);
+ if (expr)
+ FcVStackPushExpr (parse, FcVStackExpr, expr);
+}
+
+static void
+FcParseInclude (FcConfigParse *parse)
+{
+ FcChar8 *s;
+ const FcChar8 *i;
+ FcBool ignore_missing = FcFalse;
+
+ s = FcStrBufDone (&parse->pstack->str);
+ if (!s)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ return;
+ }
+ i = FcConfigGetAttribute (parse, "ignore_missing");
+ if (i && FcConfigLexBool (parse, (FcChar8 *) i) == FcTrue)
+ ignore_missing = FcTrue;
+ if (!FcConfigParseAndLoad (parse->config, s, !ignore_missing))
+ parse->error = FcTrue;
+ FcStrFree (s);
+}
+
+typedef struct _FcOpMap {
+ char *name;
+ FcOp op;
+} FcOpMap;
+
+static FcOp
+FcConfigLexOp (const FcChar8 *op, const FcOpMap *map, int nmap)
+{
+ int i;
+
+ for (i = 0; i < nmap; i++)
+ if (!strcmp ((char *) op, map[i].name))
+ return map[i].op;
+ return FcOpInvalid;
+}
+
+static const FcOpMap fcCompareOps[] = {
+ { "eq", FcOpEqual },
+ { "not_eq", FcOpNotEqual },
+ { "less", FcOpLess },
+ { "less_eq", FcOpLessEqual },
+ { "more", FcOpMore },
+ { "more_eq", FcOpMoreEqual },
+ { "contains", FcOpContains },
+ { "not_contains", FcOpNotContains }
+};
+
+#define NUM_COMPARE_OPS (sizeof fcCompareOps / sizeof fcCompareOps[0])
+
+static FcOp
+FcConfigLexCompare (const FcChar8 *compare)
+{
+ return FcConfigLexOp (compare, fcCompareOps, NUM_COMPARE_OPS);
+}
+
+
+static void
+FcParseTest (FcConfigParse *parse)
+{
+ const FcChar8 *kind_string;
+ FcMatchKind kind;
+ const FcChar8 *qual_string;
+ FcQual qual;
+ const FcChar8 *name;
+ const FcChar8 *compare_string;
+ FcOp compare;
+ FcExpr *expr;
+ FcTest *test;
+
+ kind_string = FcConfigGetAttribute (parse, "target");
+ if (!kind_string)
+ kind = FcMatchDefault;
+ else
+ {
+ if (!strcmp ((char *) kind_string, "pattern"))
+ kind = FcMatchPattern;
+ else if (!strcmp ((char *) kind_string, "font"))
+ kind = FcMatchFont;
+ else if (!strcmp ((char *) kind_string, "default"))
+ kind = FcMatchDefault;
+ else
+ {
+ FcConfigMessage (parse, FcSevereWarning, "invalid test target \"%s\"", kind_string);
+ return;
+ }
+ }
+ qual_string = FcConfigGetAttribute (parse, "qual");
+ if (!qual_string)
+ qual = FcQualAny;
+ else
+ {
+ if (!strcmp ((char *) qual_string, "any"))
+ qual = FcQualAny;
+ else if (!strcmp ((char *) qual_string, "all"))
+ qual = FcQualAll;
+ else if (!strcmp ((char *) qual_string, "first"))
+ qual = FcQualFirst;
+ else if (!strcmp ((char *) qual_string, "not_first"))
+ qual = FcQualNotFirst;
+ else
+ {
+ FcConfigMessage (parse, FcSevereWarning, "invalid test qual \"%s\"", qual_string);
+ return;
+ }
+ }
+ name = FcConfigGetAttribute (parse, "name");
+ if (!name)
+ {
+ FcConfigMessage (parse, FcSevereWarning, "missing test name");
+ return;
+ }
+ compare_string = FcConfigGetAttribute (parse, "compare");
+ if (!compare_string)
+ compare = FcOpEqual;
+ else
+ {
+ compare = FcConfigLexCompare (compare_string);
+ if (compare == FcOpInvalid)
+ {
+ FcConfigMessage (parse, FcSevereWarning, "invalid test compare \"%s\"", compare_string);
+ return;
+ }
+ }
+ expr = FcPopBinary (parse, FcOpComma);
+ if (!expr)
+ {
+ FcConfigMessage (parse, FcSevereWarning, "missing test expression");
+ return;
+ }
+ test = FcTestCreate (parse, kind, qual, name, compare, expr);
+ if (!test)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ return;
+ }
+ FcVStackPushTest (parse, test);
+}
+
+static const FcOpMap fcModeOps[] = {
+ { "assign", FcOpAssign },
+ { "assign_replace", FcOpAssignReplace },
+ { "prepend", FcOpPrepend },
+ { "prepend_first", FcOpPrependFirst },
+ { "append", FcOpAppend },
+ { "append_last", FcOpAppendLast },
+};
+
+#define NUM_MODE_OPS (sizeof fcModeOps / sizeof fcModeOps[0])
+
+static FcOp
+FcConfigLexMode (const FcChar8 *mode)
+{
+ return FcConfigLexOp (mode, fcModeOps, NUM_MODE_OPS);
+}
+
+static void
+FcParseEdit (FcConfigParse *parse)
+{
+ const FcChar8 *name;
+ const FcChar8 *mode_string;
+ const FcChar8 *binding_string;
+ FcOp mode;
+ FcValueBinding binding;
+ FcExpr *expr;
+ FcEdit *edit;
+
+ name = FcConfigGetAttribute (parse, "name");
+ if (!name)
+ {
+ FcConfigMessage (parse, FcSevereWarning, "missing edit name");
+ return;
+ }
+ mode_string = FcConfigGetAttribute (parse, "mode");
+ if (!mode_string)
+ mode = FcOpAssign;
+ else
+ {
+ mode = FcConfigLexMode (mode_string);
+ if (mode == FcOpInvalid)
+ {
+ FcConfigMessage (parse, FcSevereWarning, "invalid edit mode \"%s\"", mode_string);
+ return;
+ }
+ }
+ binding_string = FcConfigGetAttribute (parse, "binding");
+ if (!binding_string)
+ binding = FcValueBindingWeak;
+ else
+ {
+ if (!strcmp ((char *) binding_string, "weak"))
+ binding = FcValueBindingWeak;
+ else if (!strcmp ((char *) binding_string, "strong"))
+ binding = FcValueBindingStrong;
+ else if (!strcmp ((char *) binding_string, "same"))
+ binding = FcValueBindingSame;
+ else
+ {
+ FcConfigMessage (parse, FcSevereWarning, "invalid edit binding \"%s\"", binding_string);
+ return;
+ }
+ }
+ expr = FcPopBinary (parse, FcOpComma);
+ edit = FcEditCreate (parse, (char *) FcStrCopy (name), mode, expr, binding);
+ if (!edit)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ FcExprDestroy (expr);
+ return;
+ }
+ if (!FcVStackPushEdit (parse, edit))
+ FcEditDestroy (edit);
+}
+
+static void
+FcParseMatch (FcConfigParse *parse)
+{
+ const FcChar8 *kind_name;
+ FcMatchKind kind;
+ FcTest *test = 0;
+ FcEdit *edit = 0;
+ FcVStack *vstack;
+
+ kind_name = FcConfigGetAttribute (parse, "target");
+ if (!kind_name)
+ kind = FcMatchPattern;
+ else
+ {
+ if (!strcmp ((char *) kind_name, "pattern"))
+ kind = FcMatchPattern;
+ else if (!strcmp ((char *) kind_name, "font"))
+ kind = FcMatchFont;
+ else
+ {
+ FcConfigMessage (parse, FcSevereWarning, "invalid match target \"%s\"", kind_name);
+ return;
+ }
+ }
+ while ((vstack = FcVStackPop (parse)))
+ {
+ switch (vstack->tag) {
+ case FcVStackTest:
+ vstack->u.test->next = test;
+ test = vstack->u.test;
+ vstack->tag = FcVStackNone;
+ break;
+ case FcVStackEdit:
+ vstack->u.edit->next = edit;
+ edit = vstack->u.edit;
+ vstack->tag = FcVStackNone;
+ break;
+ default:
+ FcConfigMessage (parse, FcSevereWarning, "invalid match element");
+ break;
+ }
+ FcVStackDestroy (vstack);
+ }
+ if (!FcConfigAddEdit (parse->config, test, edit, kind))
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+}
+
+static void
+FcParseAcceptRejectFont (FcConfigParse *parse, FcElement element)
+{
+ FcVStack *vstack;
+
+ while ((vstack = FcVStackPop (parse)))
+ {
+ switch (vstack->tag) {
+ case FcVStackGlob:
+ if (!FcConfigGlobAdd (parse->config,
+ vstack->u.string,
+ element == FcElementAcceptfont))
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ }
+ break;
+ case FcVStackPattern:
+ if (!FcConfigPatternsAdd (parse->config,
+ vstack->u.pattern,
+ element == FcElementAcceptfont))
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ }
+ else
+ vstack->tag = FcVStackNone;
+ break;
+ default:
+ FcConfigMessage (parse, FcSevereWarning, "bad font selector");
+ break;
+ }
+ FcVStackDestroy (vstack);
+ }
+}
+
+
+static FcValue
+FcPopValue (FcConfigParse *parse)
+{
+ FcVStack *vstack = FcVStackPop (parse);
+ FcValue value;
+
+ value.type = FcTypeVoid;
+
+ if (!vstack)
+ return value;
+
+ switch (vstack->tag) {
+ case FcVStackString:
+ value.u.s = FcStrCopy (vstack->u.string);
+ if (value.u.s)
+ value.type = FcTypeString;
+ break;
+ case FcVStackConstant:
+ if (FcNameConstant (vstack->u.string, &value.u.i))
+ value.type = FcTypeInteger;
+ break;
+ case FcVStackInteger:
+ value.u.i = vstack->u.integer;
+ value.type = FcTypeInteger;
+ break;
+ case FcVStackDouble:
+ value.u.d = vstack->u._double;
+ value.type = FcTypeInteger;
+ break;
+ case FcVStackMatrix:
+ value.u.m = FcMatrixCopy (vstack->u.matrix);
+ if (value.u.m)
+ value.type = FcTypeMatrix;
+ break;
+ case FcVStackBool:
+ value.u.b = vstack->u.bool;
+ value.type = FcTypeBool;
+ break;
+ default:
+ FcConfigMessage (parse, FcSevereWarning, "unknown pattern element %d",
+ vstack->tag);
+ break;
+ }
+ FcVStackDestroy (vstack);
+
+ return value;
+}
+
+static void
+FcParsePatelt (FcConfigParse *parse)
+{
+ FcValue value;
+ FcPattern *pattern = FcPatternCreate ();
+ const char *name;
+
+ if (!pattern)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ return;
+ }
+
+ name = FcConfigGetAttribute (parse, "name");
+ if (!name)
+ {
+ FcConfigMessage (parse, FcSevereWarning, "missing pattern element name");
+ return;
+ }
+
+ for (;;)
+ {
+ value = FcPopValue (parse);
+ if (value.type == FcTypeVoid)
+ break;
+ if (!FcPatternAdd (pattern, name, value, FcTrue))
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ break;
+ }
+ }
+
+ FcVStackPushPattern (parse, pattern);
+}
+
+static void
+FcParsePattern (FcConfigParse *parse)
+{
+ FcVStack *vstack;
+ FcPattern *pattern = FcPatternCreate ();
+
+ if (!pattern)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ return;
+ }
+
+ while ((vstack = FcVStackPop (parse)))
+ {
+ switch (vstack->tag) {
+ case FcVStackPattern:
+ if (!FcPatternAppend (pattern, vstack->u.pattern))
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ return;
+ }
+ break;
+ default:
+ FcConfigMessage (parse, FcSevereWarning, "unknown pattern element");
+ break;
+ }
+ FcVStackDestroy (vstack);
+ }
+
+ FcVStackPushPattern (parse, pattern);
+}
+
+static void
+FcEndElement(void *userData, const XML_Char *name)
+{
+ FcConfigParse *parse = userData;
+ FcChar8 *data;
+
+ if (!parse->pstack)
+ return;
+ switch (parse->pstack->element) {
+ case FcElementNone:
+ break;
+ case FcElementFontconfig:
+ break;
+ case FcElementDir:
+ data = FcStrBufDone (&parse->pstack->str);
+ if (!data)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ break;
+ }
+#ifdef _WIN32
+ if (strcmp (data, "WINDOWSFONTDIR") == 0)
+ {
+ int rc;
+ FcStrFree (data);
+ data = malloc (1000);
+ if (!data)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ break;
+ }
+ FcMemAlloc (FC_MEM_STRING, 1000);
+ rc = GetWindowsDirectory (data, 800);
+ if (rc == 0 || rc > 800)
+ {
+ FcConfigMessage (parse, FcSevereError, "GetWindowsDirectory failed");
+ FcStrFree (data);
+ break;
+ }
+ if (data [strlen (data) - 1] != '\\')
+ strcat (data, "\\");
+ strcat (data, "fonts");
+ }
+#endif
+ if (!FcStrUsesHome (data) || FcConfigHome ())
+ {
+ if (!FcConfigAddDir (parse->config, data))
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ }
+ FcStrFree (data);
+ break;
+ case FcElementCache:
+ data = FcStrBufDone (&parse->pstack->str);
+ if (!data)
+ {
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ break;
+ }
+ if (!FcStrUsesHome (data) || FcConfigHome ())
+ {
+ if (!FcConfigSetCache (parse->config, data))
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+ }
+ FcStrFree (data);
+ break;
+ case FcElementInclude:
+ FcParseInclude (parse);
+ break;
+ case FcElementConfig:
+ break;
+ case FcElementMatch:
+ FcParseMatch (parse);
+ break;
+ case FcElementAlias:
+ FcParseAlias (parse);
+ break;
+
+ case FcElementBlank:
+ FcParseBlank (parse);
+ break;
+ case FcElementRescan:
+ FcParseRescan (parse);
+ break;
+
+ case FcElementPrefer:
+ FcParseFamilies (parse, FcVStackPrefer);
+ break;
+ case FcElementAccept:
+ FcParseFamilies (parse, FcVStackAccept);
+ break;
+ case FcElementDefault:
+ FcParseFamilies (parse, FcVStackDefault);
+ break;
+ case FcElementFamily:
+ FcParseFamily (parse);
+ break;
+
+ case FcElementTest:
+ FcParseTest (parse);
+ break;
+ case FcElementEdit:
+ FcParseEdit (parse);
+ break;
+
+ case FcElementInt:
+ FcParseInt (parse);
+ break;
+ case FcElementDouble:
+ FcParseDouble (parse);
+ break;
+ case FcElementString:
+ FcParseString (parse, FcVStackString);
+ break;
+ case FcElementMatrix:
+ FcParseMatrix (parse);
+ break;
+ case FcElementBool:
+ FcParseBool (parse);
+ break;
+ case FcElementCharset:
+/* FcParseCharset (parse); */
+ break;
+ case FcElementSelectfont:
+ break;
+ case FcElementAcceptfont:
+ case FcElementRejectfont:
+ FcParseAcceptRejectFont (parse, parse->pstack->element);
+ break;
+ case FcElementGlob:
+ FcParseString (parse, FcVStackGlob);
+ break;
+ case FcElementPattern:
+ FcParsePattern (parse);
+ break;
+ case FcElementPatelt:
+ FcParsePatelt (parse);
+ break;
+ case FcElementName:
+ FcParseString (parse, FcVStackField);
+ break;
+ case FcElementConst:
+ FcParseString (parse, FcVStackConstant);
+ break;
+ case FcElementOr:
+ FcParseBinary (parse, FcOpOr);
+ break;
+ case FcElementAnd:
+ FcParseBinary (parse, FcOpAnd);
+ break;
+ case FcElementEq:
+ FcParseBinary (parse, FcOpEqual);
+ break;
+ case FcElementNotEq:
+ FcParseBinary (parse, FcOpNotEqual);
+ break;
+ case FcElementLess:
+ FcParseBinary (parse, FcOpLess);
+ break;
+ case FcElementLessEq:
+ FcParseBinary (parse, FcOpLessEqual);
+ break;
+ case FcElementMore:
+ FcParseBinary (parse, FcOpMore);
+ break;
+ case FcElementMoreEq:
+ FcParseBinary (parse, FcOpMoreEqual);
+ break;
+ case FcElementContains:
+ FcParseBinary (parse, FcOpContains);
+ break;
+ case FcElementNotContains:
+ FcParseBinary (parse, FcOpNotContains);
+ break;
+ case FcElementPlus:
+ FcParseBinary (parse, FcOpPlus);
+ break;
+ case FcElementMinus:
+ FcParseBinary (parse, FcOpMinus);
+ break;
+ case FcElementTimes:
+ FcParseBinary (parse, FcOpTimes);
+ break;
+ case FcElementDivide:
+ FcParseBinary (parse, FcOpDivide);
+ break;
+ case FcElementNot:
+ FcParseUnary (parse, FcOpNot);
+ break;
+ case FcElementIf:
+ FcParseBinary (parse, FcOpQuest);
+ break;
+ case FcElementFloor:
+ FcParseUnary (parse, FcOpFloor);
+ break;
+ case FcElementCeil:
+ FcParseUnary (parse, FcOpCeil);
+ break;
+ case FcElementRound:
+ FcParseUnary (parse, FcOpRound);
+ break;
+ case FcElementTrunc:
+ FcParseUnary (parse, FcOpTrunc);
+ break;
+ case FcElementUnknown:
+ break;
+ }
+ (void) FcPStackPop (parse);
+}
+
+static void
+FcCharacterData (void *userData, const XML_Char *s, int len)
+{
+ FcConfigParse *parse = userData;
+
+ if (!parse->pstack)
+ return;
+ if (!FcStrBufData (&parse->pstack->str, (FcChar8 *) s, len))
+ FcConfigMessage (parse, FcSevereError, "out of memory");
+}
+
+static void
+FcStartDoctypeDecl (void *userData,
+ const XML_Char *doctypeName,
+ const XML_Char *sysid,
+ const XML_Char *pubid,
+ int has_internal_subset)
+{
+ FcConfigParse *parse = userData;
+
+ if (strcmp ((char *) doctypeName, "fontconfig") != 0)
+ FcConfigMessage (parse, FcSevereError, "invalid doctype \"%s\"", doctypeName);
+}
+
+static void
+FcEndDoctypeDecl (void *userData)
+{
+}
+
+static FcBool
+FcConfigParseAndLoadDir (FcConfig *config,
+ const FcChar8 *name,
+ const FcChar8 *dir,
+ FcBool complain)
+{
+ DIR *d;
+ struct dirent *e;
+ FcBool ret = FcTrue;
+ FcChar8 *file;
+ FcChar8 *base;
+ FcStrSet *files;
+
+ d = opendir ((char *) dir);
+ if (!d)
+ {
+ if (complain)
+ FcConfigMessage (0, FcSevereError, "Cannot open config dir \"%s\"",
+ name);
+ ret = FcFalse;
+ goto bail0;
+ }
+ /* freed below */
+ file = (FcChar8 *) malloc (strlen ((char *) dir) + 1 + FC_MAX_FILE_LEN + 1);
+ if (!file)
+ {
+ ret = FcFalse;
+ goto bail1;
+ }
+
+ strcpy ((char *) file, (char *) dir);
+ strcat ((char *) file, "/");
+ base = file + strlen ((char *) file);
+
+ files = FcStrSetCreate ();
+ if (!files)
+ {
+ ret = FcFalse;
+ goto bail2;
+ }
+
+ if (FcDebug () & FC_DBG_CONFIG)
+ printf ("\tScanning config dir %s\n", dir);
+
+ while (ret && (e = readdir (d)))
+ {
+ /*
+ * Add all files of the form [0-9]*
+ */
+ if ('0' <= e->d_name[0] && e->d_name[0] <= '9' &&
+ strlen (e->d_name) < FC_MAX_FILE_LEN)
+ {
+ strcpy ((char *) base, (char *) e->d_name);
+ if (!FcStrSetAdd (files, file))
+ {
+ ret = FcFalse;
+ goto bail3;
+ }
+ }
+ }
+ if (ret)
+ {
+ int i;
+ qsort (files->strs, files->num, sizeof (FcChar8 *),
+ (int (*)(const void *, const void *)) FcStrCmp);
+ for (i = 0; ret && i < files->num; i++)
+ ret = FcConfigParseAndLoad (config, files->strs[i], complain);
+ }
+bail3:
+ FcStrSetDestroy (files);
+bail2:
+ free (file);
+bail1:
+ closedir (d);
+bail0:
+ return ret || !complain;
+}
+
+FcBool
+FcConfigParseAndLoad (FcConfig *config,
+ const FcChar8 *name,
+ FcBool complain)
+{
+
+ XML_Parser p;
+ FcChar8 *filename;
+ FILE *f;
+ int len;
+ void *buf;
+ FcConfigParse parse;
+ FcBool error = FcTrue;
+
+ filename = FcConfigFilename (name);
+ if (!filename)
+ goto bail0;
+
+ if (!FcStrSetAdd (config->configFiles, filename))
+ {
+ FcStrFree (filename);
+ goto bail0;
+ }
+
+ if (FcFileIsDir (filename))
+ {
+ FcBool ret = FcConfigParseAndLoadDir (config, name, filename, complain);
+ FcStrFree (filename);
+ return ret;
+ }
+
+ if (FcDebug () & FC_DBG_CONFIG)
+ printf ("\tLoading config file %s\n", filename);
+
+ f = fopen ((char *) filename, "r");
+ FcStrFree (filename);
+ if (!f)
+ goto bail0;
+
+ p = XML_ParserCreate ("UTF-8");
+ if (!p)
+ goto bail1;
+
+ if (!FcConfigInit (&parse, name, config, p))
+ goto bail2;
+
+ XML_SetUserData (p, &parse);
+
+ XML_SetDoctypeDeclHandler (p, FcStartDoctypeDecl, FcEndDoctypeDecl);
+ XML_SetElementHandler (p, FcStartElement, FcEndElement);
+ XML_SetCharacterDataHandler (p, FcCharacterData);
+
+ do {
+ buf = XML_GetBuffer (p, BUFSIZ);
+ if (!buf)
+ {
+ FcConfigMessage (&parse, FcSevereError, "cannot get parse buffer");
+ goto bail3;
+ }
+ len = fread (buf, 1, BUFSIZ, f);
+ if (len < 0)
+ {
+ FcConfigMessage (&parse, FcSevereError, "failed reading config file");
+ goto bail3;
+ }
+ if (!XML_ParseBuffer (p, len, len == 0))
+ {
+ FcConfigMessage (&parse, FcSevereError, "%s",
+ XML_ErrorString (XML_GetErrorCode (p)));
+ goto bail3;
+ }
+ } while (len != 0);
+ error = parse.error;
+bail3:
+ FcConfigCleanup (&parse);
+bail2:
+ XML_ParserFree (p);
+bail1:
+ fclose (f);
+bail0:
+ if (error && complain)
+ {
+ if (name)
+ FcConfigMessage (0, FcSevereError, "Cannot load config file \"%s\"", name);
+ else
+ FcConfigMessage (0, FcSevereError, "Cannot load default config file");
+ return FcFalse;
+ }
+ return FcTrue;
+}
diff --git a/nx-X11/extras/fontconfig/src/fontconfig.def.in b/nx-X11/extras/fontconfig/src/fontconfig.def.in
new file mode 100755
index 000000000..83dac9559
--- /dev/null
+++ b/nx-X11/extras/fontconfig/src/fontconfig.def.in
@@ -0,0 +1,163 @@
+EXPORTS
+ FcAtomicCreate
+ FcAtomicDeleteNew
+ FcAtomicDestroy
+ FcAtomicLock
+ FcAtomicNewFile
+ FcAtomicOrigFile
+ FcAtomicReplaceOrig
+ FcAtomicUnlock
+ FcBlanksAdd
+ FcBlanksCreate
+ FcBlanksDestroy
+ FcBlanksIsMember
+ FcCharSetAddChar
+ FcCharSetCopy
+ FcCharSetCount
+ FcCharSetCreate
+ FcCharSetDestroy
+ FcCharSetEqual
+ FcCharSetFirstPage
+ FcCharSetHasChar
+ FcCharSetIntersect
+ FcCharSetIntersectCount
+ FcCharSetIsSubset
+ FcCharSetNextPage
+ FcCharSetSubtract
+ FcCharSetSubtractCount
+ FcCharSetUnion
+ FcConfigAppFontAddDir
+ FcConfigAppFontAddFile
+ FcConfigAppFontClear
+ FcConfigBuildFonts
+ FcConfigCreate
+ FcConfigDestroy
+ FcConfigEnableHome
+ FcConfigFilename
+ FcConfigGetBlanks
+ FcConfigGetCache
+ FcConfigGetConfigDirs
+ FcConfigGetConfigFiles
+ FcConfigGetCurrent
+ FcConfigGetFontDirs
+ FcConfigGetFonts
+ FcConfigGetRescanInverval
+ FcConfigParseAndLoad
+ FcConfigSetCurrent
+ FcConfigSetRescanInverval
+ FcConfigSubstitute
+ FcConfigSubstituteWithPat
+ FcConfigUptoDate
+ FcDefaultSubstitute
+ FcDirCacheValid
+ FcDirSave
+ FcDirScan
+ FcFileScan
+ FcFini
+ FcFontList
+ FcFontMatch
+ FcFontRenderPrepare
+ FcFontSetAdd
+ FcFontSetCreate
+ FcFontSetDestroy
+ FcFontSetList
+ FcFontSetMatch
+ FcFontSetPrint
+ FcFontSetSort
+ FcFontSetSortDestroy
+ FcFontSort
+ FcFreeTypeCharIndex
+ FcFreeTypeCharSet
+ FcFreeTypeQuery
+ FcGetVersion
+ FcInit
+ FcInitBringUptoDate
+ FcInitLoadConfig
+ FcInitLoadConfigAndFonts
+ FcInitReinitialize
+ FcLangSetAdd
+ FcLangSetCompare
+ FcLangSetCopy
+ FcLangSetCreate
+ FcLangSetDestroy
+ FcLangSetEqual
+ FcLangSetHasLang
+ FcLangSetHash
+ FcMatrixCopy
+ FcMatrixEqual
+ FcMatrixMultiply
+ FcMatrixRotate
+ FcMatrixScale
+ FcMatrixShear
+ FcNameConstant
+ FcNameGetConstant
+ FcNameGetObjectType
+ FcNameParse
+ FcNameRegisterConstants
+ FcNameRegisterObjectTypes
+ FcNameUnparse
+ FcNameUnregisterConstants
+ FcNameUnregisterObjectTypes
+ FcObjectSetAdd
+ FcObjectSetBuild
+ FcObjectSetCreate
+ FcObjectSetDestroy
+ FcObjectSetVaBuild
+ FcPatternAdd
+ FcPatternAddBool
+ FcPatternAddCharSet
+ FcPatternAddDouble
+ FcPatternAddFTFace
+ FcPatternAddInteger
+ FcPatternAddLangSet
+ FcPatternAddMatrix
+ FcPatternAddString
+ FcPatternAddWeak
+ FcPatternBuild
+ FcPatternCreate
+ FcPatternDel
+ FcPatternDestroy
+ FcPatternDuplicate
+ FcPatternEqual
+ FcPatternEqualSubset
+ FcPatternGet
+ FcPatternGetBool
+ FcPatternGetCharSet
+ FcPatternGetDouble
+ FcPatternGetFTFace
+ FcPatternGetInteger
+ FcPatternGetLangSet
+ FcPatternGetMatrix
+ FcPatternGetString
+ FcPatternHash
+ FcPatternPrint
+ FcPatternReference
+ FcPatternVaBuild
+ FcStrBasename
+ FcStrCmp
+ FcStrCmp
+ FcStrCmpIgnoreCase
+ FcStrCopy
+ FcStrCopyFilename
+ FcStrDirname
+ FcStrListCreate
+ FcStrListDone
+ FcStrListNext
+ FcStrSetAdd
+ FcStrSetAddFilename
+ FcStrSetCreate
+ FcStrSetDel
+ FcStrSetDestroy
+ FcStrSetEqual
+ FcStrSetMember
+ FcUcs4ToUtf8
+ FcUtf16Len
+ FcUtf16ToUcs4
+ FcUtf8Len
+ FcUtf8ToUcs4
+ FcValueDestroy
+ FcValueEqual
+ FcValuePrint
+ FcValueSave
+LIBRARY libfontconfig-@LT_CURRENT_MINUS_AGE@.dll
+VERSION @LT_CURRENT@.@LT_REVISION@