xftdpy.c revision 0e0b1094
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; 35da9cf437Smrg 36c76ae52dSmrg /* 37c76ae52dSmrg * Get rid of any dangling unreferenced fonts 38c76ae52dSmrg */ 39c76ae52dSmrg info->max_unref_fonts = 0; 40c76ae52dSmrg XftFontManageMemory (dpy); 41da9cf437Smrg 42c76ae52dSmrg /* 43c76ae52dSmrg * Clean up the default values 44c76ae52dSmrg */ 45c76ae52dSmrg if (info->defaults) 46c76ae52dSmrg FcPatternDestroy (info->defaults); 47da9cf437Smrg 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; 55da9cf437Smrg 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 10916b8d512Smrg info->hasSolid = FcFalse; 11016b8d512Smrg if (major > 0 || (major == 0 && minor >= 10)) 11116b8d512Smrg info->hasSolid = FcTrue; 11216b8d512Smrg 113c76ae52dSmrg pf.type = PictTypeDirect; 114c76ae52dSmrg pf.depth = 32; 115c76ae52dSmrg pf.direct.redMask = 0xff; 116c76ae52dSmrg pf.direct.greenMask = 0xff; 117c76ae52dSmrg pf.direct.blueMask = 0xff; 118c76ae52dSmrg pf.direct.alphaMask = 0xff; 119c76ae52dSmrg info->solidFormat = XRenderFindFormat (dpy, 120c76ae52dSmrg (PictFormatType| 121c76ae52dSmrg PictFormatDepth| 122c76ae52dSmrg PictFormatRedMask| 123c76ae52dSmrg PictFormatGreenMask| 124c76ae52dSmrg PictFormatBlueMask| 125c76ae52dSmrg PictFormatAlphaMask), 126c76ae52dSmrg &pf, 127c76ae52dSmrg 0); 128c76ae52dSmrg } 129c76ae52dSmrg if (XftDebug () & XFT_DBG_RENDER) 130c76ae52dSmrg { 131c76ae52dSmrg Visual *visual = DefaultVisual (dpy, DefaultScreen (dpy)); 132c76ae52dSmrg XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 133da9cf437Smrg 134da9cf437Smrg printf ("XftDisplayInfoGet Default visual 0x%x ", 135c76ae52dSmrg (int) visual->visualid); 136c76ae52dSmrg if (format) 137c76ae52dSmrg { 138c76ae52dSmrg if (format->type == PictTypeDirect) 139c76ae52dSmrg { 140c76ae52dSmrg printf ("format %d,%d,%d,%d\n", 141c76ae52dSmrg format->direct.alpha, 142c76ae52dSmrg format->direct.red, 143c76ae52dSmrg format->direct.green, 144c76ae52dSmrg format->direct.blue); 145c76ae52dSmrg } 146c76ae52dSmrg else 147c76ae52dSmrg { 148c76ae52dSmrg printf ("format indexed\n"); 149c76ae52dSmrg } 150c76ae52dSmrg } 151c76ae52dSmrg else 152c76ae52dSmrg printf ("No Render format for default visual\n"); 153da9cf437Smrg 154c76ae52dSmrg printf ("XftDisplayInfoGet initialized, hasRender set to \"%s\"\n", 155c76ae52dSmrg info->hasRender ? "True" : "False"); 156c76ae52dSmrg } 157c76ae52dSmrg for (i = 0; i < XFT_NUM_SOLID_COLOR; i++) 158c76ae52dSmrg { 159c76ae52dSmrg info->colors[i].screen = -1; 160c76ae52dSmrg info->colors[i].pict = 0; 161c76ae52dSmrg } 1620d590c07Smrg info->fonts = NULL; 163da9cf437Smrg 164c76ae52dSmrg info->next = _XftDisplayInfo; 165c76ae52dSmrg _XftDisplayInfo = info; 1660d590c07Smrg 167be3b088cSmrg info->glyph_memory = 0; 1680e0b1094Smrg info->max_glyph_memory = (unsigned long)XftDefaultGetInteger (dpy, 169c76ae52dSmrg XFT_MAX_GLYPH_MEMORY, 0, 170c76ae52dSmrg XFT_DPY_MAX_GLYPH_MEMORY); 171c76ae52dSmrg if (XftDebug () & XFT_DBG_CACHE) 172c76ae52dSmrg printf ("global max cache memory %ld\n", info->max_glyph_memory); 173c76ae52dSmrg 174da9cf437Smrg 175c76ae52dSmrg info->num_unref_fonts = 0; 176c76ae52dSmrg info->max_unref_fonts = XftDefaultGetInteger (dpy, 177c76ae52dSmrg XFT_MAX_UNREF_FONTS, 0, 178c76ae52dSmrg XFT_DPY_MAX_UNREF_FONTS); 179c76ae52dSmrg if (XftDebug() & XFT_DBG_CACHE) 180c76ae52dSmrg printf ("global max unref fonts %d\n", info->max_unref_fonts); 181c76ae52dSmrg 182c76ae52dSmrg memset (info->fontHash, '\0', sizeof (XftFont *) * XFT_NUM_FONT_HASH); 183c76ae52dSmrg return info; 184da9cf437Smrg 185c76ae52dSmrgbail1: 186c76ae52dSmrg free (info); 187c76ae52dSmrgbail0: 188c76ae52dSmrg if (XftDebug () & XFT_DBG_RENDER) 189c76ae52dSmrg { 190c76ae52dSmrg printf ("XftDisplayInfoGet failed to initialize, Xft unhappy\n"); 191c76ae52dSmrg } 1920d590c07Smrg return NULL; 193c76ae52dSmrg} 194c76ae52dSmrg 195c76ae52dSmrg/* 196c76ae52dSmrg * Reduce memory usage in X server 197c76ae52dSmrg */ 198c76ae52dSmrg 199c76ae52dSmrgstatic void 200c76ae52dSmrg_XftDisplayValidateMemory (XftDisplayInfo *info) 201c76ae52dSmrg{ 202c76ae52dSmrg XftFont *public; 203c76ae52dSmrg XftFontInt *font; 204c76ae52dSmrg unsigned long glyph_memory; 205c76ae52dSmrg 206c76ae52dSmrg glyph_memory = 0; 207c76ae52dSmrg for (public = info->fonts; public; public = font->next) 208c76ae52dSmrg { 209c76ae52dSmrg font = (XftFontInt *) public; 210c76ae52dSmrg glyph_memory += font->glyph_memory; 211c76ae52dSmrg } 212c76ae52dSmrg if (glyph_memory != info->glyph_memory) 213c76ae52dSmrg printf ("Display glyph cache incorrect has %ld bytes, should have %ld\n", 214c76ae52dSmrg info->glyph_memory, glyph_memory); 215c76ae52dSmrg} 216c76ae52dSmrg 217c76ae52dSmrg_X_HIDDEN void 218c76ae52dSmrg_XftDisplayManageMemory (Display *dpy) 219c76ae52dSmrg{ 220c76ae52dSmrg XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False); 221c76ae52dSmrg unsigned long glyph_memory; 222c76ae52dSmrg XftFont *public; 223c76ae52dSmrg XftFontInt *font; 224c76ae52dSmrg 225c76ae52dSmrg if (!info || !info->max_glyph_memory) 226c76ae52dSmrg return; 227c76ae52dSmrg if (XftDebug () & XFT_DBG_CACHE) 228c76ae52dSmrg { 229c76ae52dSmrg if (info->glyph_memory > info->max_glyph_memory) 230c76ae52dSmrg printf ("Reduce global memory from %ld to %ld\n", 231c76ae52dSmrg info->glyph_memory, info->max_glyph_memory); 232c76ae52dSmrg _XftDisplayValidateMemory (info); 233c76ae52dSmrg } 234c76ae52dSmrg while (info->glyph_memory > info->max_glyph_memory) 235c76ae52dSmrg { 2360e0b1094Smrg glyph_memory = (unsigned long)rand () % info->glyph_memory; 237c76ae52dSmrg public = info->fonts; 238c76ae52dSmrg while (public) 239c76ae52dSmrg { 240c76ae52dSmrg font = (XftFontInt *) public; 241c76ae52dSmrg 242c76ae52dSmrg if (font->glyph_memory > glyph_memory) 243c76ae52dSmrg { 244c76ae52dSmrg _XftFontUncacheGlyph (dpy, public); 245c76ae52dSmrg break; 246c76ae52dSmrg } 247c76ae52dSmrg public = font->next; 248c76ae52dSmrg glyph_memory -= font->glyph_memory; 249c76ae52dSmrg } 250c76ae52dSmrg } 251c76ae52dSmrg if (XftDebug () & XFT_DBG_CACHE) 252c76ae52dSmrg _XftDisplayValidateMemory (info); 253c76ae52dSmrg} 254c76ae52dSmrg 255c76ae52dSmrg_X_EXPORT Bool 256c76ae52dSmrgXftDefaultHasRender (Display *dpy) 257c76ae52dSmrg{ 258c76ae52dSmrg XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); 259c76ae52dSmrg 260c76ae52dSmrg if (!info) 261c76ae52dSmrg return False; 262c76ae52dSmrg return info->hasRender; 263c76ae52dSmrg} 264c76ae52dSmrg 265c76ae52dSmrg_X_EXPORT Bool 266c76ae52dSmrgXftDefaultSet (Display *dpy, FcPattern *defaults) 267c76ae52dSmrg{ 268c76ae52dSmrg XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); 269c76ae52dSmrg 270c76ae52dSmrg if (!info) 271c76ae52dSmrg return False; 272c76ae52dSmrg if (info->defaults) 273c76ae52dSmrg FcPatternDestroy (info->defaults); 274c76ae52dSmrg info->defaults = defaults; 275c76ae52dSmrg if (!info->max_glyph_memory) 276c76ae52dSmrg info->max_glyph_memory = XFT_DPY_MAX_GLYPH_MEMORY; 2770e0b1094Smrg info->max_glyph_memory = (unsigned long)XftDefaultGetInteger (dpy, 278c76ae52dSmrg XFT_MAX_GLYPH_MEMORY, 0, 2790e0b1094Smrg (int)info->max_glyph_memory); 280c76ae52dSmrg if (!info->max_unref_fonts) 281c76ae52dSmrg info->max_unref_fonts = XFT_DPY_MAX_UNREF_FONTS; 282c76ae52dSmrg info->max_unref_fonts = XftDefaultGetInteger (dpy, 283c76ae52dSmrg XFT_MAX_UNREF_FONTS, 0, 284c76ae52dSmrg info->max_unref_fonts); 285c76ae52dSmrg return True; 286c76ae52dSmrg} 287c76ae52dSmrg 288c76ae52dSmrg_X_HIDDEN int 289da9cf437SmrgXftDefaultParseBool (const char *v) 290c76ae52dSmrg{ 291c76ae52dSmrg char c0, c1; 292c76ae52dSmrg 293c76ae52dSmrg c0 = *v; 294c76ae52dSmrg if (isupper ((int)c0)) 2950e0b1094Smrg c0 = (char)tolower (c0); 296c76ae52dSmrg if (c0 == 't' || c0 == 'y' || c0 == '1') 297c76ae52dSmrg return 1; 298c76ae52dSmrg if (c0 == 'f' || c0 == 'n' || c0 == '0') 299c76ae52dSmrg return 0; 300c76ae52dSmrg if (c0 == 'o') 301c76ae52dSmrg { 302c76ae52dSmrg c1 = v[1]; 303c76ae52dSmrg if (isupper ((int)c1)) 3040e0b1094Smrg c1 = (char)tolower (c1); 305c76ae52dSmrg if (c1 == 'n') 306c76ae52dSmrg return 1; 307c76ae52dSmrg if (c1 == 'f') 308c76ae52dSmrg return 0; 309c76ae52dSmrg } 310c76ae52dSmrg return -1; 311c76ae52dSmrg} 312c76ae52dSmrg 313c76ae52dSmrgstatic Bool 314da9cf437Smrg_XftDefaultInitBool (Display *dpy, FcPattern *pat, const char *option) 315c76ae52dSmrg{ 316c76ae52dSmrg char *v; 317c76ae52dSmrg int i; 318c76ae52dSmrg 319c76ae52dSmrg v = XGetDefault (dpy, "Xft", option); 320c76ae52dSmrg if (v && (i = XftDefaultParseBool (v)) >= 0) 321c76ae52dSmrg return FcPatternAddBool (pat, option, i != 0); 322c76ae52dSmrg return True; 323c76ae52dSmrg} 324c76ae52dSmrg 325c76ae52dSmrgstatic Bool 326da9cf437Smrg_XftDefaultInitDouble (Display *dpy, FcPattern *pat, const char *option) 327c76ae52dSmrg{ 328c76ae52dSmrg char *v, *e; 329c76ae52dSmrg double d; 330c76ae52dSmrg 331c76ae52dSmrg v = XGetDefault (dpy, "Xft", option); 332c76ae52dSmrg if (v) 333c76ae52dSmrg { 334c76ae52dSmrg d = strtod (v, &e); 335c76ae52dSmrg if (e != v) 336c76ae52dSmrg return FcPatternAddDouble (pat, option, d); 337c76ae52dSmrg } 338c76ae52dSmrg return True; 339c76ae52dSmrg} 340c76ae52dSmrg 341c76ae52dSmrgstatic Bool 342da9cf437Smrg_XftDefaultInitInteger (Display *dpy, FcPattern *pat, const char *option) 343c76ae52dSmrg{ 344c76ae52dSmrg char *v, *e; 345c76ae52dSmrg int i; 346c76ae52dSmrg 347c76ae52dSmrg v = XGetDefault (dpy, "Xft", option); 348c76ae52dSmrg if (v) 349c76ae52dSmrg { 350c76ae52dSmrg if (FcNameConstant ((FcChar8 *) v, &i)) 351c76ae52dSmrg return FcPatternAddInteger (pat, option, i); 3520e0b1094Smrg i = (int)strtol (v, &e, 0); 353c76ae52dSmrg if (e != v) 354c76ae52dSmrg return FcPatternAddInteger (pat, option, i); 355c76ae52dSmrg } 356c76ae52dSmrg return True; 357c76ae52dSmrg} 358c76ae52dSmrg 359c76ae52dSmrgstatic FcPattern * 360c76ae52dSmrg_XftDefaultInit (Display *dpy) 361c76ae52dSmrg{ 362c76ae52dSmrg FcPattern *pat; 363c76ae52dSmrg 364c76ae52dSmrg pat = FcPatternCreate (); 365c76ae52dSmrg if (!pat) 366c76ae52dSmrg goto bail0; 367c76ae52dSmrg 368c76ae52dSmrg if (!_XftDefaultInitDouble (dpy, pat, FC_SCALE)) 369c76ae52dSmrg goto bail1; 370c76ae52dSmrg if (!_XftDefaultInitDouble (dpy, pat, FC_DPI)) 371c76ae52dSmrg goto bail1; 372c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, XFT_RENDER)) 373c76ae52dSmrg goto bail1; 374c76ae52dSmrg if (!_XftDefaultInitInteger (dpy, pat, FC_RGBA)) 375c76ae52dSmrg goto bail1; 376da9cf437Smrg if (!_XftDefaultInitInteger (dpy, pat, FC_LCD_FILTER)) 377da9cf437Smrg goto bail1; 378c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, FC_ANTIALIAS)) 379c76ae52dSmrg goto bail1; 380c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, FC_EMBOLDEN)) 381c76ae52dSmrg goto bail1; 382c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, FC_AUTOHINT)) 383c76ae52dSmrg goto bail1; 384c76ae52dSmrg if (!_XftDefaultInitInteger (dpy, pat, FC_HINT_STYLE)) 385c76ae52dSmrg goto bail1; 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; 392da9cf437Smrg 393c76ae52dSmrg return pat; 394da9cf437Smrg 395c76ae52dSmrgbail1: 396c76ae52dSmrg FcPatternDestroy (pat); 397c76ae52dSmrgbail0: 3980d590c07Smrg return NULL; 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; 409da9cf437Smrg 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, 467da9cf437Smrg 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 if (FcPatternGet (pattern, FC_EMBOLDEN, 0, &v) == FcResultNoMatch) 477c76ae52dSmrg { 478c76ae52dSmrg FcPatternAddBool (pattern, FC_EMBOLDEN, 479c76ae52dSmrg XftDefaultGetBool (dpy, FC_EMBOLDEN, screen, 480c76ae52dSmrg False)); 481c76ae52dSmrg } 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 if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch) 489c76ae52dSmrg { 490c76ae52dSmrg FcPatternAddInteger (pattern, FC_HINT_STYLE, 491c76ae52dSmrg XftDefaultGetInteger (dpy, FC_HINT_STYLE, screen, 492c76ae52dSmrg FC_HINT_FULL)); 493c76ae52dSmrg } 494c76ae52dSmrg if (FcPatternGet (pattern, FC_AUTOHINT, 0, &v) == FcResultNoMatch) 495c76ae52dSmrg { 496c76ae52dSmrg FcPatternAddBool (pattern, FC_AUTOHINT, 497c76ae52dSmrg XftDefaultGetBool (dpy, FC_AUTOHINT, screen, 498c76ae52dSmrg False)); 499c76ae52dSmrg } 500c76ae52dSmrg if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch) 501c76ae52dSmrg { 502c76ae52dSmrg int subpixel = FC_RGBA_UNKNOWN; 503c76ae52dSmrg#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6 504c76ae52dSmrg if (XftDefaultHasRender (dpy)) 505c76ae52dSmrg { 506c76ae52dSmrg int render_order = XRenderQuerySubpixelOrder (dpy, screen); 507c76ae52dSmrg switch (render_order) { 508c76ae52dSmrg default: 509c76ae52dSmrg case SubPixelUnknown: subpixel = FC_RGBA_UNKNOWN; break; 510c76ae52dSmrg case SubPixelHorizontalRGB: subpixel = FC_RGBA_RGB; break; 511c76ae52dSmrg case SubPixelHorizontalBGR: subpixel = FC_RGBA_BGR; break; 512c76ae52dSmrg case SubPixelVerticalRGB: subpixel = FC_RGBA_VRGB; break; 513c76ae52dSmrg case SubPixelVerticalBGR: subpixel = FC_RGBA_VBGR; break; 514c76ae52dSmrg case SubPixelNone: subpixel = FC_RGBA_NONE; break; 515c76ae52dSmrg } 516c76ae52dSmrg } 517c76ae52dSmrg#endif 518c76ae52dSmrg FcPatternAddInteger (pattern, FC_RGBA, 519da9cf437Smrg XftDefaultGetInteger (dpy, FC_RGBA, screen, 520c76ae52dSmrg subpixel)); 521c76ae52dSmrg } 522da9cf437Smrg if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch) 523da9cf437Smrg { 524da9cf437Smrg FcPatternAddInteger (pattern, FC_LCD_FILTER, 525da9cf437Smrg XftDefaultGetInteger (dpy, FC_LCD_FILTER, screen, 526da9cf437Smrg FC_LCD_DEFAULT)); 527da9cf437Smrg } 528c76ae52dSmrg if (FcPatternGet (pattern, FC_MINSPACE, 0, &v) == FcResultNoMatch) 529c76ae52dSmrg { 530c76ae52dSmrg FcPatternAddBool (pattern, FC_MINSPACE, 531c76ae52dSmrg XftDefaultGetBool (dpy, FC_MINSPACE, screen, 532c76ae52dSmrg False)); 533c76ae52dSmrg } 534c76ae52dSmrg if (FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch) 535c76ae52dSmrg { 536da9cf437Smrg dpi = (((double) DisplayHeight (dpy, screen) * 25.4) / 537c76ae52dSmrg (double) DisplayHeightMM (dpy, screen)); 538da9cf437Smrg FcPatternAddDouble (pattern, FC_DPI, 539da9cf437Smrg XftDefaultGetDouble (dpy, FC_DPI, screen, 540c76ae52dSmrg dpi)); 541c76ae52dSmrg } 542c76ae52dSmrg if (FcPatternGet (pattern, FC_SCALE, 0, &v) == FcResultNoMatch) 543c76ae52dSmrg { 544c76ae52dSmrg FcPatternAddDouble (pattern, FC_SCALE, 545c76ae52dSmrg XftDefaultGetDouble (dpy, FC_SCALE, screen, 1.0)); 546c76ae52dSmrg } 547c76ae52dSmrg if (FcPatternGet (pattern, XFT_MAX_GLYPH_MEMORY, 0, &v) == FcResultNoMatch) 548c76ae52dSmrg { 549c76ae52dSmrg FcPatternAddInteger (pattern, XFT_MAX_GLYPH_MEMORY, 550c76ae52dSmrg XftDefaultGetInteger (dpy, XFT_MAX_GLYPH_MEMORY, 551c76ae52dSmrg screen, 552c76ae52dSmrg XFT_FONT_MAX_GLYPH_MEMORY)); 553c76ae52dSmrg } 554c76ae52dSmrg FcDefaultSubstitute (pattern); 555c76ae52dSmrg} 556c76ae52dSmrg 557