xftdpy.c revision 0d590c07
1c76ae52dSmrg/* 2c76ae52dSmrg * Copyright © 2000 Keith Packard 3c76ae52dSmrg * 4c76ae52dSmrg * Permission to use, copy, modify, distribute, and sell this software and its 5c76ae52dSmrg * documentation for any purpose is hereby granted without fee, provided that 6c76ae52dSmrg * the above copyright notice appear in all copies and that both that 7c76ae52dSmrg * copyright notice and this permission notice appear in supporting 8c76ae52dSmrg * documentation, and that the name of Keith Packard not be used in 9c76ae52dSmrg * advertising or publicity pertaining to distribution of the software without 10c76ae52dSmrg * specific, written prior permission. Keith Packard makes no 11c76ae52dSmrg * representations about the suitability of this software for any purpose. It 12c76ae52dSmrg * is provided "as is" without express or implied warranty. 13c76ae52dSmrg * 14c76ae52dSmrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15c76ae52dSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16c76ae52dSmrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17c76ae52dSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18c76ae52dSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19c76ae52dSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20c76ae52dSmrg * PERFORMANCE OF THIS SOFTWARE. 21c76ae52dSmrg */ 22c76ae52dSmrg 23c76ae52dSmrg#include "xftint.h" 24c76ae52dSmrg 25c76ae52dSmrg_X_HIDDEN XftDisplayInfo *_XftDisplayInfo; 26c76ae52dSmrg 27c76ae52dSmrgstatic int 28c76ae52dSmrg_XftCloseDisplay (Display *dpy, XExtCodes *codes) 29c76ae52dSmrg{ 30c76ae52dSmrg XftDisplayInfo *info, **prev; 31c76ae52dSmrg 32c76ae52dSmrg info = _XftDisplayInfoGet (dpy, FcFalse); 33c76ae52dSmrg if (!info) 34c76ae52dSmrg return 0; 35c76ae52dSmrg 36c76ae52dSmrg /* 37c76ae52dSmrg * Get rid of any dangling unreferenced fonts 38c76ae52dSmrg */ 39c76ae52dSmrg info->max_unref_fonts = 0; 40c76ae52dSmrg XftFontManageMemory (dpy); 41c76ae52dSmrg 42c76ae52dSmrg /* 43c76ae52dSmrg * Clean up the default values 44c76ae52dSmrg */ 45c76ae52dSmrg if (info->defaults) 46c76ae52dSmrg FcPatternDestroy (info->defaults); 47c76ae52dSmrg 48c76ae52dSmrg /* 49c76ae52dSmrg * Unhook from the global list 50c76ae52dSmrg */ 51c76ae52dSmrg for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next) 52c76ae52dSmrg if (info->display == dpy) 53c76ae52dSmrg break; 54c76ae52dSmrg *prev = info->next; 55c76ae52dSmrg 56c76ae52dSmrg free (info); 57c76ae52dSmrg return 0; 58c76ae52dSmrg} 59c76ae52dSmrg 60c76ae52dSmrg 61c76ae52dSmrg_X_HIDDEN XftDisplayInfo * 62c76ae52dSmrg_XftDisplayInfoGet (Display *dpy, FcBool createIfNecessary) 63c76ae52dSmrg{ 64c76ae52dSmrg XftDisplayInfo *info, **prev; 65c76ae52dSmrg XRenderPictFormat pf; 66c76ae52dSmrg int i; 67c76ae52dSmrg int event_base, error_base; 68c76ae52dSmrg 69c76ae52dSmrg for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next) 70c76ae52dSmrg { 71c76ae52dSmrg if (info->display == dpy) 72c76ae52dSmrg { 73c76ae52dSmrg /* 74c76ae52dSmrg * MRU the list 75c76ae52dSmrg */ 76c76ae52dSmrg if (prev != &_XftDisplayInfo) 77c76ae52dSmrg { 78c76ae52dSmrg *prev = info->next; 79c76ae52dSmrg info->next = _XftDisplayInfo; 80c76ae52dSmrg _XftDisplayInfo = info; 81c76ae52dSmrg } 82c76ae52dSmrg return info; 83c76ae52dSmrg } 84c76ae52dSmrg } 85c76ae52dSmrg if (!createIfNecessary) 860d590c07Smrg return NULL; 87c76ae52dSmrg 88c76ae52dSmrg info = (XftDisplayInfo *) malloc (sizeof (XftDisplayInfo)); 89c76ae52dSmrg if (!info) 90c76ae52dSmrg goto bail0; 91c76ae52dSmrg info->codes = XAddExtension (dpy); 92c76ae52dSmrg if (!info->codes) 93c76ae52dSmrg goto bail1; 94c76ae52dSmrg (void) XESetCloseDisplay (dpy, info->codes->extension, _XftCloseDisplay); 95c76ae52dSmrg 96c76ae52dSmrg info->display = dpy; 970d590c07Smrg info->defaults = NULL; 980d590c07Smrg info->solidFormat = NULL; 99c76ae52dSmrg info->hasRender = (XRenderQueryExtension (dpy, &event_base, &error_base) && 1000d590c07Smrg (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != NULL)); 101c76ae52dSmrg info->use_free_glyphs = FcTrue; 102c76ae52dSmrg if (info->hasRender) 103c76ae52dSmrg { 104c76ae52dSmrg int major, minor; 105c76ae52dSmrg XRenderQueryVersion (dpy, &major, &minor); 106c76ae52dSmrg if (major < 0 || (major == 0 && minor <= 2)) 107c76ae52dSmrg info->use_free_glyphs = FcFalse; 108c76ae52dSmrg 109c76ae52dSmrg pf.type = PictTypeDirect; 110c76ae52dSmrg pf.depth = 32; 111c76ae52dSmrg pf.direct.redMask = 0xff; 112c76ae52dSmrg pf.direct.greenMask = 0xff; 113c76ae52dSmrg pf.direct.blueMask = 0xff; 114c76ae52dSmrg pf.direct.alphaMask = 0xff; 115c76ae52dSmrg info->solidFormat = XRenderFindFormat (dpy, 116c76ae52dSmrg (PictFormatType| 117c76ae52dSmrg PictFormatDepth| 118c76ae52dSmrg PictFormatRedMask| 119c76ae52dSmrg PictFormatGreenMask| 120c76ae52dSmrg PictFormatBlueMask| 121c76ae52dSmrg PictFormatAlphaMask), 122c76ae52dSmrg &pf, 123c76ae52dSmrg 0); 124c76ae52dSmrg } 125c76ae52dSmrg if (XftDebug () & XFT_DBG_RENDER) 126c76ae52dSmrg { 127c76ae52dSmrg Visual *visual = DefaultVisual (dpy, DefaultScreen (dpy)); 128c76ae52dSmrg XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 129c76ae52dSmrg 130c76ae52dSmrg printf ("XftDisplayInfoGet Default visual 0x%x ", 131c76ae52dSmrg (int) visual->visualid); 132c76ae52dSmrg if (format) 133c76ae52dSmrg { 134c76ae52dSmrg if (format->type == PictTypeDirect) 135c76ae52dSmrg { 136c76ae52dSmrg printf ("format %d,%d,%d,%d\n", 137c76ae52dSmrg format->direct.alpha, 138c76ae52dSmrg format->direct.red, 139c76ae52dSmrg format->direct.green, 140c76ae52dSmrg format->direct.blue); 141c76ae52dSmrg } 142c76ae52dSmrg else 143c76ae52dSmrg { 144c76ae52dSmrg printf ("format indexed\n"); 145c76ae52dSmrg } 146c76ae52dSmrg } 147c76ae52dSmrg else 148c76ae52dSmrg printf ("No Render format for default visual\n"); 149c76ae52dSmrg 150c76ae52dSmrg printf ("XftDisplayInfoGet initialized, hasRender set to \"%s\"\n", 151c76ae52dSmrg info->hasRender ? "True" : "False"); 152c76ae52dSmrg } 153c76ae52dSmrg for (i = 0; i < XFT_NUM_SOLID_COLOR; i++) 154c76ae52dSmrg { 155c76ae52dSmrg info->colors[i].screen = -1; 156c76ae52dSmrg info->colors[i].pict = 0; 157c76ae52dSmrg } 1580d590c07Smrg info->fonts = NULL; 159c76ae52dSmrg 160c76ae52dSmrg info->next = _XftDisplayInfo; 161c76ae52dSmrg _XftDisplayInfo = info; 1620d590c07Smrg 1630d590c07Smrg info->glyph_memory = NULL; 164c76ae52dSmrg info->max_glyph_memory = XftDefaultGetInteger (dpy, 165c76ae52dSmrg XFT_MAX_GLYPH_MEMORY, 0, 166c76ae52dSmrg XFT_DPY_MAX_GLYPH_MEMORY); 167c76ae52dSmrg if (XftDebug () & XFT_DBG_CACHE) 168c76ae52dSmrg printf ("global max cache memory %ld\n", info->max_glyph_memory); 169c76ae52dSmrg 170c76ae52dSmrg 171c76ae52dSmrg info->num_unref_fonts = 0; 172c76ae52dSmrg info->max_unref_fonts = XftDefaultGetInteger (dpy, 173c76ae52dSmrg XFT_MAX_UNREF_FONTS, 0, 174c76ae52dSmrg XFT_DPY_MAX_UNREF_FONTS); 175c76ae52dSmrg if (XftDebug() & XFT_DBG_CACHE) 176c76ae52dSmrg printf ("global max unref fonts %d\n", info->max_unref_fonts); 177c76ae52dSmrg 178c76ae52dSmrg memset (info->fontHash, '\0', sizeof (XftFont *) * XFT_NUM_FONT_HASH); 179c76ae52dSmrg return info; 180c76ae52dSmrg 181c76ae52dSmrgbail1: 182c76ae52dSmrg free (info); 183c76ae52dSmrgbail0: 184c76ae52dSmrg if (XftDebug () & XFT_DBG_RENDER) 185c76ae52dSmrg { 186c76ae52dSmrg printf ("XftDisplayInfoGet failed to initialize, Xft unhappy\n"); 187c76ae52dSmrg } 1880d590c07Smrg return NULL; 189c76ae52dSmrg} 190c76ae52dSmrg 191c76ae52dSmrg/* 192c76ae52dSmrg * Reduce memory usage in X server 193c76ae52dSmrg */ 194c76ae52dSmrg 195c76ae52dSmrgstatic void 196c76ae52dSmrg_XftDisplayValidateMemory (XftDisplayInfo *info) 197c76ae52dSmrg{ 198c76ae52dSmrg XftFont *public; 199c76ae52dSmrg XftFontInt *font; 200c76ae52dSmrg unsigned long glyph_memory; 201c76ae52dSmrg 202c76ae52dSmrg glyph_memory = 0; 203c76ae52dSmrg for (public = info->fonts; public; public = font->next) 204c76ae52dSmrg { 205c76ae52dSmrg font = (XftFontInt *) public; 206c76ae52dSmrg glyph_memory += font->glyph_memory; 207c76ae52dSmrg } 208c76ae52dSmrg if (glyph_memory != info->glyph_memory) 209c76ae52dSmrg printf ("Display glyph cache incorrect has %ld bytes, should have %ld\n", 210c76ae52dSmrg info->glyph_memory, glyph_memory); 211c76ae52dSmrg} 212c76ae52dSmrg 213c76ae52dSmrg_X_HIDDEN void 214c76ae52dSmrg_XftDisplayManageMemory (Display *dpy) 215c76ae52dSmrg{ 216c76ae52dSmrg XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False); 217c76ae52dSmrg unsigned long glyph_memory; 218c76ae52dSmrg XftFont *public; 219c76ae52dSmrg XftFontInt *font; 220c76ae52dSmrg 221c76ae52dSmrg if (!info || !info->max_glyph_memory) 222c76ae52dSmrg return; 223c76ae52dSmrg if (XftDebug () & XFT_DBG_CACHE) 224c76ae52dSmrg { 225c76ae52dSmrg if (info->glyph_memory > info->max_glyph_memory) 226c76ae52dSmrg printf ("Reduce global memory from %ld to %ld\n", 227c76ae52dSmrg info->glyph_memory, info->max_glyph_memory); 228c76ae52dSmrg _XftDisplayValidateMemory (info); 229c76ae52dSmrg } 230c76ae52dSmrg while (info->glyph_memory > info->max_glyph_memory) 231c76ae52dSmrg { 232c76ae52dSmrg glyph_memory = rand () % info->glyph_memory; 233c76ae52dSmrg public = info->fonts; 234c76ae52dSmrg while (public) 235c76ae52dSmrg { 236c76ae52dSmrg font = (XftFontInt *) public; 237c76ae52dSmrg 238c76ae52dSmrg if (font->glyph_memory > glyph_memory) 239c76ae52dSmrg { 240c76ae52dSmrg _XftFontUncacheGlyph (dpy, public); 241c76ae52dSmrg break; 242c76ae52dSmrg } 243c76ae52dSmrg public = font->next; 244c76ae52dSmrg glyph_memory -= font->glyph_memory; 245c76ae52dSmrg } 246c76ae52dSmrg } 247c76ae52dSmrg if (XftDebug () & XFT_DBG_CACHE) 248c76ae52dSmrg _XftDisplayValidateMemory (info); 249c76ae52dSmrg} 250c76ae52dSmrg 251c76ae52dSmrg_X_EXPORT Bool 252c76ae52dSmrgXftDefaultHasRender (Display *dpy) 253c76ae52dSmrg{ 254c76ae52dSmrg XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); 255c76ae52dSmrg 256c76ae52dSmrg if (!info) 257c76ae52dSmrg return False; 258c76ae52dSmrg return info->hasRender; 259c76ae52dSmrg} 260c76ae52dSmrg 261c76ae52dSmrg_X_EXPORT Bool 262c76ae52dSmrgXftDefaultSet (Display *dpy, FcPattern *defaults) 263c76ae52dSmrg{ 264c76ae52dSmrg XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); 265c76ae52dSmrg 266c76ae52dSmrg if (!info) 267c76ae52dSmrg return False; 268c76ae52dSmrg if (info->defaults) 269c76ae52dSmrg FcPatternDestroy (info->defaults); 270c76ae52dSmrg info->defaults = defaults; 271c76ae52dSmrg if (!info->max_glyph_memory) 272c76ae52dSmrg info->max_glyph_memory = XFT_DPY_MAX_GLYPH_MEMORY; 273c76ae52dSmrg info->max_glyph_memory = XftDefaultGetInteger (dpy, 274c76ae52dSmrg XFT_MAX_GLYPH_MEMORY, 0, 275c76ae52dSmrg info->max_glyph_memory); 276c76ae52dSmrg if (!info->max_unref_fonts) 277c76ae52dSmrg info->max_unref_fonts = XFT_DPY_MAX_UNREF_FONTS; 278c76ae52dSmrg info->max_unref_fonts = XftDefaultGetInteger (dpy, 279c76ae52dSmrg XFT_MAX_UNREF_FONTS, 0, 280c76ae52dSmrg info->max_unref_fonts); 281c76ae52dSmrg return True; 282c76ae52dSmrg} 283c76ae52dSmrg 284c76ae52dSmrg_X_HIDDEN int 285c76ae52dSmrgXftDefaultParseBool (char *v) 286c76ae52dSmrg{ 287c76ae52dSmrg char c0, c1; 288c76ae52dSmrg 289c76ae52dSmrg c0 = *v; 290c76ae52dSmrg if (isupper ((int)c0)) 291c76ae52dSmrg c0 = tolower (c0); 292c76ae52dSmrg if (c0 == 't' || c0 == 'y' || c0 == '1') 293c76ae52dSmrg return 1; 294c76ae52dSmrg if (c0 == 'f' || c0 == 'n' || c0 == '0') 295c76ae52dSmrg return 0; 296c76ae52dSmrg if (c0 == 'o') 297c76ae52dSmrg { 298c76ae52dSmrg c1 = v[1]; 299c76ae52dSmrg if (isupper ((int)c1)) 300c76ae52dSmrg c1 = tolower (c1); 301c76ae52dSmrg if (c1 == 'n') 302c76ae52dSmrg return 1; 303c76ae52dSmrg if (c1 == 'f') 304c76ae52dSmrg return 0; 305c76ae52dSmrg } 306c76ae52dSmrg return -1; 307c76ae52dSmrg} 308c76ae52dSmrg 309c76ae52dSmrgstatic Bool 310c76ae52dSmrg_XftDefaultInitBool (Display *dpy, FcPattern *pat, char *option) 311c76ae52dSmrg{ 312c76ae52dSmrg char *v; 313c76ae52dSmrg int i; 314c76ae52dSmrg 315c76ae52dSmrg v = XGetDefault (dpy, "Xft", option); 316c76ae52dSmrg if (v && (i = XftDefaultParseBool (v)) >= 0) 317c76ae52dSmrg return FcPatternAddBool (pat, option, i != 0); 318c76ae52dSmrg return True; 319c76ae52dSmrg} 320c76ae52dSmrg 321c76ae52dSmrgstatic Bool 322c76ae52dSmrg_XftDefaultInitDouble (Display *dpy, FcPattern *pat, char *option) 323c76ae52dSmrg{ 324c76ae52dSmrg char *v, *e; 325c76ae52dSmrg double d; 326c76ae52dSmrg 327c76ae52dSmrg v = XGetDefault (dpy, "Xft", option); 328c76ae52dSmrg if (v) 329c76ae52dSmrg { 330c76ae52dSmrg d = strtod (v, &e); 331c76ae52dSmrg if (e != v) 332c76ae52dSmrg return FcPatternAddDouble (pat, option, d); 333c76ae52dSmrg } 334c76ae52dSmrg return True; 335c76ae52dSmrg} 336c76ae52dSmrg 337c76ae52dSmrgstatic Bool 338c76ae52dSmrg_XftDefaultInitInteger (Display *dpy, FcPattern *pat, char *option) 339c76ae52dSmrg{ 340c76ae52dSmrg char *v, *e; 341c76ae52dSmrg int i; 342c76ae52dSmrg 343c76ae52dSmrg v = XGetDefault (dpy, "Xft", option); 344c76ae52dSmrg if (v) 345c76ae52dSmrg { 346c76ae52dSmrg if (FcNameConstant ((FcChar8 *) v, &i)) 347c76ae52dSmrg return FcPatternAddInteger (pat, option, i); 348c76ae52dSmrg i = strtol (v, &e, 0); 349c76ae52dSmrg if (e != v) 350c76ae52dSmrg return FcPatternAddInteger (pat, option, i); 351c76ae52dSmrg } 352c76ae52dSmrg return True; 353c76ae52dSmrg} 354c76ae52dSmrg 355c76ae52dSmrgstatic FcPattern * 356c76ae52dSmrg_XftDefaultInit (Display *dpy) 357c76ae52dSmrg{ 358c76ae52dSmrg FcPattern *pat; 359c76ae52dSmrg 360c76ae52dSmrg pat = FcPatternCreate (); 361c76ae52dSmrg if (!pat) 362c76ae52dSmrg goto bail0; 363c76ae52dSmrg 364c76ae52dSmrg if (!_XftDefaultInitDouble (dpy, pat, FC_SCALE)) 365c76ae52dSmrg goto bail1; 366c76ae52dSmrg if (!_XftDefaultInitDouble (dpy, pat, FC_DPI)) 367c76ae52dSmrg goto bail1; 368c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, XFT_RENDER)) 369c76ae52dSmrg goto bail1; 370c76ae52dSmrg if (!_XftDefaultInitInteger (dpy, pat, FC_RGBA)) 371c76ae52dSmrg goto bail1; 372c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, FC_ANTIALIAS)) 373c76ae52dSmrg goto bail1; 374c76ae52dSmrg#ifdef FC_EMBOLDEN 375c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, FC_EMBOLDEN)) 376c76ae52dSmrg goto bail1; 377c76ae52dSmrg#endif 378c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, FC_AUTOHINT)) 379c76ae52dSmrg goto bail1; 380c76ae52dSmrg#ifdef FC_HINT_STYLE 381c76ae52dSmrg if (!_XftDefaultInitInteger (dpy, pat, FC_HINT_STYLE)) 382c76ae52dSmrg goto bail1; 383c76ae52dSmrg#endif 384c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, FC_HINTING)) 385c76ae52dSmrg goto bail1; 386c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, FC_MINSPACE)) 387c76ae52dSmrg goto bail1; 388c76ae52dSmrg if (!_XftDefaultInitInteger (dpy, pat, XFT_MAX_GLYPH_MEMORY)) 389c76ae52dSmrg goto bail1; 390c76ae52dSmrg 391c76ae52dSmrg return pat; 392c76ae52dSmrg 393c76ae52dSmrgbail1: 394c76ae52dSmrg FcPatternDestroy (pat); 395c76ae52dSmrgbail0: 3960d590c07Smrg return NULL; 397c76ae52dSmrg} 398c76ae52dSmrg 399c76ae52dSmrgstatic FcResult 400c76ae52dSmrg_XftDefaultGet (Display *dpy, const char *object, int screen, FcValue *v) 401c76ae52dSmrg{ 402c76ae52dSmrg XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); 403c76ae52dSmrg FcResult r; 404c76ae52dSmrg 405c76ae52dSmrg if (!info) 406c76ae52dSmrg return FcResultNoMatch; 407c76ae52dSmrg 408c76ae52dSmrg if (!info->defaults) 409c76ae52dSmrg { 410c76ae52dSmrg info->defaults = _XftDefaultInit (dpy); 411c76ae52dSmrg if (!info->defaults) 412c76ae52dSmrg return FcResultNoMatch; 413c76ae52dSmrg } 414c76ae52dSmrg r = FcPatternGet (info->defaults, object, screen, v); 415c76ae52dSmrg if (r == FcResultNoId && screen > 0) 416c76ae52dSmrg r = FcPatternGet (info->defaults, object, 0, v); 417c76ae52dSmrg return r; 418c76ae52dSmrg} 419c76ae52dSmrg 420c76ae52dSmrg_X_HIDDEN Bool 421c76ae52dSmrgXftDefaultGetBool (Display *dpy, const char *object, int screen, Bool def) 422c76ae52dSmrg{ 423c76ae52dSmrg FcResult r; 424c76ae52dSmrg FcValue v; 425c76ae52dSmrg 426c76ae52dSmrg r = _XftDefaultGet (dpy, object, screen, &v); 427c76ae52dSmrg if (r != FcResultMatch || v.type != FcTypeBool) 428c76ae52dSmrg return def; 429c76ae52dSmrg return v.u.b; 430c76ae52dSmrg} 431c76ae52dSmrg 432c76ae52dSmrg_X_HIDDEN int 433c76ae52dSmrgXftDefaultGetInteger (Display *dpy, const char *object, int screen, int def) 434c76ae52dSmrg{ 435c76ae52dSmrg FcResult r; 436c76ae52dSmrg FcValue v; 437c76ae52dSmrg 438c76ae52dSmrg r = _XftDefaultGet (dpy, object, screen, &v); 439c76ae52dSmrg if (r != FcResultMatch || v.type != FcTypeInteger) 440c76ae52dSmrg return def; 441c76ae52dSmrg return v.u.i; 442c76ae52dSmrg} 443c76ae52dSmrg 444c76ae52dSmrg_X_HIDDEN double 445c76ae52dSmrgXftDefaultGetDouble (Display *dpy, const char *object, int screen, double def) 446c76ae52dSmrg{ 447c76ae52dSmrg FcResult r; 448c76ae52dSmrg FcValue v; 449c76ae52dSmrg 450c76ae52dSmrg r = _XftDefaultGet (dpy, object, screen, &v); 451c76ae52dSmrg if (r != FcResultMatch || v.type != FcTypeDouble) 452c76ae52dSmrg return def; 453c76ae52dSmrg return v.u.d; 454c76ae52dSmrg} 455c76ae52dSmrg 456c76ae52dSmrg_X_EXPORT void 457c76ae52dSmrgXftDefaultSubstitute (Display *dpy, int screen, FcPattern *pattern) 458c76ae52dSmrg{ 459c76ae52dSmrg FcValue v; 460c76ae52dSmrg double dpi; 461c76ae52dSmrg 462c76ae52dSmrg if (FcPatternGet (pattern, XFT_RENDER, 0, &v) == FcResultNoMatch) 463c76ae52dSmrg { 464c76ae52dSmrg FcPatternAddBool (pattern, XFT_RENDER, 465c76ae52dSmrg XftDefaultGetBool (dpy, XFT_RENDER, screen, 466c76ae52dSmrg XftDefaultHasRender (dpy))); 467c76ae52dSmrg } 468c76ae52dSmrg if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch) 469c76ae52dSmrg { 470c76ae52dSmrg FcPatternAddBool (pattern, FC_ANTIALIAS, 471c76ae52dSmrg XftDefaultGetBool (dpy, FC_ANTIALIAS, screen, 472c76ae52dSmrg True)); 473c76ae52dSmrg } 474c76ae52dSmrg#ifdef FC_EMBOLDEN 475c76ae52dSmrg if (FcPatternGet (pattern, FC_EMBOLDEN, 0, &v) == FcResultNoMatch) 476c76ae52dSmrg { 477c76ae52dSmrg FcPatternAddBool (pattern, FC_EMBOLDEN, 478c76ae52dSmrg XftDefaultGetBool (dpy, FC_EMBOLDEN, screen, 479c76ae52dSmrg False)); 480c76ae52dSmrg } 481c76ae52dSmrg#endif 482c76ae52dSmrg if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch) 483c76ae52dSmrg { 484c76ae52dSmrg FcPatternAddBool (pattern, FC_HINTING, 485c76ae52dSmrg XftDefaultGetBool (dpy, FC_HINTING, screen, 486c76ae52dSmrg True)); 487c76ae52dSmrg } 488c76ae52dSmrg#ifdef FC_HINT_STYLE 489c76ae52dSmrg if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch) 490c76ae52dSmrg { 491c76ae52dSmrg FcPatternAddInteger (pattern, FC_HINT_STYLE, 492c76ae52dSmrg XftDefaultGetInteger (dpy, FC_HINT_STYLE, screen, 493c76ae52dSmrg FC_HINT_FULL)); 494c76ae52dSmrg } 495c76ae52dSmrg#endif 496c76ae52dSmrg if (FcPatternGet (pattern, FC_AUTOHINT, 0, &v) == FcResultNoMatch) 497c76ae52dSmrg { 498c76ae52dSmrg FcPatternAddBool (pattern, FC_AUTOHINT, 499c76ae52dSmrg XftDefaultGetBool (dpy, FC_AUTOHINT, screen, 500c76ae52dSmrg False)); 501c76ae52dSmrg } 502c76ae52dSmrg if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch) 503c76ae52dSmrg { 504c76ae52dSmrg int subpixel = FC_RGBA_UNKNOWN; 505c76ae52dSmrg#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6 506c76ae52dSmrg if (XftDefaultHasRender (dpy)) 507c76ae52dSmrg { 508c76ae52dSmrg int render_order = XRenderQuerySubpixelOrder (dpy, screen); 509c76ae52dSmrg switch (render_order) { 510c76ae52dSmrg default: 511c76ae52dSmrg case SubPixelUnknown: subpixel = FC_RGBA_UNKNOWN; break; 512c76ae52dSmrg case SubPixelHorizontalRGB: subpixel = FC_RGBA_RGB; break; 513c76ae52dSmrg case SubPixelHorizontalBGR: subpixel = FC_RGBA_BGR; break; 514c76ae52dSmrg case SubPixelVerticalRGB: subpixel = FC_RGBA_VRGB; break; 515c76ae52dSmrg case SubPixelVerticalBGR: subpixel = FC_RGBA_VBGR; break; 516c76ae52dSmrg case SubPixelNone: subpixel = FC_RGBA_NONE; break; 517c76ae52dSmrg } 518c76ae52dSmrg } 519c76ae52dSmrg#endif 520c76ae52dSmrg FcPatternAddInteger (pattern, FC_RGBA, 521c76ae52dSmrg XftDefaultGetInteger (dpy, FC_RGBA, screen, 522c76ae52dSmrg subpixel)); 523c76ae52dSmrg } 524c76ae52dSmrg if (FcPatternGet (pattern, FC_MINSPACE, 0, &v) == FcResultNoMatch) 525c76ae52dSmrg { 526c76ae52dSmrg FcPatternAddBool (pattern, FC_MINSPACE, 527c76ae52dSmrg XftDefaultGetBool (dpy, FC_MINSPACE, screen, 528c76ae52dSmrg False)); 529c76ae52dSmrg } 530c76ae52dSmrg if (FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch) 531c76ae52dSmrg { 532c76ae52dSmrg dpi = (((double) DisplayHeight (dpy, screen) * 25.4) / 533c76ae52dSmrg (double) DisplayHeightMM (dpy, screen)); 534c76ae52dSmrg FcPatternAddDouble (pattern, FC_DPI, 535c76ae52dSmrg XftDefaultGetDouble (dpy, FC_DPI, screen, 536c76ae52dSmrg dpi)); 537c76ae52dSmrg } 538c76ae52dSmrg if (FcPatternGet (pattern, FC_SCALE, 0, &v) == FcResultNoMatch) 539c76ae52dSmrg { 540c76ae52dSmrg FcPatternAddDouble (pattern, FC_SCALE, 541c76ae52dSmrg XftDefaultGetDouble (dpy, FC_SCALE, screen, 1.0)); 542c76ae52dSmrg } 543c76ae52dSmrg if (FcPatternGet (pattern, XFT_MAX_GLYPH_MEMORY, 0, &v) == FcResultNoMatch) 544c76ae52dSmrg { 545c76ae52dSmrg FcPatternAddInteger (pattern, XFT_MAX_GLYPH_MEMORY, 546c76ae52dSmrg XftDefaultGetInteger (dpy, XFT_MAX_GLYPH_MEMORY, 547c76ae52dSmrg screen, 548c76ae52dSmrg XFT_FONT_MAX_GLYPH_MEMORY)); 549c76ae52dSmrg } 550c76ae52dSmrg FcDefaultSubstitute (pattern); 551c76ae52dSmrg} 552c76ae52dSmrg 553