diff 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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lisp/fontconfig.el	Sat Nov 26 11:46:25 2005 +0000
@@ -0,0 +1,534 @@
+;;; fontconfig.el --- New font model, NG
+
+;; Copyright (c) 2003 Eric Knauel and Matthias Neubauer
+;; Copyright (C) 2004, 2005 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:	05 Mar 2005 by Stephen J. Turnbull
+;; Keywords: faces
+
+;; 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
+
+;;; Commentary:
+
+;; This file is one of the pillars of the face refactoring effort
+;; (another will be colorconfig.el, and there may be others).
+
+;; The overall plan is to have a sensible modern model for values of
+;; each of the components of a face (starting with fonts and colors),
+;; implemented in a single module.  Of course we must be able to
+;; convert such values to appropriate descriptors for any device type
+;; on the one hand, but on the other it seems unreasonable to force
+;; users to deal with a large number of different (and arcane, in the
+;; case of XLFD) naming formats.
+
+;; This file implements font specification.  We call a specification a
+;; *pattern* to conform to fontconfig usage.  The internal
+;; representation of a pattern will have Keith Packard's fontconfig
+;; API.  For one, there is a robust and free C implementation, which
+;; is available as a package for all platforms supported by X.org or
+;; XFree86.  For another, it seems to be capable of representing any
+;; specification of any of the font models I know.  Third, on X
+;; platforms that internal representation can be passed verbatim to
+;; libXft to get high quality TrueType fonts rendered with
+;; anti-aliasing and hinting.
+
+;; We will support the following user interfaces:
+
+;;   1. fontconfig font names
+;;   2. X Logical Font Descriptions (XLFD)
+;;   3. MS Windows font names
+;;   4. Mac OS X font names
+
+;; and possibly others (such as ad hoc abbreviations used in older X11
+;; implementations).  This is called the *fontname UI* (for the
+;; platform) to distinguish it from XEmacs's internal model
+;; (fontconfig patterns) and the API for rendering engines (called the
+;; *font API* for the engine).
+
+;; We will support the following rendering engine APIs:
+
+;;   1. fontconfig patterns (the native language of Xft); to emphasize
+;;      the engine-specific nature, we will call these *Xft fonts*
+;;   2. XLFD strings
+;;   3. MS Windows font names
+
+;; and possibly others (such as Mac OS X font names).  This is called
+;; the *font API* (for the platform) to distinguish it from XEmacs's
+;; internal model (fontconfig *patterns*) and the names used by users
+;; (called the *fontname UI* for the platform).
+
+
+;; TODO (possible enhancements)
+;; 1.  add a more complete docstring for properties as such (would be a
+;;     hash table?) to describe things like special symbolic values, and
+;;     Emacs-relevant semantics
+;; 2.  add a special value defining macro for constants
+
+;;; Code:
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; The fontconfig pattern API
+;;
+;; The basic interfaces are defined as API wrappers in C in xft-font.c
+;; #### which should be renamed to fontconfig.c.  These are prefixed
+;; with "fc-pattern-".  These are
+;;
+;;   fc-pattern-p
+;;   fc-pattern-create
+;;   fc-pattern-duplicate
+;;   fc-pattern-add
+;;   fc-pattern-del
+;;   fc-pattern-get
+;;   fc-pattern-destroy
+
+;; We provide a LISP-y alias, `make-fc-pattern' for the pattern
+;; constructor function `fc-pattern-create'.  #### It might make sense
+;; to generalize `make-fc-pattern' by allowing a plist of properties
+;; as an optional argument.  We also provide accessors
+;; `fc-pattern-get-PROPERTY' and mutators `fc-pattern-add-PROPERTY'
+;; for each of the standard properties used by Xft, which overlap
+;; substantially with the properties defined by X11.  #### We probably
+;; should provide `fc-pattern-delete-PROPERTY', too.
+
+(defalias 'make-fc-pattern 'fc-pattern-create)
+
+(defmacro fc-define-property (property type docfrag &optional obsolete-p)
+  "Define PROPERTY as a fontconfig font property of type TYPE using DOCFRAG.
+
+A font property is a key in a fontconfig pattern and is associated with
+one or more values of a given type.  This macro creates wrappers around
+`fc-pattern-get' and `fc-pattern-add' for PROPERTY.  Wrappers are
+preferred to use of primitives with a string as the OBJECT argument because
+typos in wrappers result in \"not fboundp\" errors, while a typo in a string
+produces a silent null return.
+
+PROPERTY is a string.
+TYPE is a symbol indicating the type of the property value.  It is used only
+to modify formatting of the wrapper function docstrings.
+DOCFRAG is a string which briefly describes the use of the property, and is
+interpolated into a format to create the doctstrings.
+OBSOLETE-P if non-nil marks the property as pertaining only to older versions
+of fontconfig or Xft.  This merely adds a deprecation to the docstrings.
+
+This macro defines an accessor named `fc-pattern-get-PROPERTY' which takes
+a fontconfig pattern object and an integer as arguments, and returns the
+value associated with PROPERTY and ID in the pattern object.  Since it is
+not possible to associate a value to PROPERTY for a particular ID, it is
+not very useful to interpret the values associated with a given id for
+different properties as being linked to each other in some way.
+
+A mutator `fc-pattern-add-PROPERTY' which takes a fontconfig pattern object
+and a value as arguments, and adds the value to the property with the next
+id.  The type of the value is recognized by `fc-pattern-add', and the id
+is chosen by the fontconfig implementation."
+
+  `(progn
+    (defsubst ,(intern (concat "fc-pattern-get-" property))
+      (pattern id)
+      ,(format "\
+Return %s %s fc pattern PATTERN %s.%s
+
+This function is a convenience wrapper for `fc-pattern-get'.
+See `fc-pattern-get' for documentation of patterns, ids, and error returns."
+	       (if (eq type 'boolean)
+		   "t"
+		 docfrag)
+	       (if (eq type 'boolean)
+		   "if"
+		 "associated with id ID in")
+	       (if (eq type 'boolean)
+		   docfrag
+		 (format "as a%s %s" (if (eq type 'integer) "n" "") type))
+	       (if obsolete-p "
+\(Obsolete, only available on systems using Xft version 1.)"
+		 ""))
+      (fc-pattern-get pattern ,property id))
+
+    (defsubst ,(intern (concat "fc-pattern-add-" property))
+      (pattern value)
+      ,(format "\
+Add VALUE to the %s property of fontconfig pattern PATTERN.%s
+
+The type of VALUE should be %s.
+
+This function is a convenience wrapper for `fc-pattern-add'.
+See `fc-pattern-add' for documentation of patterns, values, and error returns."
+	       property
+	       (if obsolete-p "
+\(Obsolete, only available on systems using Xft version 1.)"
+		 "")
+	       type)
+      (fc-pattern-add pattern ,property value))
+    ,property))
+
+;; define the standard properties for Xft v.2 here
+(fc-define-property "antialias" boolean "the font supports antialiasing")
+(fc-define-property "dpi" float "the design resolution")
+(fc-define-property "family" string "the font family")
+(fc-define-property "file" string "the file containing glyph data")
+(fc-define-property "foundry" string "the vendor")
+(fc-define-property "index" integer "the index of the glyph set")
+(fc-define-property "minspace" boolean "has a minimum spacing")
+(fc-define-property "outline" boolean "is an outline font")
+(fc-define-property "pixelsize" float "the size in pixels")
+(fc-define-property "rasterizer" string "the name of the rasterizing engine")
+(fc-define-property "rgba" integer "the subpixel rendering capabilities")
+(fc-define-property "scalable" boolean "is scalable")
+(fc-define-property "scale" float "the scale factor")
+(fc-define-property "size" float "the size in points")
+(fc-define-property "slant" integer "the slant")
+(fc-define-property "spacing" integer "the spacing model")
+(fc-define-property "style" string "the typographic face or style")
+(fc-define-property "weight" integer "the weight")
+(fc-define-property "xlfd" string "the XLFD (full name in X11)")
+
+;; Xft v.1 properties (marked as obsolete)
+(fc-define-property "encoding" string "the encoding" t)
+(fc-define-property "charwidth" integer "the average character width" t)
+(fc-define-property "charheight" integer "the average character height" t)
+(fc-define-property "core" boolean "represents a core font" t)
+(fc-define-property "render" boolean "represents a render (Xft) font" t)
+
+
+(defconst fc-font-name-property-family "family")
+(defconst fc-font-name-property-style "style")
+(defconst fc-font-name-property-slant "slant")
+(defconst fc-font-name-property-weight "weight")
+(defconst fc-font-name-property-size "size")
+(defconst fc-font-name-property-pixelsize "pixelsize")
+(defconst fc-font-name-property-spacing "spacing")
+(defconst fc-font-name-property-foundry "foundry")
+(defconst fc-font-name-property-antialias "antialias")
+(defconst fc-font-name-property-xlfd "xlfd")
+(defconst fc-font-name-property-file "file")
+(defconst fc-font-name-property-index "index")
+(defconst fc-font-name-property-rasterizer "rasterizer")
+(defconst fc-font-name-property-outline "outline")
+(defconst fc-font-name-property-scalable "scalable")
+(defconst fc-font-name-property-rgba "rgba")
+(defconst fc-font-name-property-minspace "minspace")
+(defconst fc-font-name-property-dpi "dpi")
+
+;; Xft version 1 only
+;;(defconst fc-font-name-property-encoding "encoding")
+;;(defconst fc-font-name-property-charwidth "charwidth")
+;;(defconst fc-font-name-property-charheight "charheight")
+;;(defconst fc-font-name-property-core "core")
+;;(defconst fc-font-name-property-render "render")
+
+
+(defconst fc-pattern-selector-mapping
+  `((,fc-font-name-property-family        . fc-pattern-get-family)
+    (,fc-font-name-property-style         . fc-pattern-get-style)
+    (,fc-font-name-property-slant         . fc-pattern-get-slant)
+    (,fc-font-name-property-weight        . fc-pattern-get-weight)
+    (,fc-font-name-property-size          . fc-pattern-get-size)
+    (,fc-font-name-property-pixelsize     . fc-pattern-get-pixelsize)
+    (,fc-font-name-property-spacing       . fc-pattern-get-spacing)
+    (,fc-font-name-property-foundry       . fc-pattern-get-foundry)
+    (,fc-font-name-property-antialias     . fc-pattern-get-antialias)
+    (,fc-font-name-property-xlfd          . fc-pattern-get-xlfd)
+    (,fc-font-name-property-file          . fc-pattern-get-file)
+    (,fc-font-name-property-index         . fc-pattern-get-index)
+    (,fc-font-name-property-rasterizer    . fc-pattern-get-rasterizer)
+    (,fc-font-name-property-outline       . fc-pattern-get-outline)
+    (,fc-font-name-property-scalable      . fc-pattern-get-scalable)
+    (,fc-font-name-property-rgba          . fc-pattern-get-rgba)
+    (,fc-font-name-property-minspace      . fc-pattern-get-minspace)
+    (,fc-font-name-property-dpi           . fc-pattern-get-dpi)
+    ;; Xft version 1 only
+    ;; (,fc-font-name-property-encoding      . fc-pattern-get-encoding)
+    ;; (,fc-font-name-property-charwidth     . fc-pattern-get-char-width)
+    ;; (,fc-font-name-property-charheight    . fc-pattern-get-char-height)
+    ;; (,fc-font-name-property-core          . fc-pattern-get-core)
+    ;; (,fc-font-name-property-render        . fc-pattern-get-render)
+    ))
+
+(defvar fc-find-available-font-families-fc-fonts-only t
+  "If `fc-find-available-font-families-fc-fonts-only' is set to `t',
+`fc-find-available-font-families' will ignore core fonts.")
+
+(defconst fc-font-name-slant-roman 0)
+(defconst fc-font-name-slant-italic 100)
+(defconst fc-font-name-slant-oblique 110)
+
+(defconst fc-font-name-slant-mapping
+  `((,fc-font-name-slant-roman   . :roman)
+    (,fc-font-name-slant-italic  . :italic)
+    (,fc-font-name-slant-oblique . :oblique)))
+
+(defconst fc-font-name-slant-mapping-string
+  `((,fc-font-name-slant-roman   . "R")
+    (,fc-font-name-slant-roman   . "I")
+    (,fc-font-name-slant-roman   . "O")))
+
+(defconst fc-font-name-slant-mapping-string-reverse
+  `(("R" . ,fc-font-name-slant-roman)
+    ("I" . ,fc-font-name-slant-italic)
+    ("O" . ,fc-font-name-slant-oblique)))
+
+(defconst fc-font-name-slant-mapping-reverse
+  `((:roman   . ,fc-font-name-slant-roman)
+    (:italic  . ,fc-font-name-slant-italic)
+    (:oblique . ,fc-font-name-slant-oblique)))
+
+(defun fc-font-slant-translate-from-constant (number)
+  "Translate the Xft font slant constant NUMBER to symbol."
+  (let ((pair (assoc number fc-font-name-slant-mapping)))
+    (if pair (cdr pair))))
+
+(defun fc-font-slant-translate-from-symbol (symbol)
+  "Translate SYMBOL (`:roman', `:italic' or `:oblique') to the
+corresponding Xft font slant constant."
+  (let ((pair (assoc symbol fc-font-name-slant-mapping-reverse)))
+    (if pair (cdr pair))))
+
+(defun fc-font-slant-translate-to-string (num-or-sym)
+  (let* ((constant (if (symbolp num-or-sym)
+		       (cdr (assoc num-or-sym fc-font-name-slant-mapping-reverse))
+		     num-or-sym))
+	 (pair (assoc constant fc-font-name-slant-mapping-string)))
+    (if pair (cdr pair))))
+
+(defun fc-font-slant-translate-from-string (str)
+  (let ((pair (assoc str fc-font-name-slant-mapping-string-reverse)))
+    (if pair (cdr pair))))
+
+(defconst fc-font-name-weight-light 0)
+(defconst fc-font-name-weight-regular 80)
+(defconst fc-font-name-weight-medium 100)
+(defconst fc-font-name-weight-demibold 180)
+(defconst fc-font-name-weight-bold 200)
+(defconst fc-font-name-weight-black 210)
+
+(defconst fc-font-name-weight-mapping
+  `((,fc-font-name-weight-light    . :light)
+    (,fc-font-name-weight-regular  . :regular)
+    (,fc-font-name-weight-medium   . :medium)
+    (,fc-font-name-weight-demibold . :demibold)
+    (,fc-font-name-weight-bold     . :bold)
+    (,fc-font-name-weight-black    . :black)))
+
+(defconst fc-font-name-weight-mapping-string
+  `((,fc-font-name-weight-light    . "Light")
+    (,fc-font-name-weight-regular  . "Regular")
+    (,fc-font-name-weight-medium   . "Medium")
+    (,fc-font-name-weight-demibold . "Demibold")
+    (,fc-font-name-weight-bold     . "Bold")
+    (,fc-font-name-weight-black    . "Black")))
+
+(defconst fc-font-name-weight-mapping-string-reverse
+  `(("Light"    . ,fc-font-name-weight-light)
+    ("Regular"  . ,fc-font-name-weight-regular)
+    ("Medium"   . ,fc-font-name-weight-medium)
+    ("Demibold" . ,fc-font-name-weight-demibold)
+    ("Bold"     . ,fc-font-name-weight-bold)
+    ("Black"    . ,fc-font-name-weight-black)))
+
+(defconst fc-font-name-weight-mapping-reverse
+  `((:light    . ,fc-font-name-weight-light)
+    (:regular  . ,fc-font-name-weight-regular)
+    (:medium   . ,fc-font-name-weight-medium)
+    (:demibold . ,fc-font-name-weight-demibold)
+    (:bold     . ,fc-font-name-weight-bold)
+    (:black    . ,fc-font-name-weight-black)))
+
+(defun fc-font-weight-translate-from-constant (number)
+  "Translate a Xft font weight constant NUMBER to symbol."
+  (let ((pair (assoc number fc-font-name-weight-mapping)))
+    (if pair (cdr pair))))
+
+(defun fc-font-weight-translate-from-symbol (symbol) 
+  "Translate SYMBOL (`:light', `:regular', `:medium', `:demibold',
+`:bold' or `:black') to the corresponding Xft font weight constant."
+  (let ((pair (assoc symbol fc-font-name-weight-mapping-reverse)))
+    (if pair (cdr pair))))
+
+(defun fc-font-weight-translate-to-string (num-or-sym)
+  (let* ((constant (if (symbolp num-or-sym)
+		       (cdr (assoc num-or-sym fc-font-name-weight-mapping-reverse))
+		     num-or-sym))
+	 (pair (assoc constant fc-font-name-weight-mapping-string)))
+    (if pair (cdr pair))))
+
+(defun fc-font-weight-translate-from-string (str)
+  (let ((pair (assoc str fc-font-name-weight-mapping-string-reverse)))
+    (if pair (cdr pair))))
+
+(defun fc-copy-pattern-partial (pattern attribute-list)
+  "Return a copy of PATTERN restricted to ATTRIBUTE-LIST.
+
+PATTERN is a fontconfig pattern object.
+ATTRIBUTE-LIST is a list of strings denoting font properties.
+A new object is allocated and returned."
+  (let ((new (make-fc-pattern))
+	(attrs attribute-list))
+    ;;; We demand proper tail recursion!
+    (while (not (null attrs))
+      (let ((get (intern (concat "fc-pattern-get-" (car attrs))))
+	    (set (intern (concat "fc-pattern-add-" (car attrs)))))
+	(if (and (fboundp get) (fboundp set))
+	    (funcall set new (funcall get pattern 0))
+	  (warn "property '%s' not defined, ignoring" (car attrs))))
+      (setq attrs (cdr attrs)))
+    new))
+
+(defun fc-pattern-get-all-attributes (fc-pattern fc-pattern-get-function)
+  (let ((count 0)
+	res end val)
+    (while (not end)
+      (setq val (funcall fc-pattern-get-function fc-pattern count))
+      (if (or (equal val 'fc-result-no-id)
+	      (equal val 'fc-result-no-match))
+	  (setq end t)
+	(setq res (append res (list val))
+	      count (+ count 1))))
+    res))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; The fontconfig fontname UI
+;;
+;; The basic interfaces are defined as API wrappers in C in xft-font.c
+;; #### which should be renamed to fontconfig.c.  These are prefixed
+;; with "fc-name-".  These are
+;;
+;;   fc-name-parse
+;;   fc-name-unparse
+;;   xft-name-unparse
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; The fontconfig font API
+;;
+;; The basic interfaces are defined as API wrappers in C in xft-font.c
+;; #### which should be renamed to fontconfig.c.  These are prefixed
+;; with "fc-font-".  These are
+;;
+;;   fc-font-match
+;;   fc-list-fonts-pattern-objects
+;;   fc-font-sort
+;;   fc-font-real-pattern
+
+;; #### it might make sense to generalize `fc-try-font' by having a
+;; global variable that contains a list of font name parsers.  They are
+;; tried in order, and the first one to return an fc-pattern is matched.
+
+(defun fc-try-font (font &optional device)
+  "Return list of pattern objects matching FONT on DEVICE.
+
+FONT may be a fontconfig pattern object or a fontconfig font name (a string).
+Optional DEVICE is the device object to query, defaulting to the currently
+selected device."
+  (fc-list-fonts-pattern-objects (or device (default-x-device))
+				 (if (fc-pattern-p font) 
+				     font
+				   (fc-name-parse font))
+				 nil))
+
+(defun fc-find-available-font-families (&optional device filter-fun)
+  "Find all available font families."
+  (let ((device (or device (default-x-device)))
+	(pattern (make-fc-pattern))
+	(objectset '("family" "style")))
+;     Xft2: does not work anymore
+;     (if (not fc-find-available-font-families-fc-fonts-only)
+; 	(fc-pattern-add pattern fc-font-name-property-core t))
+;     (fc-objectset-add objectset fc-font-name-property-encoding)
+    (let* ((all-fonts
+	    (fc-list-fonts-pattern-objects device pattern objectset)))
+      (fc-delete-duplicates
+       (mapcar
+	'(lambda (pattern)
+	   (fc-pattern-get-family pattern 0))
+	(if filter-fun
+	    (fc-filter all-fonts filter-fun)
+	  all-fonts))))))
+
+; Xft2: does not work anymore
+; (defun fc-find-available-font-families-non-mule (&optional device)
+;   (fc-find-available-font-families
+;    device
+;    '(lambda (pattern)
+;       (let ((encodings (fc-pattern-get-all-attributes 
+; 			pattern 'fc-pattern-get-encoding)))
+; 	;; Be sure that the font support ISO-8859-1
+; 	(member "iso8859-1" encodings)))))
+
+(defun fc-find-available-weights-for-family (family &optional style device)
+  "Find available weights for font FAMILY."
+  (let* ((device (or device (default-x-device)))
+	 (pattern (make-fc-pattern))
+	 (objectset '("weight")))
+    (fc-pattern-add pattern fc-font-name-property-family family)
+    (if style
+	(fc-pattern-add pattern fc-font-name-property-style style))
+    (mapcar
+     '(lambda (pattern)
+	(let ((fc-weight-constant (fc-pattern-get-weight pattern 0)))
+	  (if fc-weight-constant
+	      (fc-font-weight-translate-from-constant fc-weight-constant))))
+     (fc-list-fonts-pattern-objects device pattern objectset))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; The XLFD fontname UI
+;;
+
+;;   xlfd-font-name-p
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Utility functions
+;;
+
+(defun fc-pattern-get-successp (result)
+  (and (not (equal result 'fc-result-no-match))
+       (not (equal result 'fc-result-no-id))
+       (not (equal result 'fc-internal-error))))
+
+;;; DELETE-DUPLICATES and REMOVE-DUPLICATES from cl-seq.el do not
+;;; seem to work on list of strings...
+;;; #### Presumably just use :test 'equal!
+(defun fc-delete-duplicates (l)
+  (let ((res nil)
+	(in l))
+    (while (not (null in))
+      (if (not (member (car in) res))
+	  (setq res (append res (list (car in)))))
+      (setq in (cdr in)))
+    res))
+
+;; #### Use delete-if with :test 'equal.
+(defun fc-filter (l fun)
+  (let ((res nil)
+	(in l))
+    (while (not (null in))
+      (if (funcall fun (car in))
+	  (setq res (append res (list (car in)))))
+      (setq in (cdr in)))
+    res))
+
+(provide 'fontconfig)
+
+;;; fontconfig.el ends here