Mercurial > hg > xemacs-beta
diff src/font-mgr.c @ 5118:e0db3c197671 ben-lisp-object
merge up to latest default branch, doesn't compile yet
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Sat, 26 Dec 2009 21:18:49 -0600 |
parents | 75975fd0b7fc |
children | 623d57b7fbe8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/font-mgr.c Sat Dec 26 21:18:49 2009 -0600 @@ -0,0 +1,1413 @@ +/* Lisp font handling implementation for X with Xft. + +Copyright (C) 2003 Eric Knauel and Matthias Neubauer +Copyright (C) 2005 Eric Knauel +Copyright (C) 2004-2009 Free Software Foundation, Inc. + +Authors: Eric Knauel <knauel@informatik.uni-tuebingen.de> + Matthias Neubauer <neubauer@informatik.uni-freiburg.de> + Stephen J. Turnbull <stephen@xemacs.org> +Created: 27 Oct 2003 +Updated: 18 November 2009 by Stephen J. Turnbull + +This file is part of XEmacs. + +XEmacs is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 2, or (at your option) any +later version. + +XEmacs is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with XEmacs; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* Synched up with: Not in GNU Emacs. */ + +/* This module provides the Lisp interface to fonts in X11, including Xft, + but (at least at first) not GTK+ or Qt. + + Sealevel code should be in ../lwlib/lwlib-fonts.c or + ../lwlib/lwlib-colors.c. +*/ + +#include <config.h> +#include "lisp.h" +#include "device.h" +#include "device-impl.h" +#include "console-x-impl.h" +#include "objects-x.h" +#include "objects-x-impl.h" +#include "hash.h" +#include "font-mgr.h" + +/* #### TO DO #### + . The "x-xft-*" and "x_xft_*" nomenclature is mostly redundant, especially + if we separate X fonts from Xft fonts, and use fontconfig more generally. + . We should support the most recent Xft first, old Xft libraries later. + . We may (think about it) wish to use fontconfig generally, even if we're + not using Xft. Either way, names that are really from fontconfig should + use the Fc* namespace. + . Mule-ize this file. + . Separate X Font Struct ops from Xft Font ops; give precedence to Xft but + allow fallback to X. + . Push decisions about font choice, defaults, fallbacks to Lisp; if we + really need efficiency, can reimplement in C later. + . Implement symbols interned in this file in the Q* namespace. + . Implement FcMatrix (Lisp vector). + . Implement FcCharSets (Lisp chartable? For implementation hints, see + FcCharSetFirstPage and FcCharSetNextPage). + . Implement FcConfigs. + DONE + . Fontconfig fontnames are encoded in UTF-8. +*/ + +Lisp_Object Qfont_mgr; +Lisp_Object Qfc_patternp; +/* Lisp_Object Qfc_result_match; */ /* FcResultMatch */ +Lisp_Object Qfc_result_type_mismatch; /* FcResultTypeMismatch */ +Lisp_Object Qfc_result_no_match; /* FcResultNoMatch */ +Lisp_Object Qfc_result_no_id; /* FcResultNoId */ +Lisp_Object Qfc_internal_error; +Lisp_Object Qfc_match_pattern; +Lisp_Object Qfc_match_font; +Lisp_Object Vxlfd_font_name_regexp; /* #### Really needed? */ +Fixnum xft_version; +Fixnum fc_version; +Fixnum debug_xft; /* Set to 1 enables lots of obnoxious messages. + Setting it to 2 or 3 enables even more. */ +#ifdef FONTCONFIG_EXPOSE_CONFIG +Lisp_Object Qfc_configp; +static Lisp_Object Vfc_config_weak_list; +#endif + +/**************************************************************** +* FcPattern objects * +****************************************************************/ + +static void +finalize_fc_pattern (void *header, int UNUSED (for_disksave)) +{ + struct fc_pattern *p = (struct fc_pattern *) header; + if (p->fcpatPtr) + { + FcPatternDestroy (p->fcpatPtr); + p->fcpatPtr = 0; + } +} + +static void +print_fc_pattern (Lisp_Object obj, Lisp_Object printcharfun, + int UNUSED(escapeflag)) +{ + struct fc_pattern *c = XFCPATTERN (obj); + if (print_readably) + printing_unreadable_object ("#<fc-pattern 0x%x>", c->header.uid); + write_fmt_string (printcharfun, "#<fc-pattern 0x%x>", c->header.uid); +} + +/* #### We really need an equal method and a hash method (required if you + have an equal method). For the equal method, we can probably use one + or both of + + -- Function: FcBool FcPatternEqual (const FcPattern *pa, const + FcPattern *pb); + Returns whether PA and PB are exactly alike. + + -- Function: FcBool FcPatternEqualSubset (const FcPattern *pa, const + FcPattern *pb, const FcObjectSet *os) + Returns whether PA and PB have exactly the same values for all of + the objects in OS. + + For the hash, we'll have to extract some subset of attributes. + + #### Crap. It's altogether unobvious what we need. x_color_instance + does have a hash method, but fonts are apparently special. I get the + feeling that for this to work properly we're going to need to switch + to fontconfig-based font specifications (although we can allow the + platform syntaxes, the underlying specification object will need to + conform to the fontconfig API, or more precisely the font-mgr API). + + I think the whole `font-truename' interface needs to be dropped. */ + +static const struct memory_description fcpattern_description [] = { + /* #### nothing here, is this right?? */ + { XD_END } +}; + +DEFINE_NODUMP_LISP_OBJECT ("fc-pattern", fc_pattern, + 0, print_fc_pattern, finalize_fc_pattern, + 0, 0, fcpattern_description, + struct fc_pattern); + +/* + * Helper Functions + */ +static Lisp_Object make_xlfd_font_regexp (void); +static void string_list_to_fcobjectset (Lisp_Object list, FcObjectSet *os); + +/* + extract the C representation of the Lisp string STR and convert it + to the encoding used by the Fontconfig API for property and font + names. I suppose that Qnative is the right encoding, the manual + doesn't say much about this topic. This functions assumes that STR + is a Lisp string. +*/ +#define extract_fcapi_string(str) \ + (NEW_LISP_STRING_TO_EXTERNAL ((str), Qfc_font_name_encoding)) + +#define build_fcapi_string(str) \ + (build_ext_string ((Extbyte *) (str), Qfc_font_name_encoding)) + +/* #### This homebrew lashup should be replaced with FcConstants. + + fontconfig assumes that objects (property names) are statically allocated, + and you will get bizarre results if you pass Lisp string data or strings + allocated on the stack as objects. fontconfig _does_ copy values, so we + (I hope) don't have to worry about that member. + + Probably these functions don't get called so often that the memory leak + due to strdup'ing every time we add a property would matter, but XEmacs + _is_ a long-running process. So we hash them. + + I suspect that using symbol names or even keywords does not provide + assurance that the string won't move in memory. So we hash them + ourselves; hash.c hashtables do not interpret the value pointers. + + This array should be FcChar8**, but GCC 4.x bitches about signedness. */ +static Extbyte *fc_standard_properties[] = { + /* treated specially, ordered first */ + "family", "size", + /* remaining are alphabetized by group */ + /* standard properties in fontconfig and Xft v.2 */ + "antialias", "aspect", "autohint", "charset", "dpi", "file", + "foundry", "ftface", "globaladvance", "hinting", "index", "lang", + "minspace", "outline", "pixelsize", "rasterizer", "rgba", "scalable", + "scale", "slant", "spacing", "style", "verticallayout", "weight", + /* common in modern fonts */ + "fontformat", "fontversion", + /* obsolete after Xft v. 1 */ + "charwidth", "charheight", "core", "encoding", "render" +}; + +static struct hash_table *fc_property_name_hash_table; + +/* #### Maybe fc_intern should be exposed to LISP? The idea is that + fc-pattern-add could warn or error if the property isn't interned. */ + +static const Extbyte * +fc_intern (Lisp_Object property) +{ + const void *dummy; + const Extbyte *prop = extract_fcapi_string (property); + const void *val = gethash (prop, fc_property_name_hash_table, &dummy); + + /* extract_fcapi_string returns something alloca'd + so we can just drop the old value of prop on the floor */ + if (val) + prop = (const Extbyte *) val; + else + { + prop = (const Extbyte *) FcStrCopy ((FcChar8 *) prop); + puthash (prop, NULL, fc_property_name_hash_table); + } + return prop; +} + +DEFUN("fc-pattern-p", Ffc_pattern_p, 1, 1, 0, /* +Returns t if OBJECT is of type fc-pattern, nil otherwise. +*/ + (object)) +{ + return FCPATTERNP(object) ? Qt : Qnil; +} + +DEFUN("fc-pattern-create", Ffc_pattern_create, 0, 0, 0, /* +Return a new, empty fc-pattern object. +*/ + ()) +{ + fc_pattern *fcpat = XFCPATTERN (ALLOC_LISP_OBJECT (fc_pattern)); + + fcpat->fcpatPtr = FcPatternCreate (); + return wrap_fcpattern (fcpat); +} + +DEFUN("fc-name-parse", Ffc_name_parse, 1, 1, 0, /* +Parse an Fc font name and return its representation as a fc pattern object. +*/ + (name)) +{ + fc_pattern *fcpat = XFCPATTERN (ALLOC_LISP_OBJECT (fc_pattern)); + + CHECK_STRING (name); + + fcpat->fcpatPtr = FcNameParse ((FcChar8 *) extract_fcapi_string (name)); + return wrap_fcpattern (fcpat); +} + +/* #### Ga-a-ack! Xft's similar function is actually a different API. + We provide both. */ +DEFUN("fc-name-unparse", Ffc_name_unparse, 1, 1, 0, /* +Unparse an fc pattern object to a string. +*/ + (pattern)) +{ + CHECK_FCPATTERN(pattern); + return build_fcapi_string (FcNameUnparse (XFCPATTERN_PTR (pattern))); +} + +DEFUN("fc-pattern-duplicate", Ffc_pattern_duplicate, 1, 1, 0, /* +Make a copy of the fc pattern object PATTERN and return it. +*/ + (pattern)) +{ + struct fc_pattern *copy = NULL; + CHECK_FCPATTERN (pattern); + + copy = XFCPATTERN (ALLOC_LISP_OBJECT (fc_pattern)); + copy->fcpatPtr = FcPatternDuplicate (XFCPATTERN_PTR (pattern)); + return wrap_fcpattern (copy); +} + +DEFUN("fc-pattern-add", Ffc_pattern_add, 3, 3, 0, /* +Add attributes to the pattern object PATTERN. PROPERTY is a string naming +the attribute to add, VALUE the value for this attribute. + +VALUE may be a string, integer, float, or symbol, in which case the value +will be added as an FcChar8[], int, double, or FcBool respectively. +*/ + (pattern, property, value)) +{ + Bool res = 0; + const Extbyte *obj; + FcPattern *fcpat; + + CHECK_FCPATTERN (pattern); + CHECK_STRING (property); + + obj = fc_intern (property); + fcpat = XFCPATTERN_PTR (pattern); + + if (STRINGP(value)) + { + FcChar8 *str = (FcChar8 *) extract_fcapi_string (value); + res = FcPatternAddString (fcpat, obj, str); + } + else if (INTP(value)) + { + res = FcPatternAddInteger (fcpat, obj, XINT(value)); + } + else if (FLOATP(value)) + { + res = FcPatternAddDouble (fcpat, obj, (double) XFLOAT_DATA(value)); + } + else if (SYMBOLP(value)) + { + res = FcPatternAddBool (fcpat, obj, !NILP(value)); + } + /* else ... maybe we should wta here? */ + + return res ? Qt : Qnil; +} + +DEFUN("fc-pattern-del", Ffc_pattern_del, 2, 2, 0, /* +Remove attribute PROPERTY from fc pattern object OBJECT. +*/ + (pattern, property)) +{ + Bool res; + + CHECK_FCPATTERN(pattern); + CHECK_STRING(property); + + res = FcPatternDel(XFCPATTERN_PTR(pattern), extract_fcapi_string (property)); + return res ? Qt : Qnil; +} + +/* Generic interface to FcPatternGet() + * Don't support the losing symbol-for-property interface. + */ +DEFUN("fc-pattern-get", Ffc_pattern_get, 2, 4, 0, /* +From PATTERN, extract PROPERTY for the ID'th member, of type TYPE. + +PATTERN is an Xft (fontconfig) pattern object. +PROPERTY is a string naming an fontconfig font property. +Optional ID is a nonnegative integer indexing the list of values for PROPERTY + stored in PATTERN, defaulting to 0 (the first value). +Optional TYPE is a symbol, one of 'string, 'boolean, 'integer, 'float, + 'double, 'matrix, 'charset, or 'void, corresponding to the FcValue types. + ('float is an alias for 'double). + +The Lisp types returned will conform to TYPE: + string string + boolean `t' or `nil' + integer integer + double (float) float + matrix not implemented + charset not implemented + void not implemented + +Symbols with names of the form "fc-result-DESCRIPTION" are returned when +the desired value is not available. These are + + fc-result-type-mismatch the value found has an unexpected type + fc-result-no-match there is no such attribute + fc-result-no-id there is no value for the requested ID + +The types of the following standard properties are predefined by fontconfig. +The symbol 'fc-result-type-mismatch will be returned if the object exists but +TYPE does not match the predefined type. It is best not to specify a type +for predefined properties, as a mistake here ensures error returns on the +correct type. + +Each standard property has a convenience accessor defined in fontconfig.el, +named in the form "fc-pattern-get-PROPERTY". The convenience functions are +preferred to `fc-pattern-get' since a typo in the string naming a property +will result in a silent null return, while a typo in a function name will +usually result in a compiler or runtime \"not fboundp\" error. You may use +`defsubst' to define convenience functions for non-standard properties. + +family String Font family name +style String Font style. Overrides weight and slant +slant Int Italic, oblique or roman +weight Int Light, medium, demibold, bold or black +size Double Point size +aspect Double Stretches glyphs horizontally before hinting +pixelsize Double Pixel size +spacing Int Proportional, monospace or charcell +foundry String Font foundry name +antialias Bool Whether glyphs can be antialiased +hinting Bool Whether the rasterizer should use hinting +verticallayout Bool Use vertical layout +autohint Bool Use autohinter instead of normal hinter +globaladvance Bool Use font global advance data +file String The filename holding the font +index Int The index of the font within the file +ftface FT_Face Use the specified FreeType face object +rasterizer String Which rasterizer is in use +outline Bool Whether the glyphs are outlines +scalable Bool Whether glyphs can be scaled +scale Double Scale factor for point->pixel conversions +dpi Double Target dots per inch +rgba Int unknown, rgb, bgr, vrgb, vbgr, none - subpixel geometry +minspace Bool Eliminate leading from line spacing +charset CharSet Unicode chars encoded by the font +lang String List of RFC-3066-style languages this font supports + +The FT_Face, Matrix, CharSet types are unimplemented, so the corresponding +properties are not accessible from Lisp at this time. If the value of a +property returned has type FT_Face, FcCharSet, or FcMatrix, +`fc-result-type-mismatch' is returned. + +The following properties which were standard in Xft v.1 are obsolete in +Xft v.2: encoding, charwidth, charheight, core, and render. */ + (pattern, property, id, type)) +{ + Extbyte *fc_property; + FcResult fc_result; + FcValue fc_value; + + /* + process arguments + */ + CHECK_FCPATTERN (pattern); + +#if 0 + /* Don't support the losing symbol-for-property interface. */ + property = SYMBOLP (property) ? symbol_name (XSYMBOL (property)) : property; +#endif + if (STRINGP (property)) + { + fc_property = extract_fcapi_string (property); + } + else + { + /* if we allow symbols, this would need to be + list3 (Qlambda, list1 (Qobject), + list3 (Qor, list2 (Qstringp, Qobject), + list2 (Qsymbolp, Qobject))) + or something like that? */ + dead_wrong_type_argument (Qstringp, property); + } + + if (!NILP (id)) CHECK_NATNUM (id); + if (!NILP (type)) CHECK_SYMBOL (type); + + /* get property */ + fc_result = FcPatternGet (XFCPATTERN_PTR (pattern), + fc_property, + NILP (id) ? 0 : XINT(id), + &fc_value); + + switch (fc_result) + { + case FcResultMatch: + /* wrap it and return */ + switch (fc_value.type) + { + case FcTypeInteger: + return ((!NILP (type) && !EQ (type, Qinteger)) + ? Qfc_result_type_mismatch : make_int (fc_value.u.i)); + case FcTypeDouble: + return ((!NILP (type) && !EQ (type, intern ("double")) + && !EQ (type, Qfloat)) + ? Qfc_result_type_mismatch : make_float (fc_value.u.d)); + case FcTypeString: + return ((!NILP (type) && !EQ (type, Qstring)) + ? Qfc_result_type_mismatch + : build_fcapi_string (fc_value.u.s)); + case FcTypeBool: + return ((!NILP (type) && !EQ (type, Qboolean)) + ? Qfc_result_type_mismatch : fc_value.u.b ? Qt : Qnil); + case FcTypeMatrix: + return Qfc_result_type_mismatch; + /* #### unimplemented + return ((!NILP (type) && !EQ (type, intern ("matrix"))) + ? Qfc_result_type_mismatch : make_int (fc_value.u.m)); + */ + case FcTypeCharSet: + return Qfc_result_type_mismatch; + /* #### unimplemented + return ((!NILP (type) && !EQ (type, intern ("charset"))) + ? Qfc_result_type_mismatch : make_int (fc_value.u.c)); + */ + } + case FcResultTypeMismatch: + return Qfc_result_type_mismatch; + case FcResultNoMatch: + return Qfc_result_no_match; + case FcResultNoId: + return Qfc_result_no_id; + default: + return Qfc_internal_error; + } +} + +/* FcConfig handling functions. */ + +/* We obviously need to be careful about garbage collecting the current + FcConfig. I infer from the documentation of FcConfigDestroy that that + is the only reference maintained by fontconfig. + So we keep track of our own references on a weak list, and only cons a + new object if we don't already have a reference to it there. */ + +enum DestroyFontsetP { DestroyNo = 0, DestroyYes = 1 }; + +static Lisp_Object +fc_config_create_using (FcConfig * (*create_function) ()) +{ + FcConfig *fc = (*create_function) (); + Lisp_Object configs = XWEAK_LIST_LIST (Vfc_config_weak_list); + + /* Linear search: fc_configs are not going to multiply like conses. */ + { + LIST_LOOP_2 (cfg, configs) + if (fc == XFCCONFIG_PTR (cfg)) + return cfg; + } + + { + fc_config *fccfg = XFCCONFIG (ALLOC_LISP_OBJECT (fc_config)); + fccfg->fccfgPtr = fc; + configs = Fcons (wrap_fcconfig (fccfg), configs); + XWEAK_LIST_LIST (Vfc_config_weak_list) = configs; + return wrap_fcconfig (fccfg); + } +} + +static Lisp_Object +fc_strlist_to_lisp_using (FcStrList * (*getter) (FcConfig *), + Lisp_Object config) +{ + FcChar8 *thing; + Lisp_Object value = Qnil; + FcStrList *thing_list; + + CHECK_FCCONFIG (config); + thing_list = (*getter) (XFCCONFIG_PTR(config)); + /* Yes, we need to do this check -- sheesh, Keith! */ + if (!thing_list) + return Qnil; + while ((thing = FcStrListNext (thing_list))) + value = Fcons (build_fcapi_string (thing), value); + FcStrListDone (thing_list); + return value; +} + +static Lisp_Object +fontset_to_list (FcFontSet *fontset, enum DestroyFontsetP destroyp) +{ + int idx; + Lisp_Object fontlist = Qnil; + fc_pattern *fcpat; + + /* #### improve this error message */ + if (!fontset) + Fsignal (Qinvalid_state, + list1 (build_string ("failed to create FcFontSet"))); + for (idx = 0; idx < fontset->nfont; ++idx) + { + fcpat = XFCPATTERN (ALLOC_LISP_OBJECT (fc_pattern)); + fcpat->fcpatPtr = FcPatternDuplicate (fontset->fonts[idx]); + fontlist = Fcons (wrap_fcpattern(fcpat), fontlist); + } + if (destroyp) + FcFontSetDestroy (fontset); + return fontlist; +} + +DEFUN("fc-config-p", Ffc_config_p, 1, 1, 0, /* +Returns t if OBJECT is of type fc-config, nil otherwise. +*/ + (object)) +{ + return FCCONFIGP (object) ? Qt : Qnil; +} + +DEFUN("fc-config-create", Ffc_config_create, 0, 0, 0, /* + -- Function: FcConfig *FcConfigCreate (void) + Creates an empty configuration. */ + ()) +{ + return fc_config_create_using (&FcConfigCreate); +} + +#if 0 +/* I'm sorry, but we just don't do this in Lisp, OK? + Don't even think about implementing this. */ +DEFUN("fc-config-destroy", Ffc_config_destroy, 1, 1, 0, /* + -- Function: void FcConfigDestroy (FcConfig *config) + Destroys a configuration and any data associated with it. Note + that calling this function with the return value from + FcConfigGetCurrent will place the library in an indeterminate + state. */ + (config)) +{ + signal_error (Qunimplemented, "No user-servicable parts!", + intern ("fc-config-destroy")); +} +#endif + +DEFUN("fc-config-up-to-date", Ffc_config_up_to_date, 1, 1, 0, /* + -- Function: FcBool FcConfigUptoDate (FcConfig *config) + Checks all of the files related to 'config' and returns whether the + in-memory version is in sync with the disk version. */ + (config)) +{ + CHECK_FCCONFIG (config); + return FcConfigUptoDate (XFCCONFIG_PTR (config)) == FcFalse ? Qnil : Qt; +} + +DEFUN("fc-config-build-fonts", Ffc_config_build_fonts, 1, 1, 0, /* + -- Function: FcBool FcConfigBuildFonts (FcConfig *config) + Builds the set of available fonts for the given configuration. + Note that any changes to the configuration after this call have + indeterminate effects. Returns FcFalse if this operation runs out + of memory. +XEmacs: signal out-of-memory, or return nil on success. */ + (config)) +{ + CHECK_FCCONFIG (config); + if (FcConfigBuildFonts (XFCCONFIG_PTR (config)) == FcFalse) + out_of_memory ("FcConfigBuildFonts failed", config); + return Qnil; +} + +DEFUN("fc-config-get-config-dirs", Ffc_config_get_config_dirs, 1, 1, 0, /* + -- Function: FcStrList *FcConfigGetConfigDirs (FcConfig *config) + Returns the list of font directories specified in the + configuration files for 'config'. Does not include any + subdirectories. */ + (config)) +{ + return fc_strlist_to_lisp_using (&FcConfigGetConfigDirs, config); +} + +DEFUN("fc-config-get-font-dirs", Ffc_config_get_font_dirs, 1, 1, 0, /* + -- Function: FcStrList *FcConfigGetFontDirs (FcConfig *config) + Returns the list of font directories in 'config'. This includes the + configured font directories along with any directories below those + in the filesystem. */ + (config)) +{ + return fc_strlist_to_lisp_using (&FcConfigGetFontDirs, config); +} + +DEFUN("fc-config-get-config-files", Ffc_config_get_config_files, 1, 1, 0, /* + -- Function: FcStrList *FcConfigGetConfigFiles (FcConfig *config) + Returns the list of known configuration files used to generate + 'config'. Note that this will not include any configuration done + with FcConfigParse. */ + (config)) +{ + return fc_strlist_to_lisp_using (&FcConfigGetConfigFiles, config); +} + +DEFUN("fc-config-get-cache", Ffc_config_get_cache, 1, 1, 0, /* + -- Function: char *FcConfigGetCache (FcConfig *config) + Returns the name of the file used to store per-user font + information. */ + (config)) +{ + CHECK_FCCONFIG (config); + /* Surely FcConfigGetCache just casts an FcChar8* to char*. */ + return build_fcapi_string ((FcChar8 *) FcConfigGetCache (XFCCONFIG_PTR (config))); +} + +DEFUN("fc-config-get-fonts", Ffc_config_get_fonts, 2, 2, 0, /* + -- Function: FcFontSet *FcConfigGetFonts (FcConfig *config, FcSetName set) + Returns one of the two sets of fonts from the configuration as + specified by 'set'. + `FcSetName' + Specifies one of the two sets of fonts available in a + configuration; FcSetSystem for those fonts specified in the + configuration and FcSetApplication which holds fonts provided by + the application. */ + (config, set)) +{ + FcSetName name = FcSetSystem; + FcFontSet *fs = NULL; + + CHECK_FCCONFIG (config); + CHECK_SYMBOL (set); + + if (EQ (set, intern ("fc-set-system"))) + name = FcSetSystem; + else if (EQ (set, intern ("fc-set-application"))) + name = FcSetApplication; + else + wtaerror ("must be in (fc-set-system fc-set-application)", set); + + fs = FcConfigGetFonts (XFCCONFIG_PTR (config), name); + return fs ? fontset_to_list (fs, DestroyNo) : Qnil; +} + +DEFUN("fc-config-set-current", Ffc_config_set_current, 1, 1, 0, /* + -- Function: FcBool FcConfigSetCurrent (FcConfig *config) + Sets the current default configuration to 'config'. Implicitly + calls FcConfigBuildFonts if necessary, returning FcFalse if that + call fails. +XEmacs: signals out-of-memory if FcConfigBuildFonts fails, or args-out-of-range +if the resulting FcConfig has no fonts (which would crash XEmacs if installed). +*/ + (config)) +{ + CHECK_FCCONFIG (config); + /* *sigh* "Success" DOES NOT mean you have any fonts available. It is + easy to crash fontconfig, and XEmacs with it. Without the following + check, this will do it: + (progn + (fc-config-set-current (fc-config-create)) + (set-face-font 'default "serif-12")) + */ + + if (FcConfigBuildFonts (XFCCONFIG_PTR (config)) == FcFalse) + out_of_memory ("FcConfigBuildFonts failed", config); + /* #### We'd like to avoid this consing, and FcConfigGetFonts sometimes + returns NULL, but it doesn't always. This will do for now .... */ + if (NILP (Ffc_config_get_fonts (config, intern ("fc-set-system"))) + && NILP (Ffc_config_get_fonts (config, intern ("fc-set-application")))) + signal_error (intern ("args-out-of-range"), "no fonts found", config); + /* Should never happen, but I don't trust Keith anymore .... */ + if (FcConfigSetCurrent (XFCCONFIG_PTR (config)) == FcFalse) + out_of_memory ("FcConfigBuildFonts failed in set", config); + return Qnil; +} + +DEFUN("fc-config-get-blanks", Ffc_config_get_blanks, 1, 1, 0, /* + -- Function: FcBlanks *FcConfigGetBlanks (FcConfig *config) + Returns the FcBlanks object associated with the given + configuration, if no blanks were present in the configuration, + this function will return 0. +XEmacs: should convert to a chartable. +#### Unimplemented. */ + (config)) +{ + CHECK_FCCONFIG (config); + signal_error (Qunimplemented, "no method to convert FcBlanks object", + intern ("fc-config-get-blanks")); +} + +DEFUN("fc-config-get-rescan-interval", Ffc_config_get_rescan_interval, 1, 1, 0, /* + -- Function: int FcConfigGetRescanInterval (FcConfig *config) + Returns the interval between automatic checks of the configuration + (in seconds) specified in 'config'. The configuration is checked + during a call to FcFontList when this interval has passed since + the last check. */ + (config)) +{ + CHECK_FCCONFIG (config); + return make_int (FcConfigGetRescanInterval (XFCCONFIG_PTR (config))); +} + +DEFUN("fc-config-set-rescan-interval", Ffc_config_set_rescan_interval, 2, 2, 0, /* + -- Function: FcBool FcConfigSetRescanInterval (FcConfig *config, int + rescanInterval) + Sets the rescan interval; returns FcFalse if an error occurred. + XEmacs: signal such error, or return nil on success. */ + (config, rescan_interval)) +{ + CHECK_FCCONFIG (config); + CHECK_INT (rescan_interval); + if (FcConfigSetRescanInterval (XFCCONFIG_PTR (config), + XINT (rescan_interval)) == FcFalse) + signal_error (Qio_error, "FcConfigSetRescanInverval barfed", + intern ("fc-config-set-rescan-interval")); + return Qnil; +} + +/* #### This might usefully be made interactive. */ +DEFUN("fc-config-app-font-add-file", Ffc_config_app_font_add_file, 2, 2, 0, /* + -- Function: FcBool FcConfigAppFontAddFile (FcConfig *config, const + char *file) + Adds an application-specific font to the configuration. */ + (config, file)) +{ + CHECK_FCCONFIG (config); + CHECK_STRING (file); + if (FcConfigAppFontAddFile + (XFCCONFIG_PTR (config), + /* #### FIXME! is this really Qnative? */ + (FcChar8 *) NEW_LISP_STRING_TO_EXTERNAL ((file), Qnative)) == FcFalse) + return Qnil; + else + return Qt; +} + +/* #### This might usefully be made interactive. */ +DEFUN("fc-config-app-font-add-dir", Ffc_config_app_font_add_dir, 2, 2, 0, /* + -- Function: FcBool FcConfigAppFontAddDir (FcConfig *config, const + char *dir) + Scans the specified directory for fonts, adding each one found to + the application-specific set of fonts. */ + (config, dir)) +{ + CHECK_FCCONFIG (config); + CHECK_STRING (dir); + if (FcConfigAppFontAddDir + (XFCCONFIG_PTR (config), + /* #### FIXME! is this really Qnative? */ + (FcChar8 *) NEW_LISP_STRING_TO_EXTERNAL ((dir), Qnative)) == FcFalse) + return Qnil; + else + return Qt; +} + +/* #### This might usefully be made interactive. */ +DEFUN("fc-config-app-font-clear", Ffc_config_app_font_clear, 1, 1, 0, /* + -- Function: void FcConfigAppFontClear (FcConfig *config) + Clears the set of application-specific fonts. */ + (config)) +{ + CHECK_FCCONFIG (config); + FcConfigAppFontClear (XFCCONFIG_PTR (config)); + return Qnil; +} + +/* These functions provide some control over how the default + configuration of the library is initialized. (This configuration is + normally implicitly initialized.) */ + +DEFUN("fc-config-filename", Ffc_config_filename, 1, 1, 0, /* + -- Function: char *FcConfigFilename (const char *name) + Given the specified external entity name, return the associated + filename. This provides applications a way to convert various + configuration file references into filename form. + + A null or empty 'name' indicates that the default configuration + file should be used; which file this references can be overridden + with the FC_CONFIG_FILE environment variable. Next, if the name + starts with '~', it refers to a file in the current users home + directory. Otherwise if the name doesn't start with '/', it + refers to a file in the default configuration directory; the + built-in default directory can be overridden with the + FC_CONFIG_DIR environment variable. */ + (name)) +{ + char *fcname = ""; + + if (!NILP (name)) + { + CHECK_STRING (name); + /* #### FIXME! is this really Qnative? */ + fcname = NEW_LISP_STRING_TO_EXTERNAL (name, Qnative); + } + return (build_fcapi_string (FcConfigFilename ((FcChar8 *) fcname))); +} + +DEFUN("fc-init-load-config", Ffc_init_load_config, 0, 0, 0, /* + -- Function: FcConfig *FcInitLoadConfig (void) + Loads the default configuration file and returns the resulting + configuration. Does not load any font information. */ + ()) +{ + return fc_config_create_using (&FcInitLoadConfig); +} + +DEFUN("fc-init-load-config-and-fonts", Ffc_init_load_config_and_fonts, 0, 0, 0, /* + -- Function: FcConfig *FcInitLoadConfigAndFonts (void) + Loads the default configuration file and builds information about + the available fonts. Returns the resulting configuration. */ + ()) +{ + return fc_config_create_using (&FcInitLoadConfigAndFonts); +} + +DEFUN("fc-config-get-current", Ffc_config_get_current, 0, 0, 0, /* + -- Function: FcConfig *FcConfigGetCurrent (void) + Returns the current default configuration. */ + ()) +{ + return fc_config_create_using (&FcConfigGetCurrent); +} + +/* Pattern manipulation functions. */ + +DEFUN("fc-default-substitute", Ffc_default_substitute, 1, 1, 0, /* +Adds defaults for certain attributes if not specified in PATTERN. +FcPattern PATTERN is modified in-place, and nil is returned. +* Patterns without a specified style or weight are set to Medium +* Patterns without a specified style or slant are set to Roman +* Patterns without a specified pixel size are given one computed from any + specified point size (default 12), dpi (default 75) and scale (default 1). */ + (pattern)) +{ + CHECK_FCPATTERN (pattern); + FcDefaultSubstitute (XFCPATTERN_PTR (pattern)); + return Qnil; +} + +/* -- Function: FcBool FcConfigSubstituteWithPat (FcConfig *config, + FcPattern *p, FcPattern *p_pat FcMatchKind kind) + OMITTED: use optional arguments in `fc-config-substitute'. */ + +DEFUN("fc-config-substitute", Ffc_config_substitute, 1, 4, 0, /* +Modifies PATTERN according to KIND and TESTPAT using operations from CONFIG. +PATTERN is modified in-place. Returns an undocumented Boolean value. +If optional KIND is `fc-match-pattern', then those tagged as pattern operations +are applied, else if KIND is `fc-match-font', those tagged as font operations +are applied and TESTPAT is used for <test> elements with target=pattern. KIND +defaults to `fc-match-font'. +If optional TESTPAT is nil, it is ignored. Otherwise it must be an FcPattern. +Optional CONFIG must be an FcConfig, defaulting to the current one. + +Note that this function actually corresponds to FcConfigSubstituteWithPat, and +the argument order is changed to take advantage of Lisp optional arguments. */ + (pattern, kind, testpat, config)) +{ + FcMatchKind knd; + + /* There ought to be a standard idiom for this.... */ + if (NILP (kind) + || EQ (kind, Qfc_match_font)) { + knd = FcMatchFont; + } + else if (EQ (kind, Qfc_match_pattern)) { + knd = FcMatchPattern; + } + else { + Fsignal (Qwrong_type_argument, + list2 (build_string ("need `fc-match-pattern' or `fc-match-font'"), + kind)); + } + + /* Typecheck arguments */ + CHECK_FCPATTERN (pattern); + if (!NILP (testpat)) CHECK_FCPATTERN (testpat); + if (!NILP (config)) CHECK_FCCONFIG (config); + + return (FcConfigSubstituteWithPat + (NILP (config) ? FcConfigGetCurrent () : XFCCONFIG_PTR (config), + XFCPATTERN_PTR (pattern), + NILP (testpat) ? NULL : XFCPATTERN_PTR (testpat), + knd) == FcTrue) + ? Qt : Qnil; +} + +/* Pattern matching functions. */ + +/* The following functions return fonts that match a certain pattern. + `FcFontRenderPrepare' and `FcFontMatch' always return a single best + match. `FcFontList' returns the list of fonts that match a given + pattern on a certain set of properties. `FcFontSort' returns the + entire list of fonts, sorted in order of match quality, possibly + filtering out fonts that do not provide additional characters beyond + those provided by preferred fonts. */ + +DEFUN("fc-font-render-prepare", Ffc_font_render_prepare, 2, 3, 0, /* +Return a new pattern blending PATTERN and FONT. +Optional CONFIG is an FcConfig, defaulting to the current one. +The returned pattern consists of elements of FONT not appearing in PATTERN, +elements of PATTERN not appearing in FONT, and the best matching value from +PATTERN for elements appearing in both. The result is passed to +FcConfigSubstitute with 'kind' FcMatchFont and then returned. */ + (pattern, font, config)) +{ + if (NILP (config)) { + config = Ffc_config_get_current (); + } + CHECK_FCPATTERN (pattern); + CHECK_FCPATTERN (font); + CHECK_FCCONFIG (config); + + /* I don't think this can fail? */ + return wrap_fcpattern (FcFontRenderPrepare (XFCCONFIG_PTR(config), + XFCPATTERN_PTR(font), + XFCPATTERN_PTR(pattern))); +} + +DEFUN("fc-font-match", Ffc_font_match, 2, 3, 0, /* +Return the font on DEVICE that most closely matches PATTERN. + +DEVICE is an X11 device. +PATTERN is a fontconfig pattern object. +Optional CONFIG is an FcConfig, defaulting to the current one. +Returns a fontconfig pattern object representing the closest match to the +given pattern, or an error code. Possible error codes are +`fc-result-no-match' and `fc-result-no-id'. +PATTERN is massaged with FcConfigSubstitute and FcDefaultSubstitute before +being processed by FcFontMatch. */ + (device, pattern, config)) +{ + FcResult res; + struct fc_pattern *res_fcpat; + FcPattern *p; + FcConfig *fcc; + + CHECK_FCPATTERN(pattern); + if (NILP(device)) + return Qnil; + CHECK_X_DEVICE(device); + if (!DEVICE_LIVE_P(XDEVICE(device))) + return Qnil; + if (!NILP (config)) + CHECK_FCCONFIG (config); + + res_fcpat = XFCPATTERN (ALLOC_LISP_OBJECT (fc_pattern)); + p = XFCPATTERN_PTR(pattern); + fcc = NILP (config) ? FcConfigGetCurrent () : XFCCONFIG_PTR (config); + + FcConfigSubstitute (fcc, p, FcMatchPattern); + FcDefaultSubstitute (p); + res_fcpat->fcpatPtr = FcFontMatch (fcc, p, &res); + + if (res_fcpat->fcpatPtr == NULL) + switch (res) { + case FcResultNoMatch: + return Qfc_result_no_match; + case FcResultNoId: + return Qfc_result_no_id; + default: + return Qfc_internal_error; + } + else + return wrap_fcpattern(res_fcpat); +} + +/* #### fix this name to correspond to Ben's new nomenclature */ +DEFUN("fc-list-fonts-pattern-objects", Ffc_list_fonts_pattern_objects, + 3, 3, 0, /* +Return a list of fonts on DEVICE that match PATTERN for PROPERTIES. +Each font is represented by a fontconfig pattern object. + +DEVICE is an X11 device. +PATTERN is a fontconfig pattern to be matched. +PROPERTIES is a list of property names (strings) that should match. + +#### DEVICE is unused, ignored, and may be removed if it's not needed to +match other font-listing APIs. */ + (UNUSED (device), pattern, properties)) +{ + FcObjectSet *os; + FcFontSet *fontset; + + CHECK_FCPATTERN (pattern); + CHECK_LIST (properties); + + os = FcObjectSetCreate (); + string_list_to_fcobjectset (properties, os); + /* #### why don't we need to do the "usual substitutions"? */ + fontset = FcFontList (NULL, XFCPATTERN_PTR (pattern), os); + FcObjectSetDestroy (os); + + return fontset_to_list (fontset, DestroyYes); + +} + +/* #### maybe this can/should be folded into fc-list-fonts-pattern-objects? */ +DEFUN("fc-font-sort", Ffc_font_sort, 2, 4, 0, /* +Return a list of all fonts sorted by proximity to PATTERN. +Each font is represented by a fontconfig pattern object. + +DEVICE is an X11 device. +PATTERN is a fontconfig pattern to be matched. +Optional argument TRIM, if non-nil, means to trim trailing fonts that do not +contribute new characters to the union repertoire. + +#### Optional argument NOSUB, if non-nil, suppresses some of the usual +property substitutions. DON'T USE THIS in production code, it is intended +for exploring behavior of fontconfig and will be removed when this code is +stable. + +#### DEVICE is unused, ignored, and may be removed if it's not needed to +match other font-listing APIs. */ + (UNUSED (device), pattern, trim, nosub)) +{ + CHECK_FCPATTERN (pattern); + + { + FcConfig *fcc = FcConfigGetCurrent(); + FcFontSet *fontset; + FcPattern *p = XFCPATTERN_PTR (pattern); + FcResult fcresult; + + if (NILP(nosub)) /* #### temporary debug hack */ + FcDefaultSubstitute (p); + FcConfigSubstitute (fcc, p, FcMatchPattern); + fontset = FcFontSort (fcc, p, !NILP(trim), NULL, &fcresult); + + return fontset_to_list (fontset, DestroyYes); + } +} + +#ifdef FONTCONFIG_EXPOSE_CONFIG + +/* Configuration routines --- for debugging + Don't depend on these routines being available in the future! + + 3.2.10 Initialization + --------------------- + + An FcConfig object holds the internal representation of a configuration. + There is a default configuration which applications may use by passing + 0 to any function using the data within an FcConfig. +*/ + +static void +finalize_fc_config (void *header, int UNUSED (for_disksave)) +{ + struct fc_config *p = (struct fc_config *) header; + if (p->fccfgPtr && p->fccfgPtr != FcConfigGetCurrent()) + { + /* If we get here, all of *our* references are garbage (see comment on + fc_config_create_using() for why), and the only reference that + fontconfig keeps is the current FcConfig. */ + FcConfigDestroy (p->fccfgPtr); + } + p->fccfgPtr = 0; +} + +static void +print_fc_config (Lisp_Object obj, Lisp_Object printcharfun, + int UNUSED(escapeflag)) +{ + struct fc_config *c = XFCCONFIG (obj); + if (print_readably) + printing_unreadable_object ("#<fc-config 0x%x>", c->header.uid); + write_fmt_string (printcharfun, "#<fc-config 0x%x>", c->header.uid); +} + +static const struct memory_description fcconfig_description [] = { + /* #### nothing here, is this right?? */ + { XD_END } +}; + +DEFINE_NODUMP_LISP_OBJECT ("fc-config", fc_config, + 0, print_fc_config, finalize_fc_config, 0, 0, + fcconfig_description, + struct fc_config); + +DEFUN("fc-init", Ffc_init, 0, 0, 0, /* + -- Function: FcBool FcInit (void) + Loads the default configuration file and the fonts referenced + therein and sets the default configuration to that result. + Returns whether this process succeeded or not. If the default + configuration has already been loaded, this routine does nothing + and returns FcTrue. */ + ()) +{ + return (FcInit () == FcTrue) ? Qt : Qnil; +} + +DEFUN("fc-get-version", Ffc_get_version, 0, 0, 0, /* + -- Function: int FcGetVersion (void) + Returns the version number of the library. +XEmacs: No, this should NOT return a pretty string. + (let ((i (fc-get-version))) + (format "%d.%d.%d" (/ i 10000) (mod (/ i 100) 100) (mod i 100))) +gives the usual x.y.z format. This is the version of the .so. It can be +checked against `fc-version', which is the version of fontconfig.h. +It's probably not a disaster if `(> (fc-get-version) fc-version)'. */ + ()) +{ + return make_int (FcGetVersion ()); +} + +DEFUN("fc-init-reinitialize", Ffc_init_reinitialize, 0, 0, 0, /* + -- Function: FcBool FcInitReinitialize (void) + Forces the default configuration file to be reloaded and resets + the default configuration. */ + ()) +{ + return (FcInitReinitialize () == FcTrue) ? Qt : Qnil; +} + +DEFUN("fc-init-bring-up-to-date", Ffc_init_bring_up_to_date, 0, 0, 0, /* + -- Function: FcBool FcInitBringUptoDate (void) + Checks the rescan interval in the default configuration, checking + the configuration if the interval has passed and reloading the + configuration when any changes are detected. */ + ()) +{ + return (FcInitBringUptoDate () == FcTrue) ? Qt : Qnil; +} + +#endif /* FONTCONFIG_EXPOSE_CONFIG */ + +DEFUN("xlfd-font-name-p", Fxlfd_font_name_p, 1, 1, 0, /* +Check whether the string FONTNAME is a XLFD font name. */ + (fontname)) +{ + CHECK_STRING(fontname); + /* #### should bind `case-fold-search' here? */ + return Fstring_match(Vxlfd_font_name_regexp, fontname, Qnil, Qnil); +} + +/* FcPatternPrint: there is no point in having wrappers fc-pattern-print, + Ffc_pattern_print since this function prints to stdout. */ + +/* Initialization of font-mgr */ + +#define XE_XLFD_SEPARATOR "-" + /* XLFD specifies ISO 8859-1 encoding, but we can't handle non-ASCII + in Mule when this function is called. So use HPC. */ +#if 0 +#define XE_XLFD_PREFIX "\\(\\+[\040-\176\240-\377]*\\)?-" +#define XE_XLFD_OPT_TEXT "\\([\040-\044\046-\176\240-\377]*\\)" +#define XE_XLFD_TEXT "\\([\040-\044\046-\176\240-\377]+\\)" +#else +#define XE_XLFD_PREFIX "\\(\\+[\040-\176]*\\)?-" +#define XE_XLFD_OPT_TEXT "\\([^-]*\\)" +#define XE_XLFD_TEXT "\\([^-]+\\)" +#endif + +#define XE_XLFD_SLANT "\\([0-9ior?*][iot]?\\)" +#define XE_XLFD_SPACING "\\([cmp?*]\\)" + /* Hyphen as minus conflicts with use as separator. */ +#define XE_XLFD_OPT_NEGATE "~?" +#define XE_XLFD_NUMBER "\\([0-9?*]+\\)" +#define XE_XLFD_PSIZE "\\([0-9?*]+\\|\\[[ 0-9+~.e?*]+\\]\\)" + +/* Call this only from the init code + #### This is really horrible, let's get rid of it, please. */ +static Lisp_Object +make_xlfd_font_regexp (void) +{ + struct gcpro gcpro1; + unsigned i; + Lisp_Object reg = Qnil; + const Extbyte *re[] = /* #### This could just be catenated by + cpp and passed to build_ext_string. */ + { + /* Regular expression matching XLFDs as defined by XLFD v. 1.5. + Matches must be case-insensitive. + PSIZE is a pixel or point size, which may be a "matrix". The + syntax of a matrix is not checked, just some lexical properties. + AFAICT none of the TEXT fields except adstyle is optional. + + NB. It should not be a problem if this matches "too much", since + an "old" server will simply not be able to find a matching font. */ + "\\`", + XE_XLFD_PREFIX, /* prefix */ + XE_XLFD_TEXT, /* foundry */ + XE_XLFD_SEPARATOR, + XE_XLFD_TEXT, /* family */ + XE_XLFD_SEPARATOR, + XE_XLFD_TEXT, /* weight */ + XE_XLFD_SEPARATOR, + XE_XLFD_SLANT, /* slant */ + XE_XLFD_SEPARATOR, + XE_XLFD_TEXT, /* swidth */ + XE_XLFD_SEPARATOR, + XE_XLFD_OPT_TEXT, /* adstyle */ + XE_XLFD_SEPARATOR, + XE_XLFD_PSIZE, /* pixelsize */ + XE_XLFD_SEPARATOR, + XE_XLFD_PSIZE, /* pointsize */ + XE_XLFD_SEPARATOR, + XE_XLFD_NUMBER, /* resx */ + XE_XLFD_SEPARATOR, + XE_XLFD_NUMBER, /* resy */ + XE_XLFD_SEPARATOR, + XE_XLFD_SPACING, /* spacing */ + XE_XLFD_SEPARATOR, + XE_XLFD_OPT_NEGATE, /* avgwidth */ + XE_XLFD_NUMBER, + XE_XLFD_SEPARATOR, + XE_XLFD_TEXT, /* registry */ + XE_XLFD_SEPARATOR, + XE_XLFD_TEXT, /* encoding */ + "\\'" + }; + + GCPRO1 (reg); + for (i = 0; i < sizeof(re)/sizeof(Extbyte *); i++) + { + /* #### Currently this is Host Portable Coding, not ISO 8859-1. */ + reg = concat2(reg, build_ext_string (re[i], Qx_font_name_encoding)); + } + + RETURN_UNGCPRO (reg); +} +#undef XE_XLFD_SEPARATOR +#undef XE_XLFD_PREFIX +#undef XE_XLFD_OPT_TEXT +#undef XE_XLFD_TEXT +#undef XE_XLFD_OPT_SLANT +#undef XE_XLFD_OPT_SPACING +#undef XE_XLFD_OPT_NEGATE +#undef XE_XLFD_NUMBER +#undef XE_XLFD_PSIZE + +#define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \ + ? ((unsigned long) (x)) : ((unsigned long) (y))) + +static void +string_list_to_fcobjectset (Lisp_Object list, FcObjectSet *os) +{ + EXTERNAL_LIST_LOOP_2 (elt, list) + { + const Extbyte *s; + + CHECK_STRING (elt); + s = fc_intern (elt); + FcObjectSetAdd (os, s); + } +} + +void +syms_of_font_mgr (void) { + INIT_LISP_OBJECT(fc_pattern); + + DEFSYMBOL_MULTIWORD_PREDICATE(Qfc_patternp); + + DEFSYMBOL(Qfc_result_type_mismatch); + DEFSYMBOL(Qfc_result_no_match); + DEFSYMBOL(Qfc_result_no_id); + DEFSYMBOL(Qfc_internal_error); + DEFSYMBOL(Qfc_match_pattern); + DEFSYMBOL(Qfc_match_font); + DEFSYMBOL(Qfont_mgr); + + DEFSUBR(Ffc_pattern_p); + DEFSUBR(Ffc_pattern_create); + DEFSUBR(Ffc_name_parse); + DEFSUBR(Ffc_name_unparse); + DEFSUBR(Ffc_pattern_duplicate); + DEFSUBR(Ffc_pattern_add); + DEFSUBR(Ffc_pattern_del); + DEFSUBR(Ffc_pattern_get); + DEFSUBR(Ffc_list_fonts_pattern_objects); + DEFSUBR(Ffc_font_sort); + DEFSUBR(Ffc_font_match); + DEFSUBR(Ffc_default_substitute); + DEFSUBR(Ffc_config_substitute); + DEFSUBR(Ffc_font_render_prepare); + DEFSUBR(Fxlfd_font_name_p); + +#ifdef FONTCONFIG_EXPOSE_CONFIG + INIT_LISP_OBJECT(fc_config); + + DEFSYMBOL_MULTIWORD_PREDICATE(Qfc_configp); + + DEFSUBR(Ffc_config_p); + DEFSUBR(Ffc_config_create); +#if 0 + DEFSUBR(Ffc_config_destroy); +#endif + DEFSUBR(Ffc_config_set_current); + DEFSUBR(Ffc_config_get_current); + DEFSUBR(Ffc_config_up_to_date); + DEFSUBR(Ffc_config_build_fonts); + DEFSUBR(Ffc_config_get_config_dirs); + DEFSUBR(Ffc_config_get_font_dirs); + DEFSUBR(Ffc_config_get_config_files); + DEFSUBR(Ffc_config_get_cache); + DEFSUBR(Ffc_config_get_fonts); + DEFSUBR(Ffc_config_get_blanks); + DEFSUBR(Ffc_config_get_rescan_interval); + DEFSUBR(Ffc_config_set_rescan_interval); + DEFSUBR(Ffc_config_app_font_add_file); + DEFSUBR(Ffc_config_app_font_add_dir); + DEFSUBR(Ffc_config_app_font_clear); + DEFSUBR(Ffc_config_filename); + DEFSUBR(Ffc_init_load_config); + DEFSUBR(Ffc_init_load_config_and_fonts); + DEFSUBR(Ffc_init); + DEFSUBR(Ffc_get_version); + DEFSUBR(Ffc_init_reinitialize); + DEFSUBR(Ffc_init_bring_up_to_date); +#endif /* FONTCONFIG_EXPOSE_CONFIG */ +} + +void +vars_of_font_mgr (void) +{ + /* #### The next two DEFVARs belong somewhere else. */ + + /* #### I know, but the right fix is use the generic debug facility. */ + DEFVAR_INT ("xft-debug-level", &debug_xft /* +Level of debugging messages to issue to stderr for Xft. +A nonnegative integer. Set to 0 to suppress all warnings. +Default is 1 to ensure a minimum of debugging output at initialization. +Higher levels give even more information. +*/ ); + debug_xft = 0; + + DEFVAR_CONST_INT("xft-version", &xft_version /* +The major version number of the Xft library being used. +*/ ); + xft_version = XFT_VERSION; + + DEFVAR_CONST_INT("fc-version", &fc_version /* +The version number of fontconfig.h. It can be checked against +`(fc-get-version)', which is the version of the .so. +It's probably not a disaster if `(> (fc-get-version) fc-version)'. +*/ ); + fc_version = FC_VERSION; + + Fprovide (intern ("font-mgr")); +} + +void +complex_vars_of_font_mgr (void) +{ +#ifdef FONTCONFIG_EXPOSE_CONFIG + Vfc_config_weak_list = make_weak_list (WEAK_LIST_SIMPLE); + staticpro (&Vfc_config_weak_list); +#endif + + DEFVAR_LISP("xft-xlfd-font-regexp", &Vxlfd_font_name_regexp /* +The regular expression used to match XLFD font names. */ + ); + Vxlfd_font_name_regexp = make_xlfd_font_regexp(); +} + +void +reinit_vars_of_font_mgr (void) +{ + int i, size = (int) countof (fc_standard_properties); + + FcInit (); + + fc_property_name_hash_table = make_string_hash_table (size); + for (i = 0; i < size; ++i) + puthash (fc_standard_properties[i], NULL, fc_property_name_hash_table); +} +