Mercurial > hg > xemacs-beta
annotate src/font-mgr.c @ 5589:851c741a15d0 pkg-docs
Close branch.
| author | Stephen J. Turnbull <stephen@xemacs.org> |
|---|---|
| date | Sat, 29 Oct 2011 17:08:25 +0900 |
| parents | dfd878799ef0 |
| children | a23ac8f90a49 |
| rev | line source |
|---|---|
| 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 DEFUN("fc-config-get-rescan-interval", Ffc_config_get_rescan_interval, 1, 1, 0, /* | |
|
4328
dfd878799ef0
Autoconfiscate the recent fontconfig spelling change.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3935
diff
changeset
|
902 -- Function: int FcConfigGetRescanInterval (FcConfig *config) |
| 3931 | 903 Returns the interval between automatic checks of the configuration |
| 904 (in seconds) specified in 'config'. The configuration is checked | |
| 905 during a call to FcFontList when this interval has passed since | |
| 906 the last check. */ | |
| 907 (config)) | |
| 908 { | |
| 909 CHECK_FCCONFIG (config); | |
|
4328
dfd878799ef0
Autoconfiscate the recent fontconfig spelling change.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3935
diff
changeset
|
910 return make_int (FcConfigGetRescanInterval (XFCCONFIG_PTR (config))); |
| 3931 | 911 } |
| 912 | |
| 913 DEFUN("fc-config-set-rescan-interval", Ffc_config_set_rescan_interval, 2, 2, 0, /* | |
|
4328
dfd878799ef0
Autoconfiscate the recent fontconfig spelling change.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3935
diff
changeset
|
914 -- Function: FcBool FcConfigSetRescanInterval (FcConfig *config, int |
| 3931 | 915 rescanInterval) |
| 916 Sets the rescan interval; returns FcFalse if an error occurred. | |
| 917 XEmacs: signal such error, or return nil on success. */ | |
| 918 (config, rescan_interval)) | |
| 919 { | |
| 920 CHECK_FCCONFIG (config); | |
| 921 CHECK_INT (rescan_interval); | |
|
4328
dfd878799ef0
Autoconfiscate the recent fontconfig spelling change.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3935
diff
changeset
|
922 if (FcConfigSetRescanInterval (XFCCONFIG_PTR (config), |
| 3931 | 923 XINT (rescan_interval)) == FcFalse) |
| 924 signal_error (Qio_error, "FcConfigSetRescanInverval barfed", | |
| 925 intern ("fc-config-set-rescan-interval")); | |
| 926 return Qnil; | |
| 927 } | |
| 928 | |
| 929 /* #### This might usefully be made interactive. */ | |
| 930 DEFUN("fc-config-app-font-add-file", Ffc_config_app_font_add_file, 2, 2, 0, /* | |
| 931 -- Function: FcBool FcConfigAppFontAddFile (FcConfig *config, const | |
| 932 char *file) | |
| 933 Adds an application-specific font to the configuration. */ | |
| 934 (config, file)) | |
| 935 { | |
| 936 CHECK_FCCONFIG (config); | |
| 937 CHECK_STRING (file); | |
| 938 if (FcConfigAppFontAddFile | |
| 939 (XFCCONFIG_PTR (config), | |
| 940 /* #### FIXME! is this really Qnative? */ | |
| 941 (FcChar8 *) NEW_LISP_STRING_TO_EXTERNAL ((file), Qnative)) == FcFalse) | |
| 942 return Qnil; | |
| 943 else | |
| 944 return Qt; | |
| 945 } | |
| 946 | |
| 947 /* #### This might usefully be made interactive. */ | |
| 948 DEFUN("fc-config-app-font-add-dir", Ffc_config_app_font_add_dir, 2, 2, 0, /* | |
| 949 -- Function: FcBool FcConfigAppFontAddDir (FcConfig *config, const | |
| 950 char *dir) | |
| 951 Scans the specified directory for fonts, adding each one found to | |
| 952 the application-specific set of fonts. */ | |
| 953 (config, dir)) | |
| 954 { | |
| 955 CHECK_FCCONFIG (config); | |
| 956 CHECK_STRING (dir); | |
| 957 if (FcConfigAppFontAddDir | |
| 958 (XFCCONFIG_PTR (config), | |
| 959 /* #### FIXME! is this really Qnative? */ | |
| 960 (FcChar8 *) NEW_LISP_STRING_TO_EXTERNAL ((dir), Qnative)) == FcFalse) | |
| 961 return Qnil; | |
| 962 else | |
| 963 return Qt; | |
| 964 } | |
| 965 | |
| 966 /* #### This might usefully be made interactive. */ | |
| 967 DEFUN("fc-config-app-font-clear", Ffc_config_app_font_clear, 1, 1, 0, /* | |
| 968 -- Function: void FcConfigAppFontClear (FcConfig *config) | |
| 969 Clears the set of application-specific fonts. */ | |
| 970 (config)) | |
| 971 { | |
| 972 CHECK_FCCONFIG (config); | |
| 973 FcConfigAppFontClear (XFCCONFIG_PTR (config)); | |
| 974 return Qnil; | |
| 975 } | |
| 976 | |
| 977 /* These functions provide some control over how the default | |
| 978 configuration of the library is initialized. (This configuration is | |
| 979 normally implicitly initialized.) */ | |
| 980 | |
| 981 DEFUN("fc-config-filename", Ffc_config_filename, 1, 1, 0, /* | |
| 982 -- Function: char *FcConfigFilename (const char *name) | |
| 983 Given the specified external entity name, return the associated | |
| 984 filename. This provides applications a way to convert various | |
| 985 configuration file references into filename form. | |
| 986 | |
| 987 A null or empty 'name' indicates that the default configuration | |
| 988 file should be used; which file this references can be overridden | |
| 989 with the FC_CONFIG_FILE environment variable. Next, if the name | |
| 990 starts with '~', it refers to a file in the current users home | |
| 991 directory. Otherwise if the name doesn't start with '/', it | |
| 992 refers to a file in the default configuration directory; the | |
| 993 built-in default directory can be overridden with the | |
| 994 FC_CONFIG_DIR environment variable. */ | |
| 995 (name)) | |
| 996 { | |
| 997 char *fcname = ""; | |
| 998 | |
| 999 if (!NILP (name)) | |
| 1000 { | |
| 1001 CHECK_STRING (name); | |
| 1002 /* #### FIXME! is this really Qnative? */ | |
| 1003 fcname = NEW_LISP_STRING_TO_EXTERNAL (name, Qnative); | |
| 1004 } | |
| 1005 return (build_fcapi_string (FcConfigFilename ((FcChar8 *) fcname))); | |
| 1006 } | |
| 1007 | |
| 1008 DEFUN("fc-init-load-config", Ffc_init_load_config, 0, 0, 0, /* | |
| 1009 -- Function: FcConfig *FcInitLoadConfig (void) | |
| 1010 Loads the default configuration file and returns the resulting | |
| 1011 configuration. Does not load any font information. */ | |
| 1012 ()) | |
| 1013 { | |
| 1014 return fc_config_create_using (&FcInitLoadConfig); | |
| 1015 } | |
| 1016 | |
| 1017 DEFUN("fc-init-load-config-and-fonts", Ffc_init_load_config_and_fonts, 0, 0, 0, /* | |
| 1018 -- Function: FcConfig *FcInitLoadConfigAndFonts (void) | |
| 1019 Loads the default configuration file and builds information about | |
| 1020 the available fonts. Returns the resulting configuration. */ | |
| 1021 ()) | |
| 1022 { | |
| 1023 return fc_config_create_using (&FcInitLoadConfigAndFonts); | |
| 1024 } | |
| 1025 | |
| 1026 DEFUN("fc-init", Ffc_init, 0, 0, 0, /* | |
| 1027 -- Function: FcBool FcInit (void) | |
| 1028 Loads the default configuration file and the fonts referenced | |
| 1029 therein and sets the default configuration to that result. | |
| 1030 Returns whether this process succeeded or not. If the default | |
| 1031 configuration has already been loaded, this routine does nothing | |
| 1032 and returns FcTrue. */ | |
| 1033 ()) | |
| 1034 { | |
| 1035 return (FcInit () == FcTrue) ? Qt : Qnil; | |
| 1036 } | |
| 1037 | |
| 1038 DEFUN("fc-get-version", Ffc_get_version, 0, 0, 0, /* | |
| 1039 -- Function: int FcGetVersion (void) | |
| 1040 Returns the version number of the library. | |
| 3935 | 1041 XEmacs: No, this should NOT return a pretty string. |
| 3931 | 1042 (let ((i (fc-get-version))) |
| 1043 (format "%d.%d.%d" (/ i 10000) (mod (/ i 100) 100) (mod i 100))) | |
| 3935 | 1044 gives the usual x.y.z format. This is the version of the .so. It can be |
| 1045 checked against `fc-version', which is the version of fontconfig.h. | |
| 1046 It's probably not a disaster if `(> (fc-get-version) fc-version)'. */ | |
| 3931 | 1047 ()) |
| 1048 { | |
| 1049 return make_int (FcGetVersion ()); | |
| 1050 } | |
| 1051 | |
| 1052 DEFUN("fc-init-reinitialize", Ffc_init_reinitialize, 0, 0, 0, /* | |
| 1053 -- Function: FcBool FcInitReinitialize (void) | |
| 1054 Forces the default configuration file to be reloaded and resets | |
| 1055 the default configuration. */ | |
| 1056 ()) | |
| 1057 { | |
| 1058 return (FcInitReinitialize () == FcTrue) ? Qt : Qnil; | |
| 1059 } | |
| 1060 | |
| 1061 DEFUN("fc-init-bring-up-to-date", Ffc_init_bring_up_to_date, 0, 0, 0, /* | |
| 1062 -- Function: FcBool FcInitBringUptoDate (void) | |
| 1063 Checks the rescan interval in the default configuration, checking | |
| 1064 the configuration if the interval has passed and reloading the | |
| 1065 configuration when any changes are detected. */ | |
| 1066 ()) | |
| 1067 { | |
| 1068 return (FcInitBringUptoDate () == FcTrue) ? Qt : Qnil; | |
| 1069 } | |
| 1070 | |
| 1071 #endif /* FONTCONFIG_EXPOSE_CONFIG */ | |
| 1072 | |
| 3354 | 1073 DEFUN("xlfd-font-name-p", Fxlfd_font_name_p, 1, 1, 0, /* |
| 1074 Check whether the string FONTNAME is a XLFD font name. */ | |
| 1075 (fontname)) | |
| 1076 { | |
| 1077 CHECK_STRING(fontname); | |
| 1078 /* #### should bind `case-fold-search' here? */ | |
| 1079 return Fstring_match(Vxlfd_font_name_regexp, fontname, Qnil, Qnil); | |
| 1080 } | |
| 1081 | |
| 1082 /* FcPatternPrint: there is no point in having wrappers fc-pattern-print, | |
| 1083 Ffc_pattern_print since this function prints to stdout. */ | |
| 1084 | |
| 1085 /* Initialization of font-mgr */ | |
| 1086 | |
| 1087 #define XE_XLFD_SEPARATOR "-" | |
| 1088 /* XLFD specifies ISO 8859-1 encoding, but we can't handle non-ASCII | |
| 1089 in Mule when this function is called. So use HPC. */ | |
| 1090 #if 0 | |
| 1091 #define XE_XLFD_PREFIX "\\(\\+[\040-\176\240-\377]*\\)?-" | |
| 1092 #define XE_XLFD_OPT_TEXT "\\([\040-\044\046-\176\240-\377]*\\)" | |
| 1093 #define XE_XLFD_TEXT "\\([\040-\044\046-\176\240-\377]+\\)" | |
| 1094 #else | |
| 1095 #define XE_XLFD_PREFIX "\\(\\+[\040-\176]*\\)?-" | |
| 1096 #define XE_XLFD_OPT_TEXT "\\([^-]*\\)" | |
| 1097 #define XE_XLFD_TEXT "\\([^-]+\\)" | |
| 1098 #endif | |
| 1099 | |
| 1100 #define XE_XLFD_SLANT "\\([0-9ior?*][iot]?\\)" | |
| 1101 #define XE_XLFD_SPACING "\\([cmp?*]\\)" | |
| 1102 /* Hyphen as minus conflicts with use as separator. */ | |
| 1103 #define XE_XLFD_OPT_NEGATE "~?" | |
| 1104 #define XE_XLFD_NUMBER "\\([0-9?*]+\\)" | |
| 1105 #define XE_XLFD_PSIZE "\\([0-9?*]+\\|\\[[ 0-9+~.e?*]+\\]\\)" | |
| 1106 | |
| 1107 /* Call this only from the init code | |
| 1108 #### This is really horrible, let's get rid of it, please. */ | |
| 1109 static Lisp_Object | |
| 1110 make_xlfd_font_regexp (void) | |
| 1111 { | |
| 1112 struct gcpro gcpro1; | |
| 1113 unsigned i; | |
| 1114 Lisp_Object reg = Qnil; | |
| 1115 const Extbyte *re[] = /* #### This could just be catenated by | |
| 1116 cpp and passed to build_ext_string. */ | |
| 1117 { | |
| 1118 /* Regular expression matching XLFDs as defined by XLFD v. 1.5. | |
| 1119 Matches must be case-insensitive. | |
| 1120 PSIZE is a pixel or point size, which may be a "matrix". The | |
| 1121 syntax of a matrix is not checked, just some lexical properties. | |
| 1122 AFAICT none of the TEXT fields except adstyle is optional. | |
| 1123 | |
| 1124 NB. It should not be a problem if this matches "too much", since | |
| 1125 an "old" server will simply not be able to find a matching font. */ | |
| 1126 "\\`", | |
| 1127 XE_XLFD_PREFIX, /* prefix */ | |
| 1128 XE_XLFD_TEXT, /* foundry */ | |
| 1129 XE_XLFD_SEPARATOR, | |
| 1130 XE_XLFD_TEXT, /* family */ | |
| 1131 XE_XLFD_SEPARATOR, | |
| 1132 XE_XLFD_TEXT, /* weight */ | |
| 1133 XE_XLFD_SEPARATOR, | |
| 1134 XE_XLFD_SLANT, /* slant */ | |
| 1135 XE_XLFD_SEPARATOR, | |
| 1136 XE_XLFD_TEXT, /* swidth */ | |
| 1137 XE_XLFD_SEPARATOR, | |
| 1138 XE_XLFD_OPT_TEXT, /* adstyle */ | |
| 1139 XE_XLFD_SEPARATOR, | |
| 1140 XE_XLFD_PSIZE, /* pixelsize */ | |
| 1141 XE_XLFD_SEPARATOR, | |
| 1142 XE_XLFD_PSIZE, /* pointsize */ | |
| 1143 XE_XLFD_SEPARATOR, | |
| 1144 XE_XLFD_NUMBER, /* resx */ | |
| 1145 XE_XLFD_SEPARATOR, | |
| 1146 XE_XLFD_NUMBER, /* resy */ | |
| 1147 XE_XLFD_SEPARATOR, | |
| 1148 XE_XLFD_SPACING, /* spacing */ | |
| 1149 XE_XLFD_SEPARATOR, | |
| 1150 XE_XLFD_OPT_NEGATE, /* avgwidth */ | |
| 1151 XE_XLFD_NUMBER, | |
| 1152 XE_XLFD_SEPARATOR, | |
| 1153 XE_XLFD_TEXT, /* registry */ | |
| 1154 XE_XLFD_SEPARATOR, | |
| 1155 XE_XLFD_TEXT, /* encoding */ | |
| 1156 "\\'" | |
| 1157 }; | |
| 1158 | |
| 1159 GCPRO1 (reg); | |
| 1160 for (i = 0; i < sizeof(re)/sizeof(Extbyte *); i++) | |
| 1161 { | |
| 1162 /* #### Currently this is Host Portable Coding, not ISO 8859-1. */ | |
| 1163 reg = concat2(reg, build_ext_string (re[i], Qx_font_name_encoding)); | |
| 1164 } | |
| 1165 | |
| 1166 RETURN_UNGCPRO (reg); | |
| 1167 } | |
| 1168 #undef XE_XLFD_SEPARATOR | |
| 1169 #undef XE_XLFD_PREFIX | |
| 1170 #undef XE_XLFD_OPT_TEXT | |
| 1171 #undef XE_XLFD_TEXT | |
| 1172 #undef XE_XLFD_OPT_SLANT | |
| 1173 #undef XE_XLFD_OPT_SPACING | |
| 1174 #undef XE_XLFD_OPT_NEGATE | |
| 1175 #undef XE_XLFD_NUMBER | |
| 1176 #undef XE_XLFD_PSIZE | |
| 1177 | |
| 1178 #define MINL(x,y) ((((unsigned long) (x)) < ((unsigned long) (y))) \ | |
| 1179 ? ((unsigned long) (x)) : ((unsigned long) (y))) | |
| 1180 | |
| 1181 static void | |
| 1182 string_list_to_fcobjectset (Lisp_Object list, FcObjectSet *os) | |
| 1183 { | |
| 1184 EXTERNAL_LIST_LOOP_2 (elt, list) | |
| 1185 { | |
| 3469 | 1186 const Extbyte *s; |
| 3354 | 1187 |
| 1188 CHECK_STRING (elt); | |
| 1189 s = fc_intern (elt); | |
| 1190 FcObjectSetAdd (os, s); | |
| 1191 } | |
| 1192 } | |
| 1193 | |
| 1194 void | |
| 1195 syms_of_font_mgr (void) | |
| 1196 { | |
| 1197 INIT_LRECORD_IMPLEMENTATION(fc_pattern); | |
| 1198 | |
| 1199 DEFSYMBOL_MULTIWORD_PREDICATE(Qfc_patternp); | |
| 1200 | |
| 1201 DEFSYMBOL(Qfc_result_type_mismatch); | |
| 1202 DEFSYMBOL(Qfc_result_no_match); | |
| 1203 DEFSYMBOL(Qfc_result_no_id); | |
| 1204 DEFSYMBOL(Qfc_internal_error); | |
| 3360 | 1205 DEFSYMBOL(Qfont_mgr); |
| 3354 | 1206 |
| 1207 DEFSUBR(Ffc_pattern_p); | |
| 1208 DEFSUBR(Ffc_pattern_create); | |
| 1209 DEFSUBR(Ffc_name_parse); | |
| 1210 DEFSUBR(Ffc_name_unparse); | |
| 1211 DEFSUBR(Ffc_pattern_duplicate); | |
| 1212 DEFSUBR(Ffc_pattern_add); | |
| 1213 DEFSUBR(Ffc_pattern_del); | |
| 1214 DEFSUBR(Ffc_pattern_get); | |
| 1215 DEFSUBR(Ffc_list_fonts_pattern_objects); | |
| 1216 DEFSUBR(Ffc_font_sort); | |
| 1217 DEFSUBR(Ffc_font_match); | |
| 1218 DEFSUBR(Fxlfd_font_name_p); | |
| 3931 | 1219 |
| 1220 #ifdef FONTCONFIG_EXPOSE_CONFIG | |
| 1221 INIT_LRECORD_IMPLEMENTATION(fc_config); | |
| 1222 | |
| 1223 DEFSYMBOL_MULTIWORD_PREDICATE(Qfc_configp); | |
| 1224 | |
| 1225 DEFSUBR(Ffc_config_p); | |
| 1226 DEFSUBR(Ffc_config_create); | |
| 1227 #if 0 | |
| 1228 DEFSUBR(Ffc_config_destroy); | |
| 1229 #endif | |
| 1230 DEFSUBR(Ffc_config_set_current); | |
| 1231 DEFSUBR(Ffc_config_get_current); | |
| 1232 DEFSUBR(Ffc_config_up_to_date); | |
| 1233 DEFSUBR(Ffc_config_build_fonts); | |
| 1234 DEFSUBR(Ffc_config_get_config_dirs); | |
| 1235 DEFSUBR(Ffc_config_get_font_dirs); | |
| 1236 DEFSUBR(Ffc_config_get_config_files); | |
| 1237 DEFSUBR(Ffc_config_get_cache); | |
| 1238 DEFSUBR(Ffc_config_get_fonts); | |
| 1239 DEFSUBR(Ffc_config_get_blanks); | |
| 1240 DEFSUBR(Ffc_config_get_rescan_interval); | |
| 1241 DEFSUBR(Ffc_config_set_rescan_interval); | |
| 1242 DEFSUBR(Ffc_config_app_font_add_file); | |
| 1243 DEFSUBR(Ffc_config_app_font_add_dir); | |
| 1244 DEFSUBR(Ffc_config_app_font_clear); | |
| 1245 DEFSUBR(Ffc_config_filename); | |
| 1246 DEFSUBR(Ffc_init_load_config); | |
| 1247 DEFSUBR(Ffc_init_load_config_and_fonts); | |
| 1248 DEFSUBR(Ffc_init); | |
| 1249 DEFSUBR(Ffc_get_version); | |
| 1250 DEFSUBR(Ffc_init_reinitialize); | |
| 1251 DEFSUBR(Ffc_init_bring_up_to_date); | |
| 1252 #endif /* FONTCONFIG_EXPOSE_CONFIG */ | |
| 3354 | 1253 } |
| 1254 | |
| 1255 void | |
| 1256 vars_of_font_mgr (void) | |
| 1257 { | |
| 3935 | 1258 /* #### The next two DEFVARs belong somewhere else. */ |
| 3354 | 1259 |
| 1260 /* #### I know, but the right fix is use the generic debug facility. */ | |
| 1261 DEFVAR_INT ("xft-debug-level", &debug_xft /* | |
| 1262 Level of debugging messages to issue to stderr for Xft. | |
| 1263 A nonnegative integer. Set to 0 to suppress all warnings. | |
| 1264 Default is 1 to ensure a minimum of debugging output at initialization. | |
| 1265 Higher levels give even more information. | |
| 1266 */ ); | |
| 1267 debug_xft = 1; | |
| 1268 | |
| 3935 | 1269 DEFVAR_CONST_INT("xft-version", &xft_version /* |
| 3354 | 1270 The major version number of the Xft library being used. |
| 1271 */ ); | |
| 3935 | 1272 xft_version = XFT_VERSION; |
| 1273 | |
| 1274 DEFVAR_CONST_INT("fc-version", &fc_version /* | |
| 1275 The version number of fontconfig.h. It can be checked against | |
| 1276 `(fc-get-version)', which is the version of the .so. | |
| 1277 It's probably not a disaster if `(> (fc-get-version) fc-version)'. | |
| 1278 */ ); | |
| 1279 fc_version = FC_VERSION; | |
| 3354 | 1280 |
| 3360 | 1281 Fprovide (intern ("font-mgr")); |
| 3354 | 1282 } |
| 1283 | |
| 1284 void | |
| 1285 complex_vars_of_font_mgr (void) | |
| 1286 { | |
| 3931 | 1287 #ifdef FONTCONFIG_EXPOSE_CONFIG |
| 1288 Vfc_config_weak_list = make_weak_list (WEAK_LIST_SIMPLE); | |
| 1289 staticpro (&Vfc_config_weak_list); | |
| 1290 #endif | |
| 1291 | |
| 3354 | 1292 DEFVAR_LISP("xft-xlfd-font-regexp", &Vxlfd_font_name_regexp /* |
| 1293 The regular expression used to match XLFD font names. */ | |
| 1294 ); | |
| 1295 Vxlfd_font_name_regexp = make_xlfd_font_regexp(); | |
| 1296 } | |
| 1297 | |
| 1298 void | |
| 1299 reinit_vars_of_font_mgr (void) | |
| 1300 { | |
| 1301 int i, size = (int) countof (fc_standard_properties); | |
| 1302 | |
| 1303 FcInit (); | |
| 1304 | |
| 1305 fc_property_name_hash_table = make_string_hash_table (size); | |
| 1306 for (i = 0; i < size; ++i) | |
| 1307 puthash (fc_standard_properties[i], NULL, fc_property_name_hash_table); | |
| 1308 } | |
| 1309 |
