comparison lisp/fontconfig.el @ 3094:ad2f4ae9895b

[xemacs-hg @ 2005-11-26 11:45:47 by stephent] Xft merge. <87k6ev4p8q.fsf@tleepslib.sk.tsukuba.ac.jp>
author stephent
date Sat, 26 Nov 2005 11:46:25 +0000
parents
children 15fb91e3a115
comparison
equal deleted inserted replaced
3093:769dc945b085 3094:ad2f4ae9895b
1 ;;; fontconfig.el --- New font model, NG
2
3 ;; Copyright (c) 2003 Eric Knauel and Matthias Neubauer
4 ;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
5
6 ;; Authors: Eric Knauel <knauel@informatik.uni-tuebingen.de>
7 ;; Matthias Neubauer <neubauer@informatik.uni-freiburg.de>
8 ;; Stephen J. Turnbull <stephen@xemacs.org>
9 ;; Created: 27 Oct 2003
10 ;; Updated: 05 Mar 2005 by Stephen J. Turnbull
11 ;; Keywords: faces
12
13 ;; XEmacs is free software; you can redistribute it and/or modify it
14 ;; under the terms of the GNU General Public License as published by
15 ;; the Free Software Foundation; either version 2, or (at your option)
16 ;; any later version.
17
18 ;; XEmacs is distributed in the hope that it will be useful, but
19 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 ;; General Public License for more details.
22
23 ;; You should have received a copy of the GNU General Public License
24 ;; along with XEmacs; see the file COPYING. If not, write to the Free
25 ;; Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 ;; 02111-1307, USA.
27
28 ;;; Synched up with: Not in GNU
29
30 ;;; Commentary:
31
32 ;; This file is one of the pillars of the face refactoring effort
33 ;; (another will be colorconfig.el, and there may be others).
34
35 ;; The overall plan is to have a sensible modern model for values of
36 ;; each of the components of a face (starting with fonts and colors),
37 ;; implemented in a single module. Of course we must be able to
38 ;; convert such values to appropriate descriptors for any device type
39 ;; on the one hand, but on the other it seems unreasonable to force
40 ;; users to deal with a large number of different (and arcane, in the
41 ;; case of XLFD) naming formats.
42
43 ;; This file implements font specification. We call a specification a
44 ;; *pattern* to conform to fontconfig usage. The internal
45 ;; representation of a pattern will have Keith Packard's fontconfig
46 ;; API. For one, there is a robust and free C implementation, which
47 ;; is available as a package for all platforms supported by X.org or
48 ;; XFree86. For another, it seems to be capable of representing any
49 ;; specification of any of the font models I know. Third, on X
50 ;; platforms that internal representation can be passed verbatim to
51 ;; libXft to get high quality TrueType fonts rendered with
52 ;; anti-aliasing and hinting.
53
54 ;; We will support the following user interfaces:
55
56 ;; 1. fontconfig font names
57 ;; 2. X Logical Font Descriptions (XLFD)
58 ;; 3. MS Windows font names
59 ;; 4. Mac OS X font names
60
61 ;; and possibly others (such as ad hoc abbreviations used in older X11
62 ;; implementations). This is called the *fontname UI* (for the
63 ;; platform) to distinguish it from XEmacs's internal model
64 ;; (fontconfig patterns) and the API for rendering engines (called the
65 ;; *font API* for the engine).
66
67 ;; We will support the following rendering engine APIs:
68
69 ;; 1. fontconfig patterns (the native language of Xft); to emphasize
70 ;; the engine-specific nature, we will call these *Xft fonts*
71 ;; 2. XLFD strings
72 ;; 3. MS Windows font names
73
74 ;; and possibly others (such as Mac OS X font names). This is called
75 ;; the *font API* (for the platform) to distinguish it from XEmacs's
76 ;; internal model (fontconfig *patterns*) and the names used by users
77 ;; (called the *fontname UI* for the platform).
78
79
80 ;; TODO (possible enhancements)
81 ;; 1. add a more complete docstring for properties as such (would be a
82 ;; hash table?) to describe things like special symbolic values, and
83 ;; Emacs-relevant semantics
84 ;; 2. add a special value defining macro for constants
85
86 ;;; Code:
87
88 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
89 ;;
90 ;; The fontconfig pattern API
91 ;;
92 ;; The basic interfaces are defined as API wrappers in C in xft-font.c
93 ;; #### which should be renamed to fontconfig.c. These are prefixed
94 ;; with "fc-pattern-". These are
95 ;;
96 ;; fc-pattern-p
97 ;; fc-pattern-create
98 ;; fc-pattern-duplicate
99 ;; fc-pattern-add
100 ;; fc-pattern-del
101 ;; fc-pattern-get
102 ;; fc-pattern-destroy
103
104 ;; We provide a LISP-y alias, `make-fc-pattern' for the pattern
105 ;; constructor function `fc-pattern-create'. #### It might make sense
106 ;; to generalize `make-fc-pattern' by allowing a plist of properties
107 ;; as an optional argument. We also provide accessors
108 ;; `fc-pattern-get-PROPERTY' and mutators `fc-pattern-add-PROPERTY'
109 ;; for each of the standard properties used by Xft, which overlap
110 ;; substantially with the properties defined by X11. #### We probably
111 ;; should provide `fc-pattern-delete-PROPERTY', too.
112
113 (defalias 'make-fc-pattern 'fc-pattern-create)
114
115 (defmacro fc-define-property (property type docfrag &optional obsolete-p)
116 "Define PROPERTY as a fontconfig font property of type TYPE using DOCFRAG.
117
118 A font property is a key in a fontconfig pattern and is associated with
119 one or more values of a given type. This macro creates wrappers around
120 `fc-pattern-get' and `fc-pattern-add' for PROPERTY. Wrappers are
121 preferred to use of primitives with a string as the OBJECT argument because
122 typos in wrappers result in \"not fboundp\" errors, while a typo in a string
123 produces a silent null return.
124
125 PROPERTY is a string.
126 TYPE is a symbol indicating the type of the property value. It is used only
127 to modify formatting of the wrapper function docstrings.
128 DOCFRAG is a string which briefly describes the use of the property, and is
129 interpolated into a format to create the doctstrings.
130 OBSOLETE-P if non-nil marks the property as pertaining only to older versions
131 of fontconfig or Xft. This merely adds a deprecation to the docstrings.
132
133 This macro defines an accessor named `fc-pattern-get-PROPERTY' which takes
134 a fontconfig pattern object and an integer as arguments, and returns the
135 value associated with PROPERTY and ID in the pattern object. Since it is
136 not possible to associate a value to PROPERTY for a particular ID, it is
137 not very useful to interpret the values associated with a given id for
138 different properties as being linked to each other in some way.
139
140 A mutator `fc-pattern-add-PROPERTY' which takes a fontconfig pattern object
141 and a value as arguments, and adds the value to the property with the next
142 id. The type of the value is recognized by `fc-pattern-add', and the id
143 is chosen by the fontconfig implementation."
144
145 `(progn
146 (defsubst ,(intern (concat "fc-pattern-get-" property))
147 (pattern id)
148 ,(format "\
149 Return %s %s fc pattern PATTERN %s.%s
150
151 This function is a convenience wrapper for `fc-pattern-get'.
152 See `fc-pattern-get' for documentation of patterns, ids, and error returns."
153 (if (eq type 'boolean)
154 "t"
155 docfrag)
156 (if (eq type 'boolean)
157 "if"
158 "associated with id ID in")
159 (if (eq type 'boolean)
160 docfrag
161 (format "as a%s %s" (if (eq type 'integer) "n" "") type))
162 (if obsolete-p "
163 \(Obsolete, only available on systems using Xft version 1.)"
164 ""))
165 (fc-pattern-get pattern ,property id))
166
167 (defsubst ,(intern (concat "fc-pattern-add-" property))
168 (pattern value)
169 ,(format "\
170 Add VALUE to the %s property of fontconfig pattern PATTERN.%s
171
172 The type of VALUE should be %s.
173
174 This function is a convenience wrapper for `fc-pattern-add'.
175 See `fc-pattern-add' for documentation of patterns, values, and error returns."
176 property
177 (if obsolete-p "
178 \(Obsolete, only available on systems using Xft version 1.)"
179 "")
180 type)
181 (fc-pattern-add pattern ,property value))
182 ,property))
183
184 ;; define the standard properties for Xft v.2 here
185 (fc-define-property "antialias" boolean "the font supports antialiasing")
186 (fc-define-property "dpi" float "the design resolution")
187 (fc-define-property "family" string "the font family")
188 (fc-define-property "file" string "the file containing glyph data")
189 (fc-define-property "foundry" string "the vendor")
190 (fc-define-property "index" integer "the index of the glyph set")
191 (fc-define-property "minspace" boolean "has a minimum spacing")
192 (fc-define-property "outline" boolean "is an outline font")
193 (fc-define-property "pixelsize" float "the size in pixels")
194 (fc-define-property "rasterizer" string "the name of the rasterizing engine")
195 (fc-define-property "rgba" integer "the subpixel rendering capabilities")
196 (fc-define-property "scalable" boolean "is scalable")
197 (fc-define-property "scale" float "the scale factor")
198 (fc-define-property "size" float "the size in points")
199 (fc-define-property "slant" integer "the slant")
200 (fc-define-property "spacing" integer "the spacing model")
201 (fc-define-property "style" string "the typographic face or style")
202 (fc-define-property "weight" integer "the weight")
203 (fc-define-property "xlfd" string "the XLFD (full name in X11)")
204
205 ;; Xft v.1 properties (marked as obsolete)
206 (fc-define-property "encoding" string "the encoding" t)
207 (fc-define-property "charwidth" integer "the average character width" t)
208 (fc-define-property "charheight" integer "the average character height" t)
209 (fc-define-property "core" boolean "represents a core font" t)
210 (fc-define-property "render" boolean "represents a render (Xft) font" t)
211
212
213 (defconst fc-font-name-property-family "family")
214 (defconst fc-font-name-property-style "style")
215 (defconst fc-font-name-property-slant "slant")
216 (defconst fc-font-name-property-weight "weight")
217 (defconst fc-font-name-property-size "size")
218 (defconst fc-font-name-property-pixelsize "pixelsize")
219 (defconst fc-font-name-property-spacing "spacing")
220 (defconst fc-font-name-property-foundry "foundry")
221 (defconst fc-font-name-property-antialias "antialias")
222 (defconst fc-font-name-property-xlfd "xlfd")
223 (defconst fc-font-name-property-file "file")
224 (defconst fc-font-name-property-index "index")
225 (defconst fc-font-name-property-rasterizer "rasterizer")
226 (defconst fc-font-name-property-outline "outline")
227 (defconst fc-font-name-property-scalable "scalable")
228 (defconst fc-font-name-property-rgba "rgba")
229 (defconst fc-font-name-property-minspace "minspace")
230 (defconst fc-font-name-property-dpi "dpi")
231
232 ;; Xft version 1 only
233 ;;(defconst fc-font-name-property-encoding "encoding")
234 ;;(defconst fc-font-name-property-charwidth "charwidth")
235 ;;(defconst fc-font-name-property-charheight "charheight")
236 ;;(defconst fc-font-name-property-core "core")
237 ;;(defconst fc-font-name-property-render "render")
238
239
240 (defconst fc-pattern-selector-mapping
241 `((,fc-font-name-property-family . fc-pattern-get-family)
242 (,fc-font-name-property-style . fc-pattern-get-style)
243 (,fc-font-name-property-slant . fc-pattern-get-slant)
244 (,fc-font-name-property-weight . fc-pattern-get-weight)
245 (,fc-font-name-property-size . fc-pattern-get-size)
246 (,fc-font-name-property-pixelsize . fc-pattern-get-pixelsize)
247 (,fc-font-name-property-spacing . fc-pattern-get-spacing)
248 (,fc-font-name-property-foundry . fc-pattern-get-foundry)
249 (,fc-font-name-property-antialias . fc-pattern-get-antialias)
250 (,fc-font-name-property-xlfd . fc-pattern-get-xlfd)
251 (,fc-font-name-property-file . fc-pattern-get-file)
252 (,fc-font-name-property-index . fc-pattern-get-index)
253 (,fc-font-name-property-rasterizer . fc-pattern-get-rasterizer)
254 (,fc-font-name-property-outline . fc-pattern-get-outline)
255 (,fc-font-name-property-scalable . fc-pattern-get-scalable)
256 (,fc-font-name-property-rgba . fc-pattern-get-rgba)
257 (,fc-font-name-property-minspace . fc-pattern-get-minspace)
258 (,fc-font-name-property-dpi . fc-pattern-get-dpi)
259 ;; Xft version 1 only
260 ;; (,fc-font-name-property-encoding . fc-pattern-get-encoding)
261 ;; (,fc-font-name-property-charwidth . fc-pattern-get-char-width)
262 ;; (,fc-font-name-property-charheight . fc-pattern-get-char-height)
263 ;; (,fc-font-name-property-core . fc-pattern-get-core)
264 ;; (,fc-font-name-property-render . fc-pattern-get-render)
265 ))
266
267 (defvar fc-find-available-font-families-fc-fonts-only t
268 "If `fc-find-available-font-families-fc-fonts-only' is set to `t',
269 `fc-find-available-font-families' will ignore core fonts.")
270
271 (defconst fc-font-name-slant-roman 0)
272 (defconst fc-font-name-slant-italic 100)
273 (defconst fc-font-name-slant-oblique 110)
274
275 (defconst fc-font-name-slant-mapping
276 `((,fc-font-name-slant-roman . :roman)
277 (,fc-font-name-slant-italic . :italic)
278 (,fc-font-name-slant-oblique . :oblique)))
279
280 (defconst fc-font-name-slant-mapping-string
281 `((,fc-font-name-slant-roman . "R")
282 (,fc-font-name-slant-roman . "I")
283 (,fc-font-name-slant-roman . "O")))
284
285 (defconst fc-font-name-slant-mapping-string-reverse
286 `(("R" . ,fc-font-name-slant-roman)
287 ("I" . ,fc-font-name-slant-italic)
288 ("O" . ,fc-font-name-slant-oblique)))
289
290 (defconst fc-font-name-slant-mapping-reverse
291 `((:roman . ,fc-font-name-slant-roman)
292 (:italic . ,fc-font-name-slant-italic)
293 (:oblique . ,fc-font-name-slant-oblique)))
294
295 (defun fc-font-slant-translate-from-constant (number)
296 "Translate the Xft font slant constant NUMBER to symbol."
297 (let ((pair (assoc number fc-font-name-slant-mapping)))
298 (if pair (cdr pair))))
299
300 (defun fc-font-slant-translate-from-symbol (symbol)
301 "Translate SYMBOL (`:roman', `:italic' or `:oblique') to the
302 corresponding Xft font slant constant."
303 (let ((pair (assoc symbol fc-font-name-slant-mapping-reverse)))
304 (if pair (cdr pair))))
305
306 (defun fc-font-slant-translate-to-string (num-or-sym)
307 (let* ((constant (if (symbolp num-or-sym)
308 (cdr (assoc num-or-sym fc-font-name-slant-mapping-reverse))
309 num-or-sym))
310 (pair (assoc constant fc-font-name-slant-mapping-string)))
311 (if pair (cdr pair))))
312
313 (defun fc-font-slant-translate-from-string (str)
314 (let ((pair (assoc str fc-font-name-slant-mapping-string-reverse)))
315 (if pair (cdr pair))))
316
317 (defconst fc-font-name-weight-light 0)
318 (defconst fc-font-name-weight-regular 80)
319 (defconst fc-font-name-weight-medium 100)
320 (defconst fc-font-name-weight-demibold 180)
321 (defconst fc-font-name-weight-bold 200)
322 (defconst fc-font-name-weight-black 210)
323
324 (defconst fc-font-name-weight-mapping
325 `((,fc-font-name-weight-light . :light)
326 (,fc-font-name-weight-regular . :regular)
327 (,fc-font-name-weight-medium . :medium)
328 (,fc-font-name-weight-demibold . :demibold)
329 (,fc-font-name-weight-bold . :bold)
330 (,fc-font-name-weight-black . :black)))
331
332 (defconst fc-font-name-weight-mapping-string
333 `((,fc-font-name-weight-light . "Light")
334 (,fc-font-name-weight-regular . "Regular")
335 (,fc-font-name-weight-medium . "Medium")
336 (,fc-font-name-weight-demibold . "Demibold")
337 (,fc-font-name-weight-bold . "Bold")
338 (,fc-font-name-weight-black . "Black")))
339
340 (defconst fc-font-name-weight-mapping-string-reverse
341 `(("Light" . ,fc-font-name-weight-light)
342 ("Regular" . ,fc-font-name-weight-regular)
343 ("Medium" . ,fc-font-name-weight-medium)
344 ("Demibold" . ,fc-font-name-weight-demibold)
345 ("Bold" . ,fc-font-name-weight-bold)
346 ("Black" . ,fc-font-name-weight-black)))
347
348 (defconst fc-font-name-weight-mapping-reverse
349 `((:light . ,fc-font-name-weight-light)
350 (:regular . ,fc-font-name-weight-regular)
351 (:medium . ,fc-font-name-weight-medium)
352 (:demibold . ,fc-font-name-weight-demibold)
353 (:bold . ,fc-font-name-weight-bold)
354 (:black . ,fc-font-name-weight-black)))
355
356 (defun fc-font-weight-translate-from-constant (number)
357 "Translate a Xft font weight constant NUMBER to symbol."
358 (let ((pair (assoc number fc-font-name-weight-mapping)))
359 (if pair (cdr pair))))
360
361 (defun fc-font-weight-translate-from-symbol (symbol)
362 "Translate SYMBOL (`:light', `:regular', `:medium', `:demibold',
363 `:bold' or `:black') to the corresponding Xft font weight constant."
364 (let ((pair (assoc symbol fc-font-name-weight-mapping-reverse)))
365 (if pair (cdr pair))))
366
367 (defun fc-font-weight-translate-to-string (num-or-sym)
368 (let* ((constant (if (symbolp num-or-sym)
369 (cdr (assoc num-or-sym fc-font-name-weight-mapping-reverse))
370 num-or-sym))
371 (pair (assoc constant fc-font-name-weight-mapping-string)))
372 (if pair (cdr pair))))
373
374 (defun fc-font-weight-translate-from-string (str)
375 (let ((pair (assoc str fc-font-name-weight-mapping-string-reverse)))
376 (if pair (cdr pair))))
377
378 (defun fc-copy-pattern-partial (pattern attribute-list)
379 "Return a copy of PATTERN restricted to ATTRIBUTE-LIST.
380
381 PATTERN is a fontconfig pattern object.
382 ATTRIBUTE-LIST is a list of strings denoting font properties.
383 A new object is allocated and returned."
384 (let ((new (make-fc-pattern))
385 (attrs attribute-list))
386 ;;; We demand proper tail recursion!
387 (while (not (null attrs))
388 (let ((get (intern (concat "fc-pattern-get-" (car attrs))))
389 (set (intern (concat "fc-pattern-add-" (car attrs)))))
390 (if (and (fboundp get) (fboundp set))
391 (funcall set new (funcall get pattern 0))
392 (warn "property '%s' not defined, ignoring" (car attrs))))
393 (setq attrs (cdr attrs)))
394 new))
395
396 (defun fc-pattern-get-all-attributes (fc-pattern fc-pattern-get-function)
397 (let ((count 0)
398 res end val)
399 (while (not end)
400 (setq val (funcall fc-pattern-get-function fc-pattern count))
401 (if (or (equal val 'fc-result-no-id)
402 (equal val 'fc-result-no-match))
403 (setq end t)
404 (setq res (append res (list val))
405 count (+ count 1))))
406 res))
407
408 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
409 ;;
410 ;; The fontconfig fontname UI
411 ;;
412 ;; The basic interfaces are defined as API wrappers in C in xft-font.c
413 ;; #### which should be renamed to fontconfig.c. These are prefixed
414 ;; with "fc-name-". These are
415 ;;
416 ;; fc-name-parse
417 ;; fc-name-unparse
418 ;; xft-name-unparse
419
420 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
421 ;;
422 ;; The fontconfig font API
423 ;;
424 ;; The basic interfaces are defined as API wrappers in C in xft-font.c
425 ;; #### which should be renamed to fontconfig.c. These are prefixed
426 ;; with "fc-font-". These are
427 ;;
428 ;; fc-font-match
429 ;; fc-list-fonts-pattern-objects
430 ;; fc-font-sort
431 ;; fc-font-real-pattern
432
433 ;; #### it might make sense to generalize `fc-try-font' by having a
434 ;; global variable that contains a list of font name parsers. They are
435 ;; tried in order, and the first one to return an fc-pattern is matched.
436
437 (defun fc-try-font (font &optional device)
438 "Return list of pattern objects matching FONT on DEVICE.
439
440 FONT may be a fontconfig pattern object or a fontconfig font name (a string).
441 Optional DEVICE is the device object to query, defaulting to the currently
442 selected device."
443 (fc-list-fonts-pattern-objects (or device (default-x-device))
444 (if (fc-pattern-p font)
445 font
446 (fc-name-parse font))
447 nil))
448
449 (defun fc-find-available-font-families (&optional device filter-fun)
450 "Find all available font families."
451 (let ((device (or device (default-x-device)))
452 (pattern (make-fc-pattern))
453 (objectset '("family" "style")))
454 ; Xft2: does not work anymore
455 ; (if (not fc-find-available-font-families-fc-fonts-only)
456 ; (fc-pattern-add pattern fc-font-name-property-core t))
457 ; (fc-objectset-add objectset fc-font-name-property-encoding)
458 (let* ((all-fonts
459 (fc-list-fonts-pattern-objects device pattern objectset)))
460 (fc-delete-duplicates
461 (mapcar
462 '(lambda (pattern)
463 (fc-pattern-get-family pattern 0))
464 (if filter-fun
465 (fc-filter all-fonts filter-fun)
466 all-fonts))))))
467
468 ; Xft2: does not work anymore
469 ; (defun fc-find-available-font-families-non-mule (&optional device)
470 ; (fc-find-available-font-families
471 ; device
472 ; '(lambda (pattern)
473 ; (let ((encodings (fc-pattern-get-all-attributes
474 ; pattern 'fc-pattern-get-encoding)))
475 ; ;; Be sure that the font support ISO-8859-1
476 ; (member "iso8859-1" encodings)))))
477
478 (defun fc-find-available-weights-for-family (family &optional style device)
479 "Find available weights for font FAMILY."
480 (let* ((device (or device (default-x-device)))
481 (pattern (make-fc-pattern))
482 (objectset '("weight")))
483 (fc-pattern-add pattern fc-font-name-property-family family)
484 (if style
485 (fc-pattern-add pattern fc-font-name-property-style style))
486 (mapcar
487 '(lambda (pattern)
488 (let ((fc-weight-constant (fc-pattern-get-weight pattern 0)))
489 (if fc-weight-constant
490 (fc-font-weight-translate-from-constant fc-weight-constant))))
491 (fc-list-fonts-pattern-objects device pattern objectset))))
492
493 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
494 ;;
495 ;; The XLFD fontname UI
496 ;;
497
498 ;; xlfd-font-name-p
499
500 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
501 ;;
502 ;; Utility functions
503 ;;
504
505 (defun fc-pattern-get-successp (result)
506 (and (not (equal result 'fc-result-no-match))
507 (not (equal result 'fc-result-no-id))
508 (not (equal result 'fc-internal-error))))
509
510 ;;; DELETE-DUPLICATES and REMOVE-DUPLICATES from cl-seq.el do not
511 ;;; seem to work on list of strings...
512 ;;; #### Presumably just use :test 'equal!
513 (defun fc-delete-duplicates (l)
514 (let ((res nil)
515 (in l))
516 (while (not (null in))
517 (if (not (member (car in) res))
518 (setq res (append res (list (car in)))))
519 (setq in (cdr in)))
520 res))
521
522 ;; #### Use delete-if with :test 'equal.
523 (defun fc-filter (l fun)
524 (let ((res nil)
525 (in l))
526 (while (not (null in))
527 (if (funcall fun (car in))
528 (setq res (append res (list (car in)))))
529 (setq in (cdr in)))
530 res))
531
532 (provide 'fontconfig)
533
534 ;;; fontconfig.el ends here