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