3354
|
1 /* Lisp font handling implementation for X with Xft.
|
|
2
|
|
3 Copyright (C) 2003 Eric Knauel and Matthias Neubauer
|
|
4 Copyright (C) 2005 Eric Knauel
|
3906
|
5 Copyright (C) 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
|
3354
|
6
|
|
7 Authors: Eric Knauel <knauel@informatik.uni-tuebingen.de>
|
|
8 Matthias Neubauer <neubauer@informatik.uni-freiburg.de>
|
|
9 Stephen J. Turnbull <stephen@xemacs.org>
|
|
10 Created: 27 Oct 2003
|
3906
|
11 Updated: 14 April 2007 by Stephen J. Turnbull
|
3354
|
12
|
|
13 This file is part of XEmacs.
|
|
14
|
|
15 XEmacs is free software; you can redistribute it and/or modify it
|
|
16 under the terms of the GNU General Public License as published by the
|
|
17 Free Software Foundation; either version 2, or (at your option) any
|
|
18 later version.
|
|
19
|
|
20 XEmacs is distributed in the hope that it will be useful, but WITHOUT
|
|
21 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
22 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
23 for more details.
|
|
24
|
|
25 You should have received a copy of the GNU General Public License
|
|
26 along with XEmacs; see the file COPYING. If not, write to
|
|
27 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
28 Boston, MA 02111-1307, USA. */
|
|
29
|
|
30 /* Synched up with: Not in GNU Emacs. */
|
|
31
|
|
32 /* This module provides the Lisp interface to fonts in X11, including Xft,
|
|
33 but (at least at first) not GTK+ or Qt.
|
|
34
|
|
35 Sealevel code should be in ../lwlib/lwlib-fonts.c or
|
|
36 ../lwlib/lwlib-colors.c.
|
|
37 */
|
|
38
|
|
39 #include <config.h>
|
|
40 #include "lisp.h"
|
|
41 #include "device.h"
|
|
42 #include "device-impl.h"
|
|
43 #include "console-x-impl.h"
|
|
44 #include "objects-x.h"
|
|
45 #include "objects-x-impl.h"
|
|
46 #include "hash.h"
|
|
47 #include "font-mgr.h"
|
|
48
|
|
49 /* #### TO DO ####
|
|
50 . The "x-xft-*" and "x_xft_*" nomenclature is mostly redundant, especially
|
|
51 if we separate X fonts from Xft fonts, and use fontconfig more generally.
|
|
52 . We should support the most recent Xft first, old Xft libraries later.
|
|
53 . We may (think about it) wish to use fontconfig generally, even if we're
|
|
54 not using Xft. Either way, names that are really from fontconfig should
|
|
55 use the Fc* namespace.
|
|
56 . Mule-ize this file.
|
|
57 . Separate X Font Struct ops from Xft Font ops; give precedence to Xft but
|
|
58 allow fallback to X.
|
|
59 . Push decisions about font choice, defaults, fallbacks to Lisp; if we
|
|
60 really need efficiency, can reimplement in C later.
|
|
61 . Implement symbols interned in this file in the Q* namespace.
|
|
62 . Implement FcMatrix (Lisp vector).
|
|
63 . Implement FcCharSets (Lisp chartable? For implementation hints, see
|
|
64 FcCharSetFirstPage and FcCharSetNextPage).
|
|
65 . Implement FcConfigs.
|
|
66 DONE
|
|
67 . Fontconfig fontnames are encoded in UTF-8.
|
|
68 */
|
|
69
|
3360
|
70 Lisp_Object Qfont_mgr;
|
3354
|
71 Lisp_Object Qfc_patternp;
|
|
72 /* Lisp_Object Qfc_result_match; */ /* FcResultMatch */
|
|
73 Lisp_Object Qfc_result_type_mismatch; /* FcResultTypeMismatch */
|
|
74 Lisp_Object Qfc_result_no_match; /* FcResultNoMatch */
|
|
75 Lisp_Object Qfc_result_no_id; /* FcResultNoId */
|
|
76 Lisp_Object Qfc_internal_error;
|
|
77 Lisp_Object Vxlfd_font_name_regexp; /* #### Really needed? */
|
3935
|
78 Fixnum xft_version;
|
|
79 Fixnum fc_version;
|
3354
|
80 Fixnum debug_xft; /* Set to 1 enables lots of obnoxious messages.
|
|
81 Setting it to 2 or 3 enables even more. */
|
3931
|
82 #ifdef FONTCONFIG_EXPOSE_CONFIG
|
|
83 Lisp_Object Qfc_configp;
|
|
84 static Lisp_Object Vfc_config_weak_list;
|
|
85 #endif
|
3354
|
86
|
|
87 /****************************************************************
|
|
88 * FcPattern objects *
|
|
89 ****************************************************************/
|
|
90
|
|
91 static void
|
|
92 finalize_fc_pattern (void *header, int UNUSED (for_disksave))
|
|
93 {
|
|
94 struct fc_pattern *p = (struct fc_pattern *) header;
|
|
95 if (p->fcpatPtr)
|
|
96 {
|
|
97 FcPatternDestroy (p->fcpatPtr);
|
|
98 p->fcpatPtr = 0;
|
|
99 }
|
|
100 }
|
|
101
|
3906
|
102 static void
|
|
103 print_fc_pattern (Lisp_Object obj, Lisp_Object printcharfun,
|
|
104 int UNUSED(escapeflag))
|
|
105 {
|
|
106 struct fc_pattern *c = XFCPATTERN (obj);
|
|
107 if (print_readably)
|
|
108 printing_unreadable_object ("#<fc-pattern 0x%x>", c->header.uid);
|
|
109 write_fmt_string (printcharfun, "#<fc-pattern 0x%x>", c->header.uid);
|
|
110 }
|
|
111
|
|
112 /* #### We really need an equal method and a hash method (required if you
|
|
113 have an equal method). For the equal method, we can probably use one
|
|
114 or both of
|
|
115
|
|
116 -- Function: FcBool FcPatternEqual (const FcPattern *pa, const
|
|
117 FcPattern *pb);
|
|
118 Returns whether PA and PB are exactly alike.
|
|
119
|
|
120 -- Function: FcBool FcPatternEqualSubset (const FcPattern *pa, const
|
|
121 FcPattern *pb, const FcObjectSet *os)
|
|
122 Returns whether PA and PB have exactly the same values for all of
|
|
123 the objects in OS.
|
|
124
|
|
125 For the hash, we'll have to extract some subset of attributes.
|
|
126
|
|
127 #### Crap. It's altogether unobvious what we need. x_color_instance
|
|
128 does have a hash method, but fonts are apparently special. I get the
|
|
129 feeling that for this to work properly we're going to need to switch
|
|
130 to fontconfig-based font specifications (although we can allow the
|
|
131 platform syntaxes, the underlying specification object will need to
|
|
132 conform to the fontconfig API, or more precisely the font-mgr API).
|
|
133
|
|
134 I think the whole `font-truename' interface needs to be dropped. */
|
|
135
|
3354
|
136 static const struct memory_description fcpattern_description [] = {
|
|
137 /* #### nothing here, is this right?? */
|
|
138 { XD_END }
|
|
139 };
|
|
140
|
3906
|
141 DEFINE_LRECORD_IMPLEMENTATION("fc-pattern", fc_pattern, 0,
|
|
142 0, print_fc_pattern, finalize_fc_pattern,
|
|
143 0, 0, fcpattern_description,
|
3354
|
144 struct fc_pattern);
|
|
145
|
|
146 /*
|
|
147 * Helper Functions
|
|
148 */
|
|
149 static Lisp_Object make_xlfd_font_regexp (void);
|
|
150 static void string_list_to_fcobjectset (Lisp_Object list, FcObjectSet *os);
|
|
151
|
|
152 /*
|
|
153 extract the C representation of the Lisp string STR and convert it
|
|
154 to the encoding used by the Fontconfig API for property and font
|
|
155 names. I suppose that Qnative is the right encoding, the manual
|
|
156 doesn't say much about this topic. This functions assumes that STR
|
|
157 is a Lisp string.
|
|
158 */
|
|
159 #define extract_fcapi_string(str) \
|
3469
|
160 (NEW_LISP_STRING_TO_EXTERNAL ((str), Qfc_font_name_encoding))
|
3354
|
161
|
3906
|
162 #define build_fcapi_string(str) \
|
|
163 (build_ext_string ((Extbyte *) (str), Qfc_font_name_encoding))
|
|
164
|
3360
|
165 /* #### This homebrew lashup should be replaced with FcConstants.
|
|
166
|
|
167 fontconfig assumes that objects (property names) are statically allocated,
|
3354
|
168 and you will get bizarre results if you pass Lisp string data or strings
|
|
169 allocated on the stack as objects. fontconfig _does_ copy values, so we
|
|
170 (I hope) don't have to worry about that member.
|
|
171
|
|
172 Probably these functions don't get called so often that the memory leak
|
|
173 due to strdup'ing every time we add a property would matter, but XEmacs
|
|
174 _is_ a long-running process. So we hash them.
|
|
175
|
|
176 I suspect that using symbol names or even keywords does not provide
|
|
177 assurance that the string won't move in memory. So we hash them
|
3360
|
178 ourselves; hash.c hashtables do not interpret the value pointers.
|
|
179
|
|
180 This array should be FcChar8**, but GCC 4.x bitches about signedness. */
|
|
181 static Extbyte *fc_standard_properties[] = {
|
|
182 /* treated specially, ordered first */
|
|
183 "family", "size",
|
|
184 /* remaining are alphabetized by group */
|
|
185 /* standard properties in fontconfig and Xft v.2 */
|
|
186 "antialias", "aspect", "autohint", "charset", "dpi", "file",
|
3354
|
187 "foundry", "ftface", "globaladvance", "hinting", "index", "lang",
|
|
188 "minspace", "outline", "pixelsize", "rasterizer", "rgba", "scalable",
|
3360
|
189 "scale", "slant", "spacing", "style", "verticallayout", "weight",
|
|
190 /* common in modern fonts */
|
|
191 "fontformat", "fontversion",
|
3354
|
192 /* obsolete after Xft v. 1 */
|
|
193 "charwidth", "charheight", "core", "encoding", "render"
|
|
194 };
|
|
195
|
|
196 static struct hash_table *fc_property_name_hash_table;
|
|
197
|
|
198 /* #### Maybe fc_intern should be exposed to LISP? The idea is that
|
|
199 fc-pattern-add could warn or error if the property isn't interned. */
|
|
200
|
3469
|
201 static const Extbyte *
|
3354
|
202 fc_intern (Lisp_Object property)
|
|
203 {
|
|
204 const void *dummy;
|
3469
|
205 const Extbyte *prop = extract_fcapi_string (property);
|
3354
|
206 const void *val = gethash (prop, fc_property_name_hash_table, &dummy);
|
|
207
|
|
208 /* extract_fcapi_string returns something alloca'd
|
|
209 so we can just drop the old value of prop on the floor */
|
|
210 if (val)
|
3469
|
211 prop = (const Extbyte *) val;
|
3354
|
212 else
|
|
213 {
|
3469
|
214 prop = (const Extbyte *) FcStrCopy ((FcChar8 *) prop);
|
3354
|
215 puthash (prop, NULL, fc_property_name_hash_table);
|
|
216 }
|
|
217 return prop;
|
|
218 }
|
|
219
|
|
220 DEFUN("fc-pattern-p", Ffc_pattern_p, 1, 1, 0, /*
|
|
221 Returns t if OBJECT is of type fc-pattern, nil otherwise.
|
|
222 */
|
|
223 (object))
|
|
224 {
|
|
225 return FCPATTERNP(object) ? Qt : Qnil;
|
|
226 }
|
|
227
|
|
228 DEFUN("fc-pattern-create", Ffc_pattern_create, 0, 0, 0, /*
|
|
229 Return a new, empty fc-pattern object.
|
|
230 */
|
|
231 ())
|
|
232 {
|
|
233 fc_pattern *fcpat =
|
|
234 ALLOC_LCRECORD_TYPE (struct fc_pattern, &lrecord_fc_pattern);
|
|
235
|
|
236 fcpat->fcpatPtr = FcPatternCreate();
|
|
237 return wrap_fcpattern(fcpat);
|
|
238 }
|
|
239
|
|
240 DEFUN("fc-name-parse", Ffc_name_parse, 1, 1, 0, /*
|
|
241 Parse an Fc font name and return its representation as a fc pattern object.
|
|
242 */
|
|
243 (name))
|
|
244 {
|
|
245 struct fc_pattern *fcpat =
|
|
246 ALLOC_LCRECORD_TYPE (struct fc_pattern, &lrecord_fc_pattern);
|
|
247
|
3906
|
248 CHECK_STRING(name);
|
3354
|
249
|
3469
|
250 fcpat->fcpatPtr = FcNameParse ((FcChar8 *) extract_fcapi_string (name));
|
3354
|
251 return wrap_fcpattern(fcpat);
|
|
252 }
|
|
253
|
|
254 /* #### Ga-a-ack! Xft's similar function is actually a different API.
|
|
255 We provide both. */
|
|
256 DEFUN("fc-name-unparse", Ffc_name_unparse, 1, 1, 0, /*
|
|
257 Unparse an fc pattern object to a string.
|
|
258 */
|
|
259 (pattern))
|
|
260 {
|
|
261 CHECK_FCPATTERN(pattern);
|
3906
|
262 return build_fcapi_string (FcNameUnparse (XFCPATTERN_PTR (pattern)));
|
3354
|
263 }
|
|
264
|
|
265 DEFUN("fc-pattern-duplicate", Ffc_pattern_duplicate, 1, 1, 0, /*
|
|
266 Make a copy of the fc pattern object PATTERN and return it.
|
|
267 */
|
|
268 (pattern))
|
|
269 {
|
|
270 struct fc_pattern *copy = NULL;
|
|
271 CHECK_FCPATTERN(pattern);
|
|
272
|
|
273 copy = ALLOC_LCRECORD_TYPE (struct fc_pattern, &lrecord_fc_pattern);
|
|
274 copy->fcpatPtr = FcPatternDuplicate(XFCPATTERN_PTR(pattern));
|
|
275 return wrap_fcpattern(copy);
|
|
276 }
|
|
277
|
|
278 DEFUN("fc-pattern-add", Ffc_pattern_add, 3, 3, 0, /*
|
|
279 Add attributes to the pattern object PATTERN. PROPERTY is a string naming
|
|
280 the attribute to add, VALUE the value for this attribute.
|
|
281
|
|
282 VALUE may be a string, integer, float, or symbol, in which case the value
|
|
283 will be added as an FcChar8[], int, double, or FcBool respectively.
|
|
284 */
|
|
285 (pattern, property, value))
|
|
286 {
|
|
287 Bool res = 0;
|
3469
|
288 const Extbyte *obj;
|
3354
|
289 FcPattern *fcpat;
|
|
290
|
|
291 CHECK_FCPATTERN(pattern);
|
|
292 CHECK_STRING(property);
|
|
293
|
|
294 obj = fc_intern (property);
|
|
295 fcpat = XFCPATTERN_PTR (pattern);
|
|
296
|
|
297 if (STRINGP(value))
|
|
298 {
|
|
299 FcChar8 *str = (FcChar8 *) extract_fcapi_string (value);
|
|
300 res = FcPatternAddString (fcpat, obj, str);
|
|
301 }
|
|
302 else if (INTP(value))
|
|
303 {
|
|
304 res = FcPatternAddInteger (fcpat, obj, XINT(value));
|
|
305 }
|
|
306 else if (FLOATP(value))
|
|
307 {
|
|
308 res = FcPatternAddDouble (fcpat, obj, (double) XFLOAT_DATA(value));
|
|
309 }
|
|
310 else if (SYMBOLP(value))
|
|
311 {
|
|
312 res = FcPatternAddBool (fcpat, obj, !NILP(value));
|
|
313 }
|
|
314 /* else ... maybe we should wta here? */
|
|
315
|
|
316 return res ? Qt : Qnil;
|
|
317 }
|
|
318
|
|
319 DEFUN("fc-pattern-del", Ffc_pattern_del, 2, 2, 0, /*
|
|
320 Remove attribute PROPERTY from fc pattern object OBJECT.
|
|
321 */
|
|
322 (pattern, property))
|
|
323 {
|
|
324 Bool res;
|
|
325
|
|
326 CHECK_FCPATTERN(pattern);
|
|
327 CHECK_STRING(property);
|
|
328
|
3469
|
329 res = FcPatternDel(XFCPATTERN_PTR(pattern), extract_fcapi_string (property));
|
3354
|
330 return res ? Qt : Qnil;
|
|
331 }
|
|
332
|
|
333 /* Generic interface to FcPatternGet()
|
|
334 * Don't support the losing symbol-for-property interface.
|
|
335 */
|
|
336 DEFUN("fc-pattern-get", Ffc_pattern_get, 2, 4, 0, /*
|
|
337 From PATTERN, extract PROPERTY for the ID'th member, of type TYPE.
|
|
338
|
|
339 PATTERN is an Xft (fontconfig) pattern object.
|
|
340 PROPERTY is a string naming an fontconfig font property.
|
|
341 Optional ID is a nonnegative integer indexing the list of values for PROPERTY
|
|
342 stored in PATTERN, defaulting to 0 (the first value).
|
|
343 Optional TYPE is a symbol, one of 'string, 'boolean, 'integer, 'float,
|
|
344 'double, 'matrix, 'charset, or 'void, corresponding to the FcValue types.
|
|
345 ('float is an alias for 'double).
|
|
346
|
|
347 The Lisp types returned will conform to TYPE:
|
|
348 string string
|
|
349 boolean `t' or `nil'
|
|
350 integer integer
|
|
351 double (float) float
|
|
352 matrix not implemented
|
|
353 charset not implemented
|
|
354 void not implemented
|
|
355
|
|
356 Symbols with names of the form "fc-result-DESCRIPTION" are returned when
|
|
357 the desired value is not available. These are
|
|
358
|
|
359 fc-result-type-mismatch the value found has an unexpected type
|
|
360 fc-result-no-match there is no such attribute
|
|
361 fc-result-no-id there is no value for the requested ID
|
|
362
|
|
363 The types of the following standard properties are predefined by fontconfig.
|
|
364 The symbol 'fc-result-type-mismatch will be returned if the object exists but
|
|
365 TYPE does not match the predefined type. It is best not to specify a type
|
|
366 for predefined properties, as a mistake here ensures error returns on the
|
|
367 correct type.
|
|
368
|
|
369 Each standard property has a convenience accessor defined in fontconfig.el,
|
|
370 named in the form "fc-pattern-get-PROPERTY". The convenience functions are
|
|
371 preferred to `fc-pattern-get' since a typo in the string naming a property
|
|
372 will result in a silent null return, while a typo in a function name will
|
|
373 usually result in a compiler or runtime \"not fboundp\" error. You may use
|
|
374 `defsubst' to define convenience functions for non-standard properties.
|
|
375
|
|
376 family String Font family name
|
|
377 style String Font style. Overrides weight and slant
|
|
378 slant Int Italic, oblique or roman
|
|
379 weight Int Light, medium, demibold, bold or black
|
|
380 size Double Point size
|
|
381 aspect Double Stretches glyphs horizontally before hinting
|
|
382 pixelsize Double Pixel size
|
|
383 spacing Int Proportional, monospace or charcell
|
|
384 foundry String Font foundry name
|
|
385 antialias Bool Whether glyphs can be antialiased
|
|
386 hinting Bool Whether the rasterizer should use hinting
|
|
387 verticallayout Bool Use vertical layout
|
|
388 autohint Bool Use autohinter instead of normal hinter
|
|
389 globaladvance Bool Use font global advance data
|
|
390 file String The filename holding the font
|
|
391 index Int The index of the font within the file
|
|
392 ftface FT_Face Use the specified FreeType face object
|
|
393 rasterizer String Which rasterizer is in use
|
|
394 outline Bool Whether the glyphs are outlines
|
|
395 scalable Bool Whether glyphs can be scaled
|
|
396 scale Double Scale factor for point->pixel conversions
|
|
397 dpi Double Target dots per inch
|
|
398 rgba Int unknown, rgb, bgr, vrgb, vbgr, none - subpixel geometry
|
|
399 minspace Bool Eliminate leading from line spacing
|
|
400 charset CharSet Unicode chars encoded by the font
|
|
401 lang String List of RFC-3066-style languages this font supports
|
|
402
|
|
403 The FT_Face, Matrix, CharSet types are unimplemented, so the corresponding
|
|
404 properties are not accessible from Lisp at this time. If the value of a
|
|
405 property returned has type FT_Face, FcCharSet, or FcMatrix,
|
|
406 `fc-result-type-mismatch' is returned.
|
|
407
|
|
408 The following properties which were standard in Xft v.1 are obsolete in
|
|
409 Xft v.2: encoding, charwidth, charheight, core, and render. */
|
|
410 (pattern, property, id, type))
|
|
411 {
|
3469
|
412 Extbyte *fc_property;
|
3354
|
413 FcResult fc_result;
|
|
414 FcValue fc_value;
|
|
415
|
|
416 /*
|
|
417 process arguments
|
|
418 */
|
|
419 CHECK_FCPATTERN (pattern);
|
|
420
|
|
421 #if 0
|
|
422 /* Don't support the losing symbol-for-property interface. */
|
|
423 property = SYMBOLP (property) ? symbol_name (XSYMBOL (property)) : property;
|
|
424 #endif
|
|
425 if (STRINGP (property))
|
|
426 {
|
3469
|
427 fc_property = extract_fcapi_string (property);
|
3354
|
428 }
|
|
429 else
|
|
430 {
|
|
431 /* if we allow symbols, this would need to be
|
|
432 list3 (Qlambda, list1 (Qobject),
|
|
433 list3 (Qor, list2 (Qstringp, Qobject),
|
|
434 list2 (Qsymbolp, Qobject)))
|
|
435 or something like that? */
|
|
436 dead_wrong_type_argument (Qstringp, property);
|
|
437 }
|
|
438
|
|
439 if (!NILP (id)) CHECK_NATNUM (id);
|
|
440 if (!NILP (type)) CHECK_SYMBOL (type);
|
|
441
|
|
442 /* get property */
|
|
443 fc_result = FcPatternGet (XFCPATTERN_PTR (pattern),
|
|
444 fc_property,
|
|
445 NILP (id) ? 0 : XINT(id),
|
|
446 &fc_value);
|
|
447
|
|
448 switch (fc_result)
|
|
449 {
|
|
450 case FcResultMatch:
|
|
451 /* wrap it and return */
|
|
452 switch (fc_value.type)
|
|
453 {
|
|
454 case FcTypeInteger:
|
|
455 return ((!NILP (type) && !EQ (type, Qinteger))
|
|
456 ? Qfc_result_type_mismatch : make_int (fc_value.u.i));
|
|
457 case FcTypeDouble:
|
|
458 return ((!NILP (type) && !EQ (type, intern ("double"))
|
|
459 && !EQ (type, Qfloat))
|
|
460 ? Qfc_result_type_mismatch : make_float (fc_value.u.d));
|
|
461 case FcTypeString:
|
|
462 return ((!NILP (type) && !EQ (type, Qstring))
|
|
463 ? Qfc_result_type_mismatch
|
3906
|
464 : build_fcapi_string (fc_value.u.s));
|
3354
|
465 case FcTypeBool:
|
|
466 return ((!NILP (type) && !EQ (type, Qboolean))
|
|
467 ? Qfc_result_type_mismatch : fc_value.u.b ? Qt : Qnil);
|
|
468 case FcTypeMatrix:
|
|
469 return Qfc_result_type_mismatch;
|
|
470 /* #### unimplemented
|
|
471 return ((!NILP (type) && !EQ (type, intern ("matrix")))
|
|
472 ? Qfc_result_type_mismatch : make_int (fc_value.u.m));
|
|
473 */
|
|
474 case FcTypeCharSet:
|
|
475 return Qfc_result_type_mismatch;
|
|
476 /* #### unimplemented
|
|
477 return ((!NILP (type) && !EQ (type, intern ("charset")))
|
|
478 ? Qfc_result_type_mismatch : make_int (fc_value.u.c));
|
|
479 */
|
|
480 }
|
|
481 case FcResultTypeMismatch:
|
|
482 return Qfc_result_type_mismatch;
|
|
483 case FcResultNoMatch:
|
|
484 return Qfc_result_no_match;
|
|
485 case FcResultNoId:
|
|
486 return Qfc_result_no_id;
|
|
487 default:
|
|
488 return Qfc_internal_error;
|
|
489 }
|
|
490 }
|
|
491
|
|
492 DEFUN("fc-font-match", Ffc_font_match, 2, 2, 0, /*
|
|
493 Return the font on DEVICE that most closely matches PATTERN.
|
|
494
|
|
495 DEVICE is an X11 device.
|
|
496 PATTERN is a fontconfig pattern object.
|
|
497 Returns a fontconfig pattern object representing the closest match to the
|
|
498 given pattern, or an error code. Possible error codes are
|
|
499 `fc-result-no-match' and `fc-result-no-id'. */
|
|
500 (device, pattern))
|
|
501 {
|
|
502 FcResult res;
|
3906
|
503 struct fc_pattern *res_fcpat;
|
3354
|
504
|
3906
|
505 CHECK_FCPATTERN(pattern);
|
3354
|
506 if (NILP(device))
|
|
507 return Qnil;
|
|
508 CHECK_X_DEVICE(device);
|
|
509 if (!DEVICE_LIVE_P(XDEVICE(device)))
|
|
510 return Qnil;
|
|
511
|
3906
|
512 res_fcpat = ALLOC_LCRECORD_TYPE (struct fc_pattern, &lrecord_fc_pattern);
|
3360
|
513 {
|
|
514 FcPattern *p = XFCPATTERN_PTR(pattern);
|
|
515 FcConfig *fcc = FcConfigGetCurrent ();
|
|
516
|
|
517 FcConfigSubstitute (fcc, p, FcMatchPattern);
|
|
518 FcDefaultSubstitute (p);
|
|
519 res_fcpat->fcpatPtr = FcFontMatch (fcc, p, &res);
|
|
520 }
|
|
521
|
3354
|
522 if (res_fcpat->fcpatPtr == NULL)
|
|
523 switch (res) {
|
|
524 case FcResultNoMatch:
|
|
525 return Qfc_result_no_match;
|
|
526 case FcResultNoId:
|
|
527 return Qfc_result_no_id;
|
|
528 default:
|
|
529 return Qfc_internal_error;
|
|
530 }
|
|
531 else
|
|
532 return wrap_fcpattern(res_fcpat);
|
|
533 }
|
|
534
|
3931
|
535 enum DestroyFontsetP { DestroyNo = 0, DestroyYes = 1 };
|
|
536
|
3354
|
537 static Lisp_Object
|
3931
|
538 fontset_to_list (FcFontSet *fontset, enum DestroyFontsetP destroyp)
|
3354
|
539 {
|
|
540 int idx;
|
|
541 Lisp_Object fontlist = Qnil;
|
|
542 fc_pattern *fcpat;
|
|
543
|
|
544 /* #### improve this error message */
|
|
545 if (!fontset)
|
|
546 Fsignal (Qinvalid_state,
|
|
547 list1 (build_string ("failed to create FcFontSet")));
|
|
548 for (idx = 0; idx < fontset->nfont; ++idx)
|
|
549 {
|
|
550 fcpat =
|
|
551 ALLOC_LCRECORD_TYPE (struct fc_pattern, &lrecord_fc_pattern);
|
|
552 fcpat->fcpatPtr = FcPatternDuplicate (fontset->fonts[idx]);
|
|
553 fontlist = Fcons (wrap_fcpattern(fcpat), fontlist);
|
|
554 }
|
3931
|
555 if (destroyp)
|
|
556 FcFontSetDestroy (fontset);
|
3354
|
557 return fontlist;
|
|
558 }
|
|
559
|
|
560 /* #### fix this name to correspond to Ben's new nomenclature */
|
|
561 DEFUN("fc-list-fonts-pattern-objects", Ffc_list_fonts_pattern_objects,
|
|
562 3, 3, 0, /*
|
|
563 Return a list of fonts on DEVICE that match PATTERN for PROPERTIES.
|
|
564 Each font is represented by a fontconfig pattern object.
|
|
565
|
|
566 DEVICE is an X11 device.
|
|
567 PATTERN is a fontconfig pattern to be matched.
|
|
568 PROPERTIES is a list of property names (strings) that should match.
|
|
569
|
|
570 #### DEVICE is unused, ignored, and may be removed if it's not needed to
|
|
571 match other font-listing APIs. */
|
|
572 (UNUSED (device), pattern, properties))
|
|
573 {
|
|
574 FcObjectSet *os;
|
|
575 FcFontSet *fontset;
|
|
576
|
|
577 CHECK_FCPATTERN (pattern);
|
|
578 CHECK_LIST (properties);
|
|
579
|
|
580 os = FcObjectSetCreate ();
|
|
581 string_list_to_fcobjectset (properties, os);
|
|
582 /* #### why don't we need to do the "usual substitutions"? */
|
|
583 fontset = FcFontList (NULL, XFCPATTERN_PTR (pattern), os);
|
|
584 FcObjectSetDestroy (os);
|
|
585
|
3931
|
586 return fontset_to_list (fontset, DestroyYes);
|
3354
|
587
|
|
588 }
|
|
589
|
|
590 /* #### maybe this can/should be folded into fc-list-fonts-pattern-objects? */
|
|
591 DEFUN("fc-font-sort", Ffc_font_sort, 2, 4, 0, /*
|
|
592 Return a list of all fonts sorted by proximity to PATTERN.
|
|
593 Each font is represented by a fontconfig pattern object.
|
|
594
|
|
595 DEVICE is an X11 device.
|
|
596 PATTERN is a fontconfig pattern to be matched.
|
|
597 Optional argument TRIM, if non-nil, means to trim trailing fonts that do not
|
|
598 contribute new characters to the union repertoire.
|
|
599
|
|
600 #### Optional argument NOSUB, if non-nil, suppresses some of the usual
|
|
601 property substitutions. DON'T USE THIS in production code, it is intended
|
|
602 for exploring behavior of fontconfig and will be removed when this code is
|
|
603 stable.
|
|
604
|
|
605 #### DEVICE is unused, ignored, and may be removed if it's not needed to
|
|
606 match other font-listing APIs. */
|
|
607 (UNUSED (device), pattern, trim, nosub))
|
|
608 {
|
|
609 CHECK_FCPATTERN (pattern);
|
|
610
|
|
611 {
|
|
612 FcConfig *fcc = FcConfigGetCurrent();
|
|
613 FcFontSet *fontset;
|
|
614 FcPattern *p = XFCPATTERN_PTR (pattern);
|
|
615 FcResult fcresult;
|
|
616
|
|
617 if (NILP(nosub)) /* #### temporary debug hack */
|
|
618 FcDefaultSubstitute (p);
|
|
619 FcConfigSubstitute (fcc, p, FcMatchPattern);
|
|
620 fontset = FcFontSort (fcc, p, !NILP(trim), NULL, &fcresult);
|
|
621
|
3931
|
622 return fontset_to_list (fontset, DestroyYes);
|
|
623 }
|
|
624 }
|
|
625
|
|
626 #ifdef FONTCONFIG_EXPOSE_CONFIG
|
|
627
|
|
628 /* Configuration routines --- for debugging
|
|
629 Don't depend on these routines being available in the future!
|
|
630
|
|
631 3.2.10 Initialization
|
|
632 ---------------------
|
|
633
|
|
634 An FcConfig object holds the internal representation of a configuration.
|
|
635 There is a default configuration which applications may use by passing
|
|
636 0 to any function using the data within an FcConfig.
|
|
637 */
|
|
638
|
|
639 static void
|
|
640 finalize_fc_config (void *header, int UNUSED (for_disksave))
|
|
641 {
|
|
642 struct fc_config *p = (struct fc_config *) header;
|
|
643 if (p->fccfgPtr && p->fccfgPtr != FcConfigGetCurrent())
|
|
644 {
|
|
645 /* If we get here, all of *our* references are garbage (see comment on
|
|
646 fc_config_create_using() for why), and the only reference that
|
|
647 fontconfig keeps is the current FcConfig. */
|
|
648 FcConfigDestroy (p->fccfgPtr);
|
|
649 }
|
|
650 p->fccfgPtr = 0;
|
|
651 }
|
|
652
|
|
653 static void
|
|
654 print_fc_config (Lisp_Object obj, Lisp_Object printcharfun,
|
|
655 int UNUSED(escapeflag))
|
|
656 {
|
|
657 struct fc_config *c = XFCCONFIG (obj);
|
|
658 if (print_readably)
|
|
659 printing_unreadable_object ("#<fc-config 0x%x>", c->header.uid);
|
|
660 write_fmt_string (printcharfun, "#<fc-config 0x%x>", c->header.uid);
|
|
661 }
|
|
662
|
|
663 static const struct memory_description fcconfig_description [] = {
|
|
664 /* #### nothing here, is this right?? */
|
|
665 { XD_END }
|
|
666 };
|
|
667
|
|
668 DEFINE_LRECORD_IMPLEMENTATION("fc-config", fc_config, 0,
|
|
669 0, print_fc_config, finalize_fc_config, 0, 0,
|
|
670 fcconfig_description,
|
|
671 struct fc_config);
|
|
672
|
|
673 /* We obviously need to be careful about garbage collecting the current
|
|
674 FcConfig. I infer from the documentation of FcConfigDestroy that that
|
|
675 is the only reference maintained by fontconfig.
|
|
676 So we keep track of our own references on a weak list, and only cons a
|
|
677 new object if we don't already have a reference to it there. */
|
|
678
|
|
679 static Lisp_Object
|
|
680 fc_config_create_using (FcConfig * (*create_function) ())
|
|
681 {
|
|
682 FcConfig *fc = (*create_function) ();
|
|
683 Lisp_Object configs = XWEAK_LIST_LIST (Vfc_config_weak_list);
|
|
684
|
|
685 /* Linear search: fc_configs are not going to multiply like conses. */
|
|
686 {
|
|
687 LIST_LOOP_2 (cfg, configs)
|
|
688 if (fc == XFCCONFIG_PTR (cfg))
|
|
689 return cfg;
|
|
690 }
|
|
691
|
|
692 {
|
|
693 fc_config *fccfg =
|
|
694 ALLOC_LCRECORD_TYPE (struct fc_config, &lrecord_fc_config);
|
|
695 fccfg->fccfgPtr = fc;
|
|
696 configs = Fcons (wrap_fcconfig (fccfg), configs);
|
|
697 XWEAK_LIST_LIST (Vfc_config_weak_list) = configs;
|
|
698 return wrap_fcconfig (fccfg);
|
3354
|
699 }
|
|
700 }
|
|
701
|
3931
|
702 DEFUN("fc-config-p", Ffc_config_p, 1, 1, 0, /*
|
|
703 Returns t if OBJECT is of type fc-config, nil otherwise.
|
|
704 */
|
|
705 (object))
|
|
706 {
|
|
707 return FCCONFIGP (object) ? Qt : Qnil;
|
|
708 }
|
|
709
|
|
710 DEFUN("fc-config-create", Ffc_config_create, 0, 0, 0, /*
|
|
711 -- Function: FcConfig *FcConfigCreate (void)
|
|
712 Creates an empty configuration. */
|
|
713 ())
|
|
714 {
|
|
715 return fc_config_create_using (&FcConfigCreate);
|
|
716 }
|
|
717
|
|
718 #if 0
|
|
719 /* I'm sorry, but we just don't do this in Lisp, OK?
|
|
720 Don't even think about implementing this. */
|
|
721 DEFUN("fc-config-destroy", Ffc_config_destroy, 1, 1, 0, /*
|
|
722 -- Function: void FcConfigDestroy (FcConfig *config)
|
|
723 Destroys a configuration and any data associated with it. Note
|
|
724 that calling this function with the return value from
|
|
725 FcConfigGetCurrent will place the library in an indeterminate
|
|
726 state. */
|
|
727 (config))
|
|
728 {
|
|
729 signal_error (Qunimplemented, "No user-servicable parts!",
|
|
730 intern ("fc-config-destroy");
|
|
731 }
|
|
732 #endif
|
|
733
|
|
734 DEFUN("fc-config-get-current", Ffc_config_get_current, 0, 0, 0, /*
|
|
735 -- Function: FcConfig *FcConfigGetCurrent (void)
|
|
736 Returns the current default configuration. */
|
|
737 ())
|
|
738 {
|
|
739 return fc_config_create_using (&FcConfigGetCurrent);
|
|
740 }
|
|
741
|
|
742 DEFUN("fc-config-up-to-date", Ffc_config_up_to_date, 1, 1, 0, /*
|
|
743 -- Function: FcBool FcConfigUptoDate (FcConfig *config)
|
|
744 Checks all of the files related to 'config' and returns whether the
|
|
745 in-memory version is in sync with the disk version. */
|
|
746 (config))
|
|
747 {
|
|
748 CHECK_FCCONFIG (config);
|
|
749 return FcConfigUptoDate (XFCCONFIG_PTR (config)) == FcFalse ? Qnil : Qt;
|
|
750 }
|
|
751
|
|
752 DEFUN("fc-config-build-fonts", Ffc_config_build_fonts, 1, 1, 0, /*
|
|
753 -- Function: FcBool FcConfigBuildFonts (FcConfig *config)
|
|
754 Builds the set of available fonts for the given configuration.
|
|
755 Note that any changes to the configuration after this call have
|
|
756 indeterminate effects. Returns FcFalse if this operation runs out
|
|
757 of memory.
|
|
758 XEmacs: signal out-of-memory, or return nil on success. */
|
|
759 (config))
|
|
760 {
|
|
761 CHECK_FCCONFIG (config);
|
|
762 if (FcConfigBuildFonts (XFCCONFIG_PTR (config)) == FcFalse)
|
|
763 out_of_memory ("FcConfigBuildFonts failed", config);
|
|
764 return Qnil;
|
|
765 }
|
|
766
|
|
767 /* Calls its argument on `config', which must be defined by the caller. */
|
|
768
|
|
769 #define FCSTRLIST_TO_LISP_USING(source) do { \
|
|
770 FcChar8 *thing; \
|
|
771 FcStrList *thing_list; \
|
|
772 Lisp_Object value = Qnil; \
|
|
773 CHECK_FCCONFIG (config); \
|
|
774 thing_list = source (XFCCONFIG_PTR(config)); \
|
|
775 /* Yes, we need to do this check -- sheesh, Keith! */ \
|
|
776 if (!thing_list) \
|
|
777 return Qnil; \
|
|
778 while ((thing = FcStrListNext (thing_list))) \
|
|
779 value = Fcons (build_fcapi_string (thing), value); \
|
|
780 FcStrListDone (thing_list); \
|
|
781 return value; \
|
|
782 } while (0)
|
|
783
|
|
784 DEFUN("fc-config-get-config-dirs", Ffc_config_get_config_dirs, 1, 1, 0, /*
|
|
785 -- Function: FcStrList *FcConfigGetConfigDirs (FcConfig *config)
|
|
786 Returns the list of font directories specified in the
|
|
787 configuration files for 'config'. Does not include any
|
|
788 subdirectories. */
|
|
789 (config))
|
|
790 {
|
|
791 FCSTRLIST_TO_LISP_USING (FcConfigGetConfigDirs);
|
|
792 }
|
|
793
|
|
794 DEFUN("fc-config-get-font-dirs", Ffc_config_get_font_dirs, 1, 1, 0, /*
|
|
795 -- Function: FcStrList *FcConfigGetFontDirs (FcConfig *config)
|
|
796 Returns the list of font directories in 'config'. This includes the
|
|
797 configured font directories along with any directories below those
|
|
798 in the filesystem. */
|
|
799 (config))
|
|
800 {
|
|
801 FCSTRLIST_TO_LISP_USING (FcConfigGetFontDirs);
|
|
802 }
|
|
803
|
|
804 DEFUN("fc-config-get-config-files", Ffc_config_get_config_files, 1, 1, 0, /*
|
|
805 -- Function: FcStrList *FcConfigGetConfigFiles (FcConfig *config)
|
|
806 Returns the list of known configuration files used to generate
|
|
807 'config'. Note that this will not include any configuration done
|
|
808 with FcConfigParse. */
|
|
809 (config))
|
|
810 {
|
|
811 FCSTRLIST_TO_LISP_USING (FcConfigGetConfigFiles);
|
|
812 }
|
|
813
|
|
814 #undef FCSTRLIST_TO_LISP_USING
|
|
815
|
|
816 DEFUN("fc-config-get-cache", Ffc_config_get_cache, 1, 1, 0, /*
|
|
817 -- Function: char *FcConfigGetCache (FcConfig *config)
|
|
818 Returns the name of the file used to store per-user font
|
|
819 information. */
|
|
820 (config))
|
|
821 {
|
|
822 CHECK_FCCONFIG (config);
|
|
823 /* Surely FcConfigGetCache just casts an FcChar8* to char*. */
|
|
824 return build_fcapi_string ((FcChar8 *) FcConfigGetCache (XFCCONFIG_PTR (config)));
|
|
825 }
|
|
826
|
|
827 DEFUN("fc-config-get-fonts", Ffc_config_get_fonts, 2, 2, 0, /*
|
|
828 -- Function: FcFontSet *FcConfigGetFonts (FcConfig *config, FcSetName set)
|
|
829 Returns one of the two sets of fonts from the configuration as
|
|
830 specified by 'set'.
|
|
831 `FcSetName'
|
|
832 Specifies one of the two sets of fonts available in a
|
|
833 configuration; FcSetSystem for those fonts specified in the
|
|
834 configuration and FcSetApplication which holds fonts provided by
|
|
835 the application. */
|
|
836 (config, set))
|
|
837 {
|
|
838 FcSetName name = FcSetSystem;
|
|
839 FcFontSet *fs = NULL;
|
|
840
|
|
841 CHECK_FCCONFIG (config);
|
|
842 CHECK_SYMBOL (set);
|
|
843
|
|
844 if (EQ (set, intern ("fc-set-system")))
|
|
845 name = FcSetSystem;
|
|
846 else if (EQ (set, intern ("fc-set-application")))
|
|
847 name = FcSetApplication;
|
|
848 else
|
|
849 wtaerror ("must be in (fc-set-system fc-set-application)", set);
|
|
850
|
|
851 fs = FcConfigGetFonts (XFCCONFIG_PTR (config), name);
|
|
852 return fs ? fontset_to_list (fs, DestroyNo) : Qnil;
|
|
853 }
|
|
854
|
|
855 DEFUN("fc-config-set-current", Ffc_config_set_current, 1, 1, 0, /*
|
|
856 -- Function: FcBool FcConfigSetCurrent (FcConfig *config)
|
|
857 Sets the current default configuration to 'config'. Implicitly
|
|
858 calls FcConfigBuildFonts if necessary, returning FcFalse if that
|
|
859 call fails.
|
|
860 XEmacs: signals out-of-memory if FcConfigBuildFonts fails, or args-out-of-range
|
|
861 if the resulting FcConfig has no fonts (which would crash XEmacs if installed).
|
|
862 */
|
|
863 (config))
|
|
864 {
|
|
865 CHECK_FCCONFIG (config);
|
|
866 /* *sigh* "Success" DOES NOT mean you have any fonts available. It is
|
|
867 easy to crash fontconfig, and XEmacs with it. Without the following
|
|
868 check, this will do it:
|
|
869 (progn
|
|
870 (fc-config-set-current (fc-config-create))
|
|
871 (set-face-font 'default "serif-12"))
|
|
872 */
|
|
873
|
|
874 if (FcConfigBuildFonts (XFCCONFIG_PTR (config)) == FcFalse)
|
|
875 out_of_memory ("FcConfigBuildFonts failed", config);
|
|
876 /* #### We'd like to avoid this consing, and FcConfigGetFonts sometimes
|
|
877 returns NULL, but it doesn't always. This will do for now .... */
|
|
878 if (NILP (Ffc_config_get_fonts (config, intern ("fc-set-system")))
|
|
879 && NILP (Ffc_config_get_fonts (config, intern ("fc-set-application"))))
|
|
880 signal_error (intern ("args-out-of-range"), "no fonts found", config);
|
|
881 /* Should never happen, but I don't trust Keith anymore .... */
|
|
882 if (FcConfigSetCurrent (XFCCONFIG_PTR (config)) == FcFalse)
|
|
883 out_of_memory ("FcConfigBuildFonts failed in set", config);
|
|
884 return Qnil;
|
|
885 }
|
|
886
|
|
887 DEFUN("fc-config-get-blanks", Ffc_config_get_blanks, 1, 1, 0, /*
|
|
888 -- Function: FcBlanks *FcConfigGetBlanks (FcConfig *config)
|
|
889 Returns the FcBlanks object associated with the given
|
|
890 configuration, if no blanks were present in the configuration,
|
|
891 this function will return 0.
|
|
892 XEmacs: should convert to a chartable.
|
|
893 #### Unimplemented. */
|
|
894 (config))
|
|
895 {
|
|
896 CHECK_FCCONFIG (config);
|
|
897 signal_error (Qunimplemented, "no method to convert FcBlanks object",
|
|
898 intern ("fc-config-get-blanks"));
|
|
899 }
|
|
900
|
|
901 /* The misspelling in the fontconfig function name accurately corresponds to
|
|
902 the version of fontconfig.h I had on 2007-04-13. -- sjt */
|
|
903 DEFUN("fc-config-get-rescan-interval", Ffc_config_get_rescan_interval, 1, 1, 0, /*
|
|
904 -- Function: int FcConfigGetRescanInverval (FcConfig *config)
|
|
905 Returns the interval between automatic checks of the configuration
|
|
906 (in seconds) specified in 'config'. The configuration is checked
|
|
907 during a call to FcFontList when this interval has passed since
|
|
908 the last check. */
|
|
909 (config))
|
|
910 {
|
|
911 CHECK_FCCONFIG (config);
|
|
912 return make_int (FcConfigGetRescanInverval (XFCCONFIG_PTR (config)));
|
|
913 }
|
|
914
|
|
915 /* The misspelling in the fontconfig function name accurately corresponds to
|
|
916 the version of fontconfig.h I had on 2007-04-13. -- sjt */
|
|
917 DEFUN("fc-config-set-rescan-interval", Ffc_config_set_rescan_interval, 2, 2, 0, /*
|
|
918 -- Function: FcBool FcConfigSetRescanInverval (FcConfig *config, int
|
|
919 rescanInterval)
|
|
920 Sets the rescan interval; returns FcFalse if an error occurred.
|
|
921 XEmacs: signal such error, or return nil on success. */
|
|
922 (config, rescan_interval))
|
|
923 {
|
|
924 CHECK_FCCONFIG (config);
|
|
925 CHECK_INT (rescan_interval);
|
|
926 if (FcConfigSetRescanInverval (XFCCONFIG_PTR (config),
|
|
927 XINT (rescan_interval)) == FcFalse)
|
|
928 signal_error (Qio_error, "FcConfigSetRescanInverval barfed",
|
|
929 intern ("fc-config-set-rescan-interval"));
|
|
930 return Qnil;
|
|
931 }
|
|
932
|
|
933 /* #### This might usefully be made interactive. */
|
|
934 DEFUN("fc-config-app-font-add-file", Ffc_config_app_font_add_file, 2, 2, 0, /*
|
|
935 -- Function: FcBool FcConfigAppFontAddFile (FcConfig *config, const
|
|
936 char *file)
|
|
937 Adds an application-specific font to the configuration. */
|
|
938 (config, file))
|
|
939 {
|
|
940 CHECK_FCCONFIG (config);
|
|
941 CHECK_STRING (file);
|
|
942 if (FcConfigAppFontAddFile
|
|
943 (XFCCONFIG_PTR (config),
|
|
944 /* #### FIXME! is this really Qnative? */
|
|
945 (FcChar8 *) NEW_LISP_STRING_TO_EXTERNAL ((file), Qnative)) == FcFalse)
|
|
946 return Qnil;
|
|
947 else
|
|
948 return Qt;
|
|
949 }
|
|
950
|
|
951 /* #### This might usefully be made interactive. */
|
|
952 DEFUN("fc-config-app-font-add-dir", Ffc_config_app_font_add_dir, 2, 2, 0, /*
|
|
953 -- Function: FcBool FcConfigAppFontAddDir (FcConfig *config, const
|
|
954 char *dir)
|
|
955 Scans the specified directory for fonts, adding each one found to
|
|
956 the application-specific set of fonts. */
|
|
957 (config, dir))
|
|
958 {
|
|
959 CHECK_FCCONFIG (config);
|
|
960 CHECK_STRING (dir);
|
|
961 if (FcConfigAppFontAddDir
|
|
962 (XFCCONFIG_PTR (config),
|
|
963 /* #### FIXME! is this really Qnative? */
|
|
964 (FcChar8 *) NEW_LISP_STRING_TO_EXTERNAL ((dir), Qnative)) == FcFalse)
|
|
965 return Qnil;
|
|
966 else
|
|
967 return Qt;
|
|
968 }
|
|
969
|
|
970 /* #### This might usefully be made interactive. */
|
|
971 DEFUN("fc-config-app-font-clear", Ffc_config_app_font_clear, 1, 1, 0, /*
|
|
972 -- Function: void FcConfigAppFontClear (FcConfig *config)
|
|
973 Clears the set of application-specific fonts. */
|
|
974 (config))
|
|
975 {
|
|
976 CHECK_FCCONFIG (config);
|
|
977 FcConfigAppFontClear (XFCCONFIG_PTR (config));
|
|
978 return Qnil;
|
|
979 }
|
|
980
|
|
981 /* These functions provide some control over how the default
|
|
982 configuration of the library is initialized. (This configuration is
|
|
983 normally implicitly initialized.) */
|
|
984
|
|
985 DEFUN("fc-config-filename", Ffc_config_filename, 1, 1, 0, /*
|
|
986 -- Function: char *FcConfigFilename (const char *name)
|
|
987 Given the specified external entity name, return the associated
|
|
988 filename. This provides applications a way to convert various
|
|
989 configuration file references into filename form.
|
|
990
|
|
991 A null or empty 'name' indicates that the default configuration
|
|
992 file should be used; which file this references can be overridden
|
|
993 with the FC_CONFIG_FILE environment variable. Next, if the name
|
|
994 starts with '~', it refers to a file in the current users home
|
|
995 directory. Otherwise if the name doesn't start with '/', it
|
|
996 refers to a file in the default configuration directory; the
|
|
997 built-in default directory can be overridden with the
|
|
998 FC_CONFIG_DIR environment variable. */
|
|
999 (name))
|
|
1000 {
|
|
1001 char *fcname = "";
|
|
1002
|
|
1003 if (!NILP (name))
|
|
1004 {
|
|
1005 CHECK_STRING (name);
|
|
1006 /* #### FIXME! is this really Qnative? */
|
|
1007 fcname = NEW_LISP_STRING_TO_EXTERNAL (name, Qnative);
|
|
1008 }
|
|
1009 return (build_fcapi_string (FcConfigFilename ((FcChar8 *) fcname)));
|
|
1010 }
|
|
1011
|
|
1012 DEFUN("fc-init-load-config", Ffc_init_load_config, 0, 0, 0, /*
|
|
1013 -- Function: FcConfig *FcInitLoadConfig (void)
|
|
1014 Loads the default configuration file and returns the resulting
|
|
1015 configuration. Does not load any font information. */
|
|
1016 ())
|
|
1017 {
|
|
1018 return fc_config_create_using (&FcInitLoadConfig);
|
|
1019 }
|
|
1020
|
|
1021 DEFUN("fc-init-load-config-and-fonts", Ffc_init_load_config_and_fonts, 0, 0, 0, /*
|
|
1022 -- Function: FcConfig *FcInitLoadConfigAndFonts (void)
|
|
1023 Loads the default configuration file and builds information about
|
|
1024 the available fonts. Returns the resulting configuration. */
|
|
1025 ())
|
|
1026 {
|
|
1027 return fc_config_create_using (&FcInitLoadConfigAndFonts);
|
|
1028 }
|
|
1029
|
|
1030 DEFUN("fc-init", Ffc_init, 0, 0, 0, /*
|
|
1031 -- Function: FcBool FcInit (void)
|
|
1032 Loads the default configuration file and the fonts referenced
|
|
1033 therein and sets the default configuration to that result.
|
|
1034 Returns whether this process succeeded or not. If the default
|
|
1035 configuration has already been loaded, this routine does nothing
|
|
1036 and returns FcTrue. */
|
|
1037 ())
|
|
1038 {
|
|
1039 return (FcInit () == FcTrue) ? Qt : Qnil;
|
|
1040 }
|
|
1041
|
|
1042 DEFUN("fc-get-version", Ffc_get_version, 0, 0, 0, /*
|
|
1043 -- Function: int FcGetVersion (void)
|
|
1044 Returns the version number of the library.
|
3935
|
1045 XEmacs: No, this should NOT return a pretty string.
|
3931
|
1046 (let ((i (fc-get-version)))
|
|
1047 (format "%d.%d.%d" (/ i 10000) (mod (/ i 100) 100) (mod i 100)))
|
3935
|
1048 gives the usual x.y.z format. This is the version of the .so. It can be
|
|
1049 checked against `fc-version', which is the version of fontconfig.h.
|
|
1050 It's probably not a disaster if `(> (fc-get-version) fc-version)'. */
|
3931
|
1051 ())
|
|
1052 {
|
|
1053 return make_int (FcGetVersion ());
|
|
1054 }
|
|
1055
|
|
1056 DEFUN("fc-init-reinitialize", Ffc_init_reinitialize, 0, 0, 0, /*
|
|
1057 -- Function: FcBool FcInitReinitialize (void)
|
|
1058 Forces the default configuration file to be reloaded and resets
|
|
1059 the default configuration. */
|
|
1060 ())
|
|
1061 {
|
|
1062 return (FcInitReinitialize () == FcTrue) ? Qt : Qnil;
|
|
1063 }
|
|
1064
|
|
1065 DEFUN("fc-init-bring-up-to-date", Ffc_init_bring_up_to_date, 0, 0, 0, /*
|
|
1066 -- Function: FcBool FcInitBringUptoDate (void)
|
|
1067 Checks the rescan interval in the default configuration, checking
|
|
1068 the configuration if the interval has passed and reloading the
|
|
1069 configuration when any changes are detected. */
|
|
1070 ())
|
|
1071 {
|
|
1072 return (FcInitBringUptoDate () == FcTrue) ? Qt : Qnil;
|
|
1073 }
|
|
1074
|
|
1075 #endif /* FONTCONFIG_EXPOSE_CONFIG */
|
|
1076
|
3354
|
1077 DEFUN("xlfd-font-name-p", Fxlfd_font_name_p, 1, 1, 0, /*
|
|
1078 Check whether the string FONTNAME is a XLFD font name. */
|
|
1079 (fontname))
|
|
1080 {
|
|
1081 CHECK_STRING(fontname);
|
|
1082 /* #### should bind `case-fold-search' here? */
|
|
1083 return Fstring_match(Vxlfd_font_name_regexp, fontname, Qnil, Qnil);
|
|
1084 }
|
|
1085
|
|
1086 /* FcPatternPrint: there is no point in having wrappers fc-pattern-print,
|
|
1087 Ffc_pattern_print since this function prints to stdout. */
|
|
1088
|
|
1089 /* Initialization of font-mgr */
|
|
1090
|
|
1091 #define XE_XLFD_SEPARATOR "-"
|
|
1092 /* XLFD specifies ISO 8859-1 encoding, but we can't handle non-ASCII
|
|
1093 in Mule when this function is called. So use HPC. */
|
|
1094 #if 0
|
|
1095 #define XE_XLFD_PREFIX "\\(\\+[\040-\176\240-\377]*\\)?-"
|
|
1096 #define XE_XLFD_OPT_TEXT "\\([\040-\044\046-\176\240-\377]*\\)"
|
|
1097 #define XE_XLFD_TEXT "\\([\040-\044\046-\176\240-\377]+\\)"
|
|
1098 #else
|
|
1099 #define XE_XLFD_PREFIX "\\(\\+[\040-\176]*\\)?-"
|
|
1100 #define XE_XLFD_OPT_TEXT "\\([^-]*\\)"
|
|
1101 #define XE_XLFD_TEXT "\\([^-]+\\)"
|
|
1102 #endif
|
|
1103
|
|
1104 #define XE_XLFD_SLANT "\\([0-9ior?*][iot]?\\)"
|
|
1105 #define XE_XLFD_SPACING "\\([cmp?*]\\)"
|
|
1106 /* Hyphen as minus conflicts with use as separator. */
|
|
1107 #define XE_XLFD_OPT_NEGATE "~?"
|
|
1108 #define XE_XLFD_NUMBER "\\([0-9?*]+\\)"
|
|
1109 #define XE_XLFD_PSIZE "\\([0-9?*]+\\|\\[[ 0-9+~.e?*]+\\]\\)"
|
|
1110
|
|
1111 /* Call this only from the init code
|
|
1112 #### This is really horrible, let's get rid of it, please. */
|
|
1113 static Lisp_Object
|
|
1114 make_xlfd_font_regexp (void)
|
|
1115 {
|
|
1116 struct gcpro gcpro1;
|
|
1117 unsigned i;
|
|
1118 Lisp_Object reg = Qnil;
|
|
1119 const Extbyte *re[] = /* #### This could just be catenated by
|
|
1120 cpp and passed to build_ext_string. */
|
|
1121 {
|
|
1122 /* Regular expression matching XLFDs as defined by XLFD v. 1.5.
|
|
1123 Matches must be case-insensitive.
|
|
1124 PSIZE is a pixel or point size, which may be a "matrix". The
|
|
1125 syntax of a matrix is not checked, just some lexical properties.
|
|
1126 AFAICT none of the TEXT fields except adstyle is optional.
|
|
1127
|
|
1128 NB. It should not be a problem if this matches "too much", since
|
|
1129 an "old" server will simply not be able to find a matching font. */
|
|
1130 "\\`",
|
|
1131 XE_XLFD_PREFIX, /* prefix */
|
|
1132 XE_XLFD_TEXT, /* foundry */
|
|
1133 XE_XLFD_SEPARATOR,
|
|
1134 XE_XLFD_TEXT, /* family */
|
|
1135 XE_XLFD_SEPARATOR,
|
|
1136 XE_XLFD_TEXT, /* weight */
|
|
1137 XE_XLFD_SEPARATOR,
|
|
1138 XE_XLFD_SLANT, /* slant */
|
|
1139 XE_XLFD_SEPARATOR,
|
|
1140 XE_XLFD_TEXT, /* swidth */
|
|
1141 XE_XLFD_SEPARATOR,
|
|
1142 XE_XLFD_OPT_TEXT, /* adstyle */
|
|
1143 XE_XLFD_SEPARATOR,
|
|
1144 XE_XLFD_PSIZE, /* pixelsize */
|
|
1145 XE_XLFD_SEPARATOR,
|
|
1146 XE_XLFD_PSIZE, /* pointsize */
|
|
1147 XE_XLFD_SEPARATOR,
|
|
1148 XE_XLFD_NUMBER, /* resx */
|
|
1149 XE_XLFD_SEPARATOR,
|
|
1150 XE_XLFD_NUMBER, /* resy */
|
|
1151 XE_XLFD_SEPARATOR,
|
|
1152 XE_XLFD_SPACING, /* spacing */
|
|
1153 XE_XLFD_SEPARATOR,
|
|
1154 XE_XLFD_OPT_NEGATE, /* avgwidth */
|
|
1155 XE_XLFD_NUMBER,
|
|
1156 XE_XLFD_SEPARATOR,
|
|
1157 XE_XLFD_TEXT, /* registry */
|
|
1158 XE_XLFD_SEPARATOR,
|
|
1159 XE_XLFD_TEXT, /* encoding */
|
|
1160 "\\'"
|
|
1161 };
|
|
1162
|
|
1163 GCPRO1 (reg);
|
|
1164 for (i = 0; i < sizeof(re)/sizeof(Extbyte *); i++)
|
|
1165 {
|
|
1166 /* #### Currently this is Host Portable Coding, not ISO 8859-1. */
|
|
1167 reg = concat2(reg, build_ext_string (re[i], Qx_font_name_encoding));
|
|
1168 }
|
|
1169
|
|
1170 RETURN_UNGCPRO (reg);
|
|
1171 }
|
|
1172 #undef XE_XLFD_SEPARATOR
|
|
1173 #undef XE_XLFD_PREFIX
|
|
1174 #undef XE_XLFD_OPT_TEXT
|
|
1175 #undef XE_XLFD_TEXT
|
|
1176 #undef XE_XLFD_OPT_SLANT
|
|
1177 #undef XE_XLFD_OPT_SPACING
|
|
1178 #undef XE_XLFD_OPT_NEGATE
|
|
1179 #undef XE_XLFD_NUMBER
|
|
1180 #undef XE_XLFD_PSIZE
|
|
1181
|
|
1182 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \
|
|
1183 ? ((unsigned long) (x)) : ((unsigned long) (y)))
|
|
1184
|
|
1185 static void
|
|
1186 string_list_to_fcobjectset (Lisp_Object list, FcObjectSet *os)
|
|
1187 {
|
|
1188 EXTERNAL_LIST_LOOP_2 (elt, list)
|
|
1189 {
|
3469
|
1190 const Extbyte *s;
|
3354
|
1191
|
|
1192 CHECK_STRING (elt);
|
|
1193 s = fc_intern (elt);
|
|
1194 FcObjectSetAdd (os, s);
|
|
1195 }
|
|
1196 }
|
|
1197
|
|
1198 void
|
|
1199 syms_of_font_mgr (void)
|
|
1200 {
|
|
1201 INIT_LRECORD_IMPLEMENTATION(fc_pattern);
|
|
1202
|
|
1203 DEFSYMBOL_MULTIWORD_PREDICATE(Qfc_patternp);
|
|
1204
|
|
1205 DEFSYMBOL(Qfc_result_type_mismatch);
|
|
1206 DEFSYMBOL(Qfc_result_no_match);
|
|
1207 DEFSYMBOL(Qfc_result_no_id);
|
|
1208 DEFSYMBOL(Qfc_internal_error);
|
3360
|
1209 DEFSYMBOL(Qfont_mgr);
|
3354
|
1210
|
|
1211 DEFSUBR(Ffc_pattern_p);
|
|
1212 DEFSUBR(Ffc_pattern_create);
|
|
1213 DEFSUBR(Ffc_name_parse);
|
|
1214 DEFSUBR(Ffc_name_unparse);
|
|
1215 DEFSUBR(Ffc_pattern_duplicate);
|
|
1216 DEFSUBR(Ffc_pattern_add);
|
|
1217 DEFSUBR(Ffc_pattern_del);
|
|
1218 DEFSUBR(Ffc_pattern_get);
|
|
1219 DEFSUBR(Ffc_list_fonts_pattern_objects);
|
|
1220 DEFSUBR(Ffc_font_sort);
|
|
1221 DEFSUBR(Ffc_font_match);
|
|
1222 DEFSUBR(Fxlfd_font_name_p);
|
3931
|
1223
|
|
1224 #ifdef FONTCONFIG_EXPOSE_CONFIG
|
|
1225 INIT_LRECORD_IMPLEMENTATION(fc_config);
|
|
1226
|
|
1227 DEFSYMBOL_MULTIWORD_PREDICATE(Qfc_configp);
|
|
1228
|
|
1229 DEFSUBR(Ffc_config_p);
|
|
1230 DEFSUBR(Ffc_config_create);
|
|
1231 #if 0
|
|
1232 DEFSUBR(Ffc_config_destroy);
|
|
1233 #endif
|
|
1234 DEFSUBR(Ffc_config_set_current);
|
|
1235 DEFSUBR(Ffc_config_get_current);
|
|
1236 DEFSUBR(Ffc_config_up_to_date);
|
|
1237 DEFSUBR(Ffc_config_build_fonts);
|
|
1238 DEFSUBR(Ffc_config_get_config_dirs);
|
|
1239 DEFSUBR(Ffc_config_get_font_dirs);
|
|
1240 DEFSUBR(Ffc_config_get_config_files);
|
|
1241 DEFSUBR(Ffc_config_get_cache);
|
|
1242 DEFSUBR(Ffc_config_get_fonts);
|
|
1243 DEFSUBR(Ffc_config_get_blanks);
|
|
1244 DEFSUBR(Ffc_config_get_rescan_interval);
|
|
1245 DEFSUBR(Ffc_config_set_rescan_interval);
|
|
1246 DEFSUBR(Ffc_config_app_font_add_file);
|
|
1247 DEFSUBR(Ffc_config_app_font_add_dir);
|
|
1248 DEFSUBR(Ffc_config_app_font_clear);
|
|
1249 DEFSUBR(Ffc_config_filename);
|
|
1250 DEFSUBR(Ffc_init_load_config);
|
|
1251 DEFSUBR(Ffc_init_load_config_and_fonts);
|
|
1252 DEFSUBR(Ffc_init);
|
|
1253 DEFSUBR(Ffc_get_version);
|
|
1254 DEFSUBR(Ffc_init_reinitialize);
|
|
1255 DEFSUBR(Ffc_init_bring_up_to_date);
|
|
1256 #endif /* FONTCONFIG_EXPOSE_CONFIG */
|
3354
|
1257 }
|
|
1258
|
|
1259 void
|
|
1260 vars_of_font_mgr (void)
|
|
1261 {
|
3935
|
1262 /* #### The next two DEFVARs belong somewhere else. */
|
3354
|
1263
|
|
1264 /* #### I know, but the right fix is use the generic debug facility. */
|
|
1265 DEFVAR_INT ("xft-debug-level", &debug_xft /*
|
|
1266 Level of debugging messages to issue to stderr for Xft.
|
|
1267 A nonnegative integer. Set to 0 to suppress all warnings.
|
|
1268 Default is 1 to ensure a minimum of debugging output at initialization.
|
|
1269 Higher levels give even more information.
|
|
1270 */ );
|
|
1271 debug_xft = 1;
|
|
1272
|
3935
|
1273 DEFVAR_CONST_INT("xft-version", &xft_version /*
|
3354
|
1274 The major version number of the Xft library being used.
|
|
1275 */ );
|
3935
|
1276 xft_version = XFT_VERSION;
|
|
1277
|
|
1278 DEFVAR_CONST_INT("fc-version", &fc_version /*
|
|
1279 The version number of fontconfig.h. It can be checked against
|
|
1280 `(fc-get-version)', which is the version of the .so.
|
|
1281 It's probably not a disaster if `(> (fc-get-version) fc-version)'.
|
|
1282 */ );
|
|
1283 fc_version = FC_VERSION;
|
3354
|
1284
|
3360
|
1285 Fprovide (intern ("font-mgr"));
|
3354
|
1286 }
|
|
1287
|
|
1288 void
|
|
1289 complex_vars_of_font_mgr (void)
|
|
1290 {
|
3931
|
1291 #ifdef FONTCONFIG_EXPOSE_CONFIG
|
|
1292 Vfc_config_weak_list = make_weak_list (WEAK_LIST_SIMPLE);
|
|
1293 staticpro (&Vfc_config_weak_list);
|
|
1294 #endif
|
|
1295
|
3354
|
1296 DEFVAR_LISP("xft-xlfd-font-regexp", &Vxlfd_font_name_regexp /*
|
|
1297 The regular expression used to match XLFD font names. */
|
|
1298 );
|
|
1299 Vxlfd_font_name_regexp = make_xlfd_font_regexp();
|
|
1300 }
|
|
1301
|
|
1302 void
|
|
1303 reinit_vars_of_font_mgr (void)
|
|
1304 {
|
|
1305 int i, size = (int) countof (fc_standard_properties);
|
|
1306
|
|
1307 FcInit ();
|
|
1308
|
|
1309 fc_property_name_hash_table = make_string_hash_table (size);
|
|
1310 for (i = 0; i < size; ++i)
|
|
1311 puthash (fc_standard_properties[i], NULL, fc_property_name_hash_table);
|
|
1312 }
|
|
1313
|