xftdpy.c revision 120fad34
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 25120fad34Smrg#define BtoS(b) ((b) ? "true" : "false") 26120fad34Smrg 27c76ae52dSmrg_X_HIDDEN XftDisplayInfo *_XftDisplayInfo; 28c76ae52dSmrg 29c76ae52dSmrgstatic int 30120fad34Smrg_XftCloseDisplay (Display *dpy, XExtCodes *codes _X_UNUSED) 31c76ae52dSmrg{ 32c76ae52dSmrg XftDisplayInfo *info, **prev; 33c76ae52dSmrg 34c76ae52dSmrg info = _XftDisplayInfoGet (dpy, FcFalse); 35c76ae52dSmrg if (!info) 36c76ae52dSmrg return 0; 37da9cf437Smrg 38c76ae52dSmrg /* 39c76ae52dSmrg * Get rid of any dangling unreferenced fonts 40c76ae52dSmrg */ 41c76ae52dSmrg info->max_unref_fonts = 0; 42c76ae52dSmrg XftFontManageMemory (dpy); 43da9cf437Smrg 44c76ae52dSmrg /* 45c76ae52dSmrg * Clean up the default values 46c76ae52dSmrg */ 47c76ae52dSmrg if (info->defaults) 48c76ae52dSmrg FcPatternDestroy (info->defaults); 49da9cf437Smrg 50c76ae52dSmrg /* 51c76ae52dSmrg * Unhook from the global list 52c76ae52dSmrg */ 53c76ae52dSmrg for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next) 54c76ae52dSmrg if (info->display == dpy) 55c76ae52dSmrg break; 56120fad34Smrg if (info != NULL) 57120fad34Smrg *prev = info->next; 58da9cf437Smrg 59c76ae52dSmrg free (info); 60c76ae52dSmrg return 0; 61c76ae52dSmrg} 62c76ae52dSmrg 63c76ae52dSmrg 64c76ae52dSmrg_X_HIDDEN XftDisplayInfo * 65c76ae52dSmrg_XftDisplayInfoGet (Display *dpy, FcBool createIfNecessary) 66c76ae52dSmrg{ 67c76ae52dSmrg XftDisplayInfo *info, **prev; 68c76ae52dSmrg XRenderPictFormat pf; 69c76ae52dSmrg int i; 70c76ae52dSmrg int event_base, error_base; 71c76ae52dSmrg 72c76ae52dSmrg for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next) 73c76ae52dSmrg { 74c76ae52dSmrg if (info->display == dpy) 75c76ae52dSmrg { 76c76ae52dSmrg /* 77c76ae52dSmrg * MRU the list 78c76ae52dSmrg */ 79c76ae52dSmrg if (prev != &_XftDisplayInfo) 80c76ae52dSmrg { 81c76ae52dSmrg *prev = info->next; 82c76ae52dSmrg info->next = _XftDisplayInfo; 83c76ae52dSmrg _XftDisplayInfo = info; 84c76ae52dSmrg } 85c76ae52dSmrg return info; 86c76ae52dSmrg } 87c76ae52dSmrg } 88c76ae52dSmrg if (!createIfNecessary) 890d590c07Smrg return NULL; 90c76ae52dSmrg 91120fad34Smrg info = malloc (sizeof (XftDisplayInfo)); 92c76ae52dSmrg if (!info) 93c76ae52dSmrg goto bail0; 94c76ae52dSmrg info->codes = XAddExtension (dpy); 95c76ae52dSmrg if (!info->codes) 96c76ae52dSmrg goto bail1; 97c76ae52dSmrg (void) XESetCloseDisplay (dpy, info->codes->extension, _XftCloseDisplay); 98c76ae52dSmrg 99c76ae52dSmrg info->display = dpy; 1000d590c07Smrg info->defaults = NULL; 1010d590c07Smrg info->solidFormat = NULL; 102c76ae52dSmrg info->hasRender = (XRenderQueryExtension (dpy, &event_base, &error_base) && 1030d590c07Smrg (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != NULL)); 104c76ae52dSmrg info->use_free_glyphs = FcTrue; 105c76ae52dSmrg if (info->hasRender) 106c76ae52dSmrg { 107c76ae52dSmrg int major, minor; 108c76ae52dSmrg XRenderQueryVersion (dpy, &major, &minor); 109c76ae52dSmrg if (major < 0 || (major == 0 && minor <= 2)) 110c76ae52dSmrg info->use_free_glyphs = FcFalse; 111c76ae52dSmrg 11216b8d512Smrg info->hasSolid = FcFalse; 11316b8d512Smrg if (major > 0 || (major == 0 && minor >= 10)) 11416b8d512Smrg info->hasSolid = FcTrue; 11516b8d512Smrg 116c76ae52dSmrg pf.type = PictTypeDirect; 117c76ae52dSmrg pf.depth = 32; 118c76ae52dSmrg pf.direct.redMask = 0xff; 119c76ae52dSmrg pf.direct.greenMask = 0xff; 120c76ae52dSmrg pf.direct.blueMask = 0xff; 121c76ae52dSmrg pf.direct.alphaMask = 0xff; 122c76ae52dSmrg info->solidFormat = XRenderFindFormat (dpy, 123c76ae52dSmrg (PictFormatType| 124c76ae52dSmrg PictFormatDepth| 125c76ae52dSmrg PictFormatRedMask| 126c76ae52dSmrg PictFormatGreenMask| 127c76ae52dSmrg PictFormatBlueMask| 128c76ae52dSmrg PictFormatAlphaMask), 129c76ae52dSmrg &pf, 130c76ae52dSmrg 0); 131c76ae52dSmrg } 132c76ae52dSmrg if (XftDebug () & XFT_DBG_RENDER) 133c76ae52dSmrg { 134c76ae52dSmrg Visual *visual = DefaultVisual (dpy, DefaultScreen (dpy)); 135c76ae52dSmrg XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); 136da9cf437Smrg 137da9cf437Smrg printf ("XftDisplayInfoGet Default visual 0x%x ", 138c76ae52dSmrg (int) visual->visualid); 139c76ae52dSmrg if (format) 140c76ae52dSmrg { 141c76ae52dSmrg if (format->type == PictTypeDirect) 142c76ae52dSmrg { 143c76ae52dSmrg printf ("format %d,%d,%d,%d\n", 144c76ae52dSmrg format->direct.alpha, 145c76ae52dSmrg format->direct.red, 146c76ae52dSmrg format->direct.green, 147c76ae52dSmrg format->direct.blue); 148c76ae52dSmrg } 149c76ae52dSmrg else 150c76ae52dSmrg { 151c76ae52dSmrg printf ("format indexed\n"); 152c76ae52dSmrg } 153c76ae52dSmrg } 154c76ae52dSmrg else 155c76ae52dSmrg printf ("No Render format for default visual\n"); 156da9cf437Smrg 157c76ae52dSmrg printf ("XftDisplayInfoGet initialized, hasRender set to \"%s\"\n", 158c76ae52dSmrg info->hasRender ? "True" : "False"); 159c76ae52dSmrg } 160c76ae52dSmrg for (i = 0; i < XFT_NUM_SOLID_COLOR; i++) 161c76ae52dSmrg { 162c76ae52dSmrg info->colors[i].screen = -1; 163c76ae52dSmrg info->colors[i].pict = 0; 164c76ae52dSmrg } 1650d590c07Smrg info->fonts = NULL; 166da9cf437Smrg 167c76ae52dSmrg info->next = _XftDisplayInfo; 168c76ae52dSmrg _XftDisplayInfo = info; 1690d590c07Smrg 170be3b088cSmrg info->glyph_memory = 0; 1710e0b1094Smrg info->max_glyph_memory = (unsigned long)XftDefaultGetInteger (dpy, 172c76ae52dSmrg XFT_MAX_GLYPH_MEMORY, 0, 173c76ae52dSmrg XFT_DPY_MAX_GLYPH_MEMORY); 174c76ae52dSmrg if (XftDebug () & XFT_DBG_CACHE) 175120fad34Smrg printf ("global max cache memory %lu\n", info->max_glyph_memory); 176c76ae52dSmrg 177da9cf437Smrg 178c76ae52dSmrg info->num_unref_fonts = 0; 179c76ae52dSmrg info->max_unref_fonts = XftDefaultGetInteger (dpy, 180c76ae52dSmrg XFT_MAX_UNREF_FONTS, 0, 181c76ae52dSmrg XFT_DPY_MAX_UNREF_FONTS); 182c76ae52dSmrg if (XftDebug() & XFT_DBG_CACHE) 183120fad34Smrg printf ("global max unref fonts %d\n", info->max_unref_fonts); 184120fad34Smrg 185120fad34Smrg info->track_mem_usage = FcFalse; 186120fad34Smrg info->track_mem_usage = XftDefaultGetBool (dpy, 187120fad34Smrg XFT_TRACK_MEM_USAGE, 0, 188120fad34Smrg FcFalse); 189120fad34Smrg if (XftDebug() & XFT_DBG_CACHE) 190120fad34Smrg printf ("global track mem usage %s\n", BtoS(info->track_mem_usage)); 191c76ae52dSmrg 192c76ae52dSmrg memset (info->fontHash, '\0', sizeof (XftFont *) * XFT_NUM_FONT_HASH); 193c76ae52dSmrg return info; 194da9cf437Smrg 195c76ae52dSmrgbail1: 196c76ae52dSmrg free (info); 197c76ae52dSmrgbail0: 198c76ae52dSmrg if (XftDebug () & XFT_DBG_RENDER) 199c76ae52dSmrg { 200c76ae52dSmrg printf ("XftDisplayInfoGet failed to initialize, Xft unhappy\n"); 201c76ae52dSmrg } 2020d590c07Smrg return NULL; 203c76ae52dSmrg} 204c76ae52dSmrg 205c76ae52dSmrg/* 206c76ae52dSmrg * Reduce memory usage in X server 207c76ae52dSmrg */ 208c76ae52dSmrg 209c76ae52dSmrgstatic void 210c76ae52dSmrg_XftDisplayValidateMemory (XftDisplayInfo *info) 211c76ae52dSmrg{ 212c76ae52dSmrg XftFont *public; 213c76ae52dSmrg XftFontInt *font; 214c76ae52dSmrg unsigned long glyph_memory; 215c76ae52dSmrg 216c76ae52dSmrg glyph_memory = 0; 217c76ae52dSmrg for (public = info->fonts; public; public = font->next) 218c76ae52dSmrg { 219c76ae52dSmrg font = (XftFontInt *) public; 220c76ae52dSmrg glyph_memory += font->glyph_memory; 221c76ae52dSmrg } 222c76ae52dSmrg if (glyph_memory != info->glyph_memory) 223120fad34Smrg printf ("Display glyph cache incorrect has %lu bytes, should have %lu\n", 224c76ae52dSmrg info->glyph_memory, glyph_memory); 225c76ae52dSmrg} 226c76ae52dSmrg 227c76ae52dSmrg_X_HIDDEN void 228c76ae52dSmrg_XftDisplayManageMemory (Display *dpy) 229c76ae52dSmrg{ 230c76ae52dSmrg XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False); 231c76ae52dSmrg unsigned long glyph_memory; 232c76ae52dSmrg XftFont *public; 233c76ae52dSmrg XftFontInt *font; 234c76ae52dSmrg 235c76ae52dSmrg if (!info || !info->max_glyph_memory) 236c76ae52dSmrg return; 237c76ae52dSmrg if (XftDebug () & XFT_DBG_CACHE) 238c76ae52dSmrg { 239c76ae52dSmrg if (info->glyph_memory > info->max_glyph_memory) 240120fad34Smrg printf ("Reduce global memory from %lu to %lu\n", 241c76ae52dSmrg info->glyph_memory, info->max_glyph_memory); 242c76ae52dSmrg _XftDisplayValidateMemory (info); 243c76ae52dSmrg } 244c76ae52dSmrg while (info->glyph_memory > info->max_glyph_memory) 245c76ae52dSmrg { 2460e0b1094Smrg glyph_memory = (unsigned long)rand () % info->glyph_memory; 247c76ae52dSmrg public = info->fonts; 248c76ae52dSmrg while (public) 249c76ae52dSmrg { 250c76ae52dSmrg font = (XftFontInt *) public; 251c76ae52dSmrg 252c76ae52dSmrg if (font->glyph_memory > glyph_memory) 253c76ae52dSmrg { 254c76ae52dSmrg _XftFontUncacheGlyph (dpy, public); 255c76ae52dSmrg break; 256c76ae52dSmrg } 257c76ae52dSmrg public = font->next; 258c76ae52dSmrg glyph_memory -= font->glyph_memory; 259c76ae52dSmrg } 260c76ae52dSmrg } 261c76ae52dSmrg if (XftDebug () & XFT_DBG_CACHE) 262c76ae52dSmrg _XftDisplayValidateMemory (info); 263c76ae52dSmrg} 264c76ae52dSmrg 265c76ae52dSmrg_X_EXPORT Bool 266c76ae52dSmrgXftDefaultHasRender (Display *dpy) 267c76ae52dSmrg{ 268c76ae52dSmrg XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); 269c76ae52dSmrg 270c76ae52dSmrg if (!info) 271c76ae52dSmrg return False; 272c76ae52dSmrg return info->hasRender; 273c76ae52dSmrg} 274c76ae52dSmrg 275c76ae52dSmrg_X_EXPORT Bool 276c76ae52dSmrgXftDefaultSet (Display *dpy, FcPattern *defaults) 277c76ae52dSmrg{ 278c76ae52dSmrg XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); 279c76ae52dSmrg 280c76ae52dSmrg if (!info) 281c76ae52dSmrg return False; 282c76ae52dSmrg if (info->defaults) 283c76ae52dSmrg FcPatternDestroy (info->defaults); 284c76ae52dSmrg info->defaults = defaults; 285120fad34Smrg 286c76ae52dSmrg if (!info->max_glyph_memory) 287c76ae52dSmrg info->max_glyph_memory = XFT_DPY_MAX_GLYPH_MEMORY; 2880e0b1094Smrg info->max_glyph_memory = (unsigned long)XftDefaultGetInteger (dpy, 289c76ae52dSmrg XFT_MAX_GLYPH_MEMORY, 0, 2900e0b1094Smrg (int)info->max_glyph_memory); 291120fad34Smrg if (XftDebug () & XFT_DBG_CACHE) 292120fad34Smrg printf ("update max cache memory %lu\n", info->max_glyph_memory); 293120fad34Smrg 294c76ae52dSmrg if (!info->max_unref_fonts) 295c76ae52dSmrg info->max_unref_fonts = XFT_DPY_MAX_UNREF_FONTS; 296c76ae52dSmrg info->max_unref_fonts = XftDefaultGetInteger (dpy, 297c76ae52dSmrg XFT_MAX_UNREF_FONTS, 0, 298c76ae52dSmrg info->max_unref_fonts); 299120fad34Smrg if (XftDebug() & XFT_DBG_CACHE) 300120fad34Smrg printf ("update max unref fonts %d\n", info->max_unref_fonts); 301120fad34Smrg 302120fad34Smrg info->track_mem_usage = XftDefaultGetBool (dpy, 303120fad34Smrg XFT_TRACK_MEM_USAGE, 0, 304120fad34Smrg info->track_mem_usage); 305120fad34Smrg if (XftDebug() & XFT_DBG_CACHE) 306120fad34Smrg printf ("update track mem usage %s\n", BtoS(info->track_mem_usage)); 307120fad34Smrg 308c76ae52dSmrg return True; 309c76ae52dSmrg} 310c76ae52dSmrg 311c76ae52dSmrg_X_HIDDEN int 312da9cf437SmrgXftDefaultParseBool (const char *v) 313c76ae52dSmrg{ 314c76ae52dSmrg char c0, c1; 315c76ae52dSmrg 316c76ae52dSmrg c0 = *v; 317c76ae52dSmrg if (isupper ((int)c0)) 3180e0b1094Smrg c0 = (char)tolower (c0); 319c76ae52dSmrg if (c0 == 't' || c0 == 'y' || c0 == '1') 320c76ae52dSmrg return 1; 321c76ae52dSmrg if (c0 == 'f' || c0 == 'n' || c0 == '0') 322c76ae52dSmrg return 0; 323c76ae52dSmrg if (c0 == 'o') 324c76ae52dSmrg { 325c76ae52dSmrg c1 = v[1]; 326c76ae52dSmrg if (isupper ((int)c1)) 3270e0b1094Smrg c1 = (char)tolower (c1); 328c76ae52dSmrg if (c1 == 'n') 329c76ae52dSmrg return 1; 330c76ae52dSmrg if (c1 == 'f') 331c76ae52dSmrg return 0; 332c76ae52dSmrg } 333c76ae52dSmrg return -1; 334c76ae52dSmrg} 335c76ae52dSmrg 336c76ae52dSmrgstatic Bool 337da9cf437Smrg_XftDefaultInitBool (Display *dpy, FcPattern *pat, const char *option) 338c76ae52dSmrg{ 339c76ae52dSmrg char *v; 340c76ae52dSmrg int i; 341c76ae52dSmrg 342c76ae52dSmrg v = XGetDefault (dpy, "Xft", option); 343c76ae52dSmrg if (v && (i = XftDefaultParseBool (v)) >= 0) 344c76ae52dSmrg return FcPatternAddBool (pat, option, i != 0); 345c76ae52dSmrg return True; 346c76ae52dSmrg} 347c76ae52dSmrg 348c76ae52dSmrgstatic Bool 349da9cf437Smrg_XftDefaultInitDouble (Display *dpy, FcPattern *pat, const char *option) 350c76ae52dSmrg{ 351c76ae52dSmrg char *v, *e; 352c76ae52dSmrg double d; 353c76ae52dSmrg 354c76ae52dSmrg v = XGetDefault (dpy, "Xft", option); 355c76ae52dSmrg if (v) 356c76ae52dSmrg { 357c76ae52dSmrg d = strtod (v, &e); 358c76ae52dSmrg if (e != v) 359c76ae52dSmrg return FcPatternAddDouble (pat, option, d); 360c76ae52dSmrg } 361c76ae52dSmrg return True; 362c76ae52dSmrg} 363c76ae52dSmrg 364c76ae52dSmrgstatic Bool 365da9cf437Smrg_XftDefaultInitInteger (Display *dpy, FcPattern *pat, const char *option) 366c76ae52dSmrg{ 367c76ae52dSmrg char *v, *e; 368c76ae52dSmrg int i; 369c76ae52dSmrg 370c76ae52dSmrg v = XGetDefault (dpy, "Xft", option); 371c76ae52dSmrg if (v) 372c76ae52dSmrg { 373c76ae52dSmrg if (FcNameConstant ((FcChar8 *) v, &i)) 374c76ae52dSmrg return FcPatternAddInteger (pat, option, i); 3750e0b1094Smrg i = (int)strtol (v, &e, 0); 376c76ae52dSmrg if (e != v) 377c76ae52dSmrg return FcPatternAddInteger (pat, option, i); 378c76ae52dSmrg } 379c76ae52dSmrg return True; 380c76ae52dSmrg} 381c76ae52dSmrg 382c76ae52dSmrgstatic FcPattern * 383c76ae52dSmrg_XftDefaultInit (Display *dpy) 384c76ae52dSmrg{ 385c76ae52dSmrg FcPattern *pat; 386c76ae52dSmrg 387c76ae52dSmrg pat = FcPatternCreate (); 388c76ae52dSmrg if (!pat) 389c76ae52dSmrg goto bail0; 390c76ae52dSmrg 391c76ae52dSmrg if (!_XftDefaultInitDouble (dpy, pat, FC_SCALE)) 392c76ae52dSmrg goto bail1; 393c76ae52dSmrg if (!_XftDefaultInitDouble (dpy, pat, FC_DPI)) 394c76ae52dSmrg goto bail1; 395c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, XFT_RENDER)) 396c76ae52dSmrg goto bail1; 397c76ae52dSmrg if (!_XftDefaultInitInteger (dpy, pat, FC_RGBA)) 398c76ae52dSmrg goto bail1; 399da9cf437Smrg if (!_XftDefaultInitInteger (dpy, pat, FC_LCD_FILTER)) 400da9cf437Smrg goto bail1; 401c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, FC_ANTIALIAS)) 402c76ae52dSmrg goto bail1; 403c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, FC_EMBOLDEN)) 404c76ae52dSmrg goto bail1; 405c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, FC_AUTOHINT)) 406c76ae52dSmrg goto bail1; 407c76ae52dSmrg if (!_XftDefaultInitInteger (dpy, pat, FC_HINT_STYLE)) 408c76ae52dSmrg goto bail1; 409c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, FC_HINTING)) 410c76ae52dSmrg goto bail1; 411c76ae52dSmrg if (!_XftDefaultInitBool (dpy, pat, FC_MINSPACE)) 412c76ae52dSmrg goto bail1; 413c76ae52dSmrg if (!_XftDefaultInitInteger (dpy, pat, XFT_MAX_GLYPH_MEMORY)) 414c76ae52dSmrg goto bail1; 415da9cf437Smrg 416c76ae52dSmrg return pat; 417da9cf437Smrg 418c76ae52dSmrgbail1: 419c76ae52dSmrg FcPatternDestroy (pat); 420c76ae52dSmrgbail0: 4210d590c07Smrg return NULL; 422c76ae52dSmrg} 423c76ae52dSmrg 424c76ae52dSmrgstatic FcResult 425c76ae52dSmrg_XftDefaultGet (Display *dpy, const char *object, int screen, FcValue *v) 426c76ae52dSmrg{ 427c76ae52dSmrg XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True); 428c76ae52dSmrg FcResult r; 429c76ae52dSmrg 430c76ae52dSmrg if (!info) 431c76ae52dSmrg return FcResultNoMatch; 432da9cf437Smrg 433c76ae52dSmrg if (!info->defaults) 434c76ae52dSmrg { 435c76ae52dSmrg info->defaults = _XftDefaultInit (dpy); 436c76ae52dSmrg if (!info->defaults) 437c76ae52dSmrg return FcResultNoMatch; 438c76ae52dSmrg } 439c76ae52dSmrg r = FcPatternGet (info->defaults, object, screen, v); 440c76ae52dSmrg if (r == FcResultNoId && screen > 0) 441c76ae52dSmrg r = FcPatternGet (info->defaults, object, 0, v); 442c76ae52dSmrg return r; 443c76ae52dSmrg} 444c76ae52dSmrg 445c76ae52dSmrg_X_HIDDEN Bool 446c76ae52dSmrgXftDefaultGetBool (Display *dpy, const char *object, int screen, Bool def) 447c76ae52dSmrg{ 448c76ae52dSmrg FcResult r; 449c76ae52dSmrg FcValue v; 450c76ae52dSmrg 451c76ae52dSmrg r = _XftDefaultGet (dpy, object, screen, &v); 452c76ae52dSmrg if (r != FcResultMatch || v.type != FcTypeBool) 453c76ae52dSmrg return def; 454c76ae52dSmrg return v.u.b; 455c76ae52dSmrg} 456c76ae52dSmrg 457c76ae52dSmrg_X_HIDDEN int 458c76ae52dSmrgXftDefaultGetInteger (Display *dpy, const char *object, int screen, int def) 459c76ae52dSmrg{ 460c76ae52dSmrg FcResult r; 461c76ae52dSmrg FcValue v; 462c76ae52dSmrg 463c76ae52dSmrg r = _XftDefaultGet (dpy, object, screen, &v); 464c76ae52dSmrg if (r != FcResultMatch || v.type != FcTypeInteger) 465c76ae52dSmrg return def; 466c76ae52dSmrg return v.u.i; 467c76ae52dSmrg} 468c76ae52dSmrg 469c76ae52dSmrg_X_HIDDEN double 470c76ae52dSmrgXftDefaultGetDouble (Display *dpy, const char *object, int screen, double def) 471c76ae52dSmrg{ 472c76ae52dSmrg FcResult r; 473c76ae52dSmrg FcValue v; 474c76ae52dSmrg 475c76ae52dSmrg r = _XftDefaultGet (dpy, object, screen, &v); 476c76ae52dSmrg if (r != FcResultMatch || v.type != FcTypeDouble) 477c76ae52dSmrg return def; 478c76ae52dSmrg return v.u.d; 479c76ae52dSmrg} 480c76ae52dSmrg 481c76ae52dSmrg_X_EXPORT void 482c76ae52dSmrgXftDefaultSubstitute (Display *dpy, int screen, FcPattern *pattern) 483c76ae52dSmrg{ 484c76ae52dSmrg FcValue v; 485c76ae52dSmrg double dpi; 486c76ae52dSmrg 487c76ae52dSmrg if (FcPatternGet (pattern, XFT_RENDER, 0, &v) == FcResultNoMatch) 488c76ae52dSmrg { 489c76ae52dSmrg FcPatternAddBool (pattern, XFT_RENDER, 490da9cf437Smrg XftDefaultGetBool (dpy, XFT_RENDER, screen, 491c76ae52dSmrg XftDefaultHasRender (dpy))); 492c76ae52dSmrg } 493c76ae52dSmrg if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch) 494c76ae52dSmrg { 495c76ae52dSmrg FcPatternAddBool (pattern, FC_ANTIALIAS, 496c76ae52dSmrg XftDefaultGetBool (dpy, FC_ANTIALIAS, screen, 497c76ae52dSmrg True)); 498c76ae52dSmrg } 499c76ae52dSmrg if (FcPatternGet (pattern, FC_EMBOLDEN, 0, &v) == FcResultNoMatch) 500c76ae52dSmrg { 501c76ae52dSmrg FcPatternAddBool (pattern, FC_EMBOLDEN, 502c76ae52dSmrg XftDefaultGetBool (dpy, FC_EMBOLDEN, screen, 503c76ae52dSmrg False)); 504c76ae52dSmrg } 505c76ae52dSmrg if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch) 506c76ae52dSmrg { 507c76ae52dSmrg FcPatternAddBool (pattern, FC_HINTING, 508c76ae52dSmrg XftDefaultGetBool (dpy, FC_HINTING, screen, 509c76ae52dSmrg True)); 510c76ae52dSmrg } 511c76ae52dSmrg if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch) 512c76ae52dSmrg { 513c76ae52dSmrg FcPatternAddInteger (pattern, FC_HINT_STYLE, 514c76ae52dSmrg XftDefaultGetInteger (dpy, FC_HINT_STYLE, screen, 515c76ae52dSmrg FC_HINT_FULL)); 516c76ae52dSmrg } 517c76ae52dSmrg if (FcPatternGet (pattern, FC_AUTOHINT, 0, &v) == FcResultNoMatch) 518c76ae52dSmrg { 519c76ae52dSmrg FcPatternAddBool (pattern, FC_AUTOHINT, 520c76ae52dSmrg XftDefaultGetBool (dpy, FC_AUTOHINT, screen, 521c76ae52dSmrg False)); 522c76ae52dSmrg } 523c76ae52dSmrg if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch) 524c76ae52dSmrg { 525c76ae52dSmrg int subpixel = FC_RGBA_UNKNOWN; 526c76ae52dSmrg#if RENDER_MAJOR > 0 || RENDER_MINOR >= 6 527c76ae52dSmrg if (XftDefaultHasRender (dpy)) 528c76ae52dSmrg { 529c76ae52dSmrg int render_order = XRenderQuerySubpixelOrder (dpy, screen); 530c76ae52dSmrg switch (render_order) { 531c76ae52dSmrg default: 532c76ae52dSmrg case SubPixelUnknown: subpixel = FC_RGBA_UNKNOWN; break; 533c76ae52dSmrg case SubPixelHorizontalRGB: subpixel = FC_RGBA_RGB; break; 534c76ae52dSmrg case SubPixelHorizontalBGR: subpixel = FC_RGBA_BGR; break; 535c76ae52dSmrg case SubPixelVerticalRGB: subpixel = FC_RGBA_VRGB; break; 536c76ae52dSmrg case SubPixelVerticalBGR: subpixel = FC_RGBA_VBGR; break; 537c76ae52dSmrg case SubPixelNone: subpixel = FC_RGBA_NONE; break; 538c76ae52dSmrg } 539c76ae52dSmrg } 540c76ae52dSmrg#endif 541c76ae52dSmrg FcPatternAddInteger (pattern, FC_RGBA, 542da9cf437Smrg XftDefaultGetInteger (dpy, FC_RGBA, screen, 543c76ae52dSmrg subpixel)); 544c76ae52dSmrg } 545da9cf437Smrg if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch) 546da9cf437Smrg { 547da9cf437Smrg FcPatternAddInteger (pattern, FC_LCD_FILTER, 548da9cf437Smrg XftDefaultGetInteger (dpy, FC_LCD_FILTER, screen, 549da9cf437Smrg FC_LCD_DEFAULT)); 550da9cf437Smrg } 551c76ae52dSmrg if (FcPatternGet (pattern, FC_MINSPACE, 0, &v) == FcResultNoMatch) 552c76ae52dSmrg { 553c76ae52dSmrg FcPatternAddBool (pattern, FC_MINSPACE, 554c76ae52dSmrg XftDefaultGetBool (dpy, FC_MINSPACE, screen, 555c76ae52dSmrg False)); 556c76ae52dSmrg } 557c76ae52dSmrg if (FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch) 558c76ae52dSmrg { 559da9cf437Smrg dpi = (((double) DisplayHeight (dpy, screen) * 25.4) / 560c76ae52dSmrg (double) DisplayHeightMM (dpy, screen)); 561da9cf437Smrg FcPatternAddDouble (pattern, FC_DPI, 562da9cf437Smrg XftDefaultGetDouble (dpy, FC_DPI, screen, 563c76ae52dSmrg dpi)); 564c76ae52dSmrg } 565c76ae52dSmrg if (FcPatternGet (pattern, FC_SCALE, 0, &v) == FcResultNoMatch) 566c76ae52dSmrg { 567c76ae52dSmrg FcPatternAddDouble (pattern, FC_SCALE, 568c76ae52dSmrg XftDefaultGetDouble (dpy, FC_SCALE, screen, 1.0)); 569c76ae52dSmrg } 570c76ae52dSmrg if (FcPatternGet (pattern, XFT_MAX_GLYPH_MEMORY, 0, &v) == FcResultNoMatch) 571c76ae52dSmrg { 572c76ae52dSmrg FcPatternAddInteger (pattern, XFT_MAX_GLYPH_MEMORY, 573c76ae52dSmrg XftDefaultGetInteger (dpy, XFT_MAX_GLYPH_MEMORY, 574c76ae52dSmrg screen, 575c76ae52dSmrg XFT_FONT_MAX_GLYPH_MEMORY)); 576c76ae52dSmrg } 577c76ae52dSmrg FcDefaultSubstitute (pattern); 578c76ae52dSmrg} 579c76ae52dSmrg 580