1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | #include "xftint.h" |
24 | |
25 | _X_HIDDEN__attribute__((visibility("hidden"))) XftDisplayInfo *_XftDisplayInfo; |
26 | |
27 | static int |
28 | _XftCloseDisplay (Display *dpy, XExtCodes *codes) |
29 | { |
30 | XftDisplayInfo *info, **prev; |
31 | |
32 | info = _XftDisplayInfoGet (dpy, FcFalse0); |
33 | if (!info) |
| 1 | Assuming 'info' is non-null | |
|
| |
34 | return 0; |
35 | |
36 | |
37 | |
38 | |
39 | info->max_unref_fonts = 0; |
40 | XftFontManageMemory (dpy); |
41 | |
42 | |
43 | |
44 | |
45 | if (info->defaults) |
| |
46 | FcPatternDestroy (info->defaults); |
47 | |
48 | |
49 | |
50 | |
51 | for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next) |
| 4 | | Value assigned to 'info' | |
|
| 5 | | Assuming pointer value is null | |
|
| 6 | | Loop condition is false. Execution continues on line 54 | |
|
52 | if (info->display == dpy) |
53 | break; |
54 | *prev = info->next; |
| 7 | | Access to field 'next' results in a dereference of a null pointer (loaded from variable 'info') |
|
55 | |
56 | free (info); |
57 | return 0; |
58 | } |
59 | |
60 | |
61 | _X_HIDDEN__attribute__((visibility("hidden"))) XftDisplayInfo * |
62 | _XftDisplayInfoGet (Display *dpy, FcBool createIfNecessary) |
63 | { |
64 | XftDisplayInfo *info, **prev; |
65 | XRenderPictFormat pf; |
66 | int i; |
67 | int event_base, error_base; |
68 | |
69 | for (prev = &_XftDisplayInfo; (info = *prev); prev = &(*prev)->next) |
70 | { |
71 | if (info->display == dpy) |
72 | { |
73 | |
74 | |
75 | |
76 | if (prev != &_XftDisplayInfo) |
77 | { |
78 | *prev = info->next; |
79 | info->next = _XftDisplayInfo; |
80 | _XftDisplayInfo = info; |
81 | } |
82 | return info; |
83 | } |
84 | } |
85 | if (!createIfNecessary) |
86 | return NULL((void*)0); |
87 | |
88 | info = (XftDisplayInfo *) malloc (sizeof (XftDisplayInfo)); |
89 | if (!info) |
90 | goto bail0; |
91 | info->codes = XAddExtension (dpy); |
92 | if (!info->codes) |
93 | goto bail1; |
94 | (void) XESetCloseDisplay (dpy, info->codes->extension, _XftCloseDisplay); |
95 | |
96 | info->display = dpy; |
97 | info->defaults = NULL((void*)0); |
98 | info->solidFormat = NULL((void*)0); |
99 | info->hasRender = (XRenderQueryExtension (dpy, &event_base, &error_base) && |
100 | (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))((&((_XPrivDisplay)dpy)->screens[(((_XPrivDisplay)dpy) ->default_screen)])->root_visual)) != NULL((void*)0))); |
101 | info->use_free_glyphs = FcTrue1; |
102 | if (info->hasRender) |
103 | { |
104 | int major, minor; |
105 | XRenderQueryVersion (dpy, &major, &minor); |
106 | if (major < 0 || (major == 0 && minor <= 2)) |
107 | info->use_free_glyphs = FcFalse0; |
108 | |
109 | info->hasSolid = FcFalse0; |
110 | if (major > 0 || (major == 0 && minor >= 10)) |
111 | info->hasSolid = FcTrue1; |
112 | |
113 | pf.type = PictTypeDirect1; |
114 | pf.depth = 32; |
115 | pf.direct.redMask = 0xff; |
116 | pf.direct.greenMask = 0xff; |
117 | pf.direct.blueMask = 0xff; |
118 | pf.direct.alphaMask = 0xff; |
119 | info->solidFormat = XRenderFindFormat (dpy, |
120 | (PictFormatType(1 << 1)| |
121 | PictFormatDepth(1 << 2)| |
122 | PictFormatRedMask(1 << 4)| |
123 | PictFormatGreenMask(1 << 6)| |
124 | PictFormatBlueMask(1 << 8)| |
125 | PictFormatAlphaMask(1 << 10)), |
126 | &pf, |
127 | 0); |
128 | } |
129 | if (XftDebug () & XFT_DBG_RENDER4) |
130 | { |
131 | Visual *visual = DefaultVisual (dpy, DefaultScreen (dpy))((&((_XPrivDisplay)dpy)->screens[(((_XPrivDisplay)dpy) ->default_screen)])->root_visual); |
132 | XRenderPictFormat *format = XRenderFindVisualFormat (dpy, visual); |
133 | |
134 | printf ("XftDisplayInfoGet Default visual 0x%x ", |
135 | (int) visual->visualid); |
136 | if (format) |
137 | { |
138 | if (format->type == PictTypeDirect1) |
139 | { |
140 | printf ("format %d,%d,%d,%d\n", |
141 | format->direct.alpha, |
142 | format->direct.red, |
143 | format->direct.green, |
144 | format->direct.blue); |
145 | } |
146 | else |
147 | { |
148 | printf ("format indexed\n"); |
149 | } |
150 | } |
151 | else |
152 | printf ("No Render format for default visual\n"); |
153 | |
154 | printf ("XftDisplayInfoGet initialized, hasRender set to \"%s\"\n", |
155 | info->hasRender ? "True" : "False"); |
156 | } |
157 | for (i = 0; i < XFT_NUM_SOLID_COLOR16; i++) |
158 | { |
159 | info->colors[i].screen = -1; |
160 | info->colors[i].pict = 0; |
161 | } |
162 | info->fonts = NULL((void*)0); |
163 | |
164 | info->next = _XftDisplayInfo; |
165 | _XftDisplayInfo = info; |
166 | |
167 | info->glyph_memory = 0; |
168 | info->max_glyph_memory = XftDefaultGetInteger (dpy, |
169 | XFT_MAX_GLYPH_MEMORY"maxglyphmemory", 0, |
170 | XFT_DPY_MAX_GLYPH_MEMORY(4 * 1024 * 1024)); |
171 | if (XftDebug () & XFT_DBG_CACHE128) |
172 | printf ("global max cache memory %ld\n", info->max_glyph_memory); |
173 | |
174 | |
175 | info->num_unref_fonts = 0; |
176 | info->max_unref_fonts = XftDefaultGetInteger (dpy, |
177 | XFT_MAX_UNREF_FONTS"maxunreffonts", 0, |
178 | XFT_DPY_MAX_UNREF_FONTS16); |
179 | if (XftDebug() & XFT_DBG_CACHE128) |
180 | printf ("global max unref fonts %d\n", info->max_unref_fonts); |
181 | |
182 | memset (info->fontHash, '\0', sizeof (XftFont *) * XFT_NUM_FONT_HASH)__builtin___memset_chk (info->fontHash, '\0', sizeof (XftFont *) * 127, __builtin_object_size (info->fontHash, 0)); |
183 | return info; |
184 | |
185 | bail1: |
186 | free (info); |
187 | bail0: |
188 | if (XftDebug () & XFT_DBG_RENDER4) |
189 | { |
190 | printf ("XftDisplayInfoGet failed to initialize, Xft unhappy\n"); |
191 | } |
192 | return NULL((void*)0); |
193 | } |
194 | |
195 | |
196 | |
197 | |
198 | |
199 | static void |
200 | _XftDisplayValidateMemory (XftDisplayInfo *info) |
201 | { |
202 | XftFont *public; |
203 | XftFontInt *font; |
204 | unsigned long glyph_memory; |
205 | |
206 | glyph_memory = 0; |
207 | for (public = info->fonts; public; public = font->next) |
208 | { |
209 | font = (XftFontInt *) public; |
210 | glyph_memory += font->glyph_memory; |
211 | } |
212 | if (glyph_memory != info->glyph_memory) |
213 | printf ("Display glyph cache incorrect has %ld bytes, should have %ld\n", |
214 | info->glyph_memory, glyph_memory); |
215 | } |
216 | |
217 | _X_HIDDEN__attribute__((visibility("hidden"))) void |
218 | _XftDisplayManageMemory (Display *dpy) |
219 | { |
220 | XftDisplayInfo *info = _XftDisplayInfoGet (dpy, False0); |
221 | unsigned long glyph_memory; |
222 | XftFont *public; |
223 | XftFontInt *font; |
224 | |
225 | if (!info || !info->max_glyph_memory) |
226 | return; |
227 | if (XftDebug () & XFT_DBG_CACHE128) |
228 | { |
229 | if (info->glyph_memory > info->max_glyph_memory) |
230 | printf ("Reduce global memory from %ld to %ld\n", |
231 | info->glyph_memory, info->max_glyph_memory); |
232 | _XftDisplayValidateMemory (info); |
233 | } |
234 | while (info->glyph_memory > info->max_glyph_memory) |
235 | { |
236 | glyph_memory = rand () % info->glyph_memory; |
237 | public = info->fonts; |
238 | while (public) |
239 | { |
240 | font = (XftFontInt *) public; |
241 | |
242 | if (font->glyph_memory > glyph_memory) |
243 | { |
244 | _XftFontUncacheGlyph (dpy, public); |
245 | break; |
246 | } |
247 | public = font->next; |
248 | glyph_memory -= font->glyph_memory; |
249 | } |
250 | } |
251 | if (XftDebug () & XFT_DBG_CACHE128) |
252 | _XftDisplayValidateMemory (info); |
253 | } |
254 | |
255 | _X_EXPORT__attribute__((visibility("default"))) Boolint |
256 | XftDefaultHasRender (Display *dpy) |
257 | { |
258 | XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True1); |
259 | |
260 | if (!info) |
261 | return False0; |
262 | return info->hasRender; |
263 | } |
264 | |
265 | _X_EXPORT__attribute__((visibility("default"))) Boolint |
266 | XftDefaultSet (Display *dpy, FcPattern *defaults) |
267 | { |
268 | XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True1); |
269 | |
270 | if (!info) |
271 | return False0; |
272 | if (info->defaults) |
273 | FcPatternDestroy (info->defaults); |
274 | info->defaults = defaults; |
275 | if (!info->max_glyph_memory) |
276 | info->max_glyph_memory = XFT_DPY_MAX_GLYPH_MEMORY(4 * 1024 * 1024); |
277 | info->max_glyph_memory = XftDefaultGetInteger (dpy, |
278 | XFT_MAX_GLYPH_MEMORY"maxglyphmemory", 0, |
279 | info->max_glyph_memory); |
280 | if (!info->max_unref_fonts) |
281 | info->max_unref_fonts = XFT_DPY_MAX_UNREF_FONTS16; |
282 | info->max_unref_fonts = XftDefaultGetInteger (dpy, |
283 | XFT_MAX_UNREF_FONTS"maxunreffonts", 0, |
284 | info->max_unref_fonts); |
285 | return True1; |
286 | } |
287 | |
288 | _X_HIDDEN__attribute__((visibility("hidden"))) int |
289 | XftDefaultParseBool (const char *v) |
290 | { |
291 | char c0, c1; |
292 | |
293 | c0 = *v; |
294 | if (isupper ((int)c0)) |
295 | c0 = tolower (c0); |
296 | if (c0 == 't' || c0 == 'y' || c0 == '1') |
297 | return 1; |
298 | if (c0 == 'f' || c0 == 'n' || c0 == '0') |
299 | return 0; |
300 | if (c0 == 'o') |
301 | { |
302 | c1 = v[1]; |
303 | if (isupper ((int)c1)) |
304 | c1 = tolower (c1); |
305 | if (c1 == 'n') |
306 | return 1; |
307 | if (c1 == 'f') |
308 | return 0; |
309 | } |
310 | return -1; |
311 | } |
312 | |
313 | static Boolint |
314 | _XftDefaultInitBool (Display *dpy, FcPattern *pat, const char *option) |
315 | { |
316 | char *v; |
317 | int i; |
318 | |
319 | v = XGetDefault (dpy, "Xft", option); |
320 | if (v && (i = XftDefaultParseBool (v)) >= 0) |
321 | return FcPatternAddBool (pat, option, i != 0); |
322 | return True1; |
323 | } |
324 | |
325 | static Boolint |
326 | _XftDefaultInitDouble (Display *dpy, FcPattern *pat, const char *option) |
327 | { |
328 | char *v, *e; |
329 | double d; |
330 | |
331 | v = XGetDefault (dpy, "Xft", option); |
332 | if (v) |
333 | { |
334 | d = strtod (v, &e); |
335 | if (e != v) |
336 | return FcPatternAddDouble (pat, option, d); |
337 | } |
338 | return True1; |
339 | } |
340 | |
341 | static Boolint |
342 | _XftDefaultInitInteger (Display *dpy, FcPattern *pat, const char *option) |
343 | { |
344 | char *v, *e; |
345 | int i; |
346 | |
347 | v = XGetDefault (dpy, "Xft", option); |
348 | if (v) |
349 | { |
350 | if (FcNameConstant ((FcChar8 *) v, &i)) |
351 | return FcPatternAddInteger (pat, option, i); |
352 | i = strtol (v, &e, 0); |
353 | if (e != v) |
354 | return FcPatternAddInteger (pat, option, i); |
355 | } |
356 | return True1; |
357 | } |
358 | |
359 | static FcPattern * |
360 | _XftDefaultInit (Display *dpy) |
361 | { |
362 | FcPattern *pat; |
363 | |
364 | pat = FcPatternCreate (); |
365 | if (!pat) |
366 | goto bail0; |
367 | |
368 | if (!_XftDefaultInitDouble (dpy, pat, FC_SCALE"scale")) |
369 | goto bail1; |
370 | if (!_XftDefaultInitDouble (dpy, pat, FC_DPI"dpi")) |
371 | goto bail1; |
372 | if (!_XftDefaultInitBool (dpy, pat, XFT_RENDER"render")) |
373 | goto bail1; |
374 | if (!_XftDefaultInitInteger (dpy, pat, FC_RGBA"rgba")) |
375 | goto bail1; |
376 | if (!_XftDefaultInitInteger (dpy, pat, FC_LCD_FILTER"lcdfilter")) |
377 | goto bail1; |
378 | if (!_XftDefaultInitBool (dpy, pat, FC_ANTIALIAS"antialias")) |
379 | goto bail1; |
380 | if (!_XftDefaultInitBool (dpy, pat, FC_EMBOLDEN"embolden")) |
381 | goto bail1; |
382 | if (!_XftDefaultInitBool (dpy, pat, FC_AUTOHINT"autohint")) |
383 | goto bail1; |
384 | if (!_XftDefaultInitInteger (dpy, pat, FC_HINT_STYLE"hintstyle")) |
385 | goto bail1; |
386 | if (!_XftDefaultInitBool (dpy, pat, FC_HINTING"hinting")) |
387 | goto bail1; |
388 | if (!_XftDefaultInitBool (dpy, pat, FC_MINSPACE"minspace")) |
389 | goto bail1; |
390 | if (!_XftDefaultInitInteger (dpy, pat, XFT_MAX_GLYPH_MEMORY"maxglyphmemory")) |
391 | goto bail1; |
392 | |
393 | return pat; |
394 | |
395 | bail1: |
396 | FcPatternDestroy (pat); |
397 | bail0: |
398 | return NULL((void*)0); |
399 | } |
400 | |
401 | static FcResult |
402 | _XftDefaultGet (Display *dpy, const char *object, int screen, FcValue *v) |
403 | { |
404 | XftDisplayInfo *info = _XftDisplayInfoGet (dpy, True1); |
405 | FcResult r; |
406 | |
407 | if (!info) |
408 | return FcResultNoMatch; |
409 | |
410 | if (!info->defaults) |
411 | { |
412 | info->defaults = _XftDefaultInit (dpy); |
413 | if (!info->defaults) |
414 | return FcResultNoMatch; |
415 | } |
416 | r = FcPatternGet (info->defaults, object, screen, v); |
417 | if (r == FcResultNoId && screen > 0) |
418 | r = FcPatternGet (info->defaults, object, 0, v); |
419 | return r; |
420 | } |
421 | |
422 | _X_HIDDEN__attribute__((visibility("hidden"))) Boolint |
423 | XftDefaultGetBool (Display *dpy, const char *object, int screen, Boolint def) |
424 | { |
425 | FcResult r; |
426 | FcValue v; |
427 | |
428 | r = _XftDefaultGet (dpy, object, screen, &v); |
429 | if (r != FcResultMatch || v.type != FcTypeBool) |
430 | return def; |
431 | return v.u.b; |
432 | } |
433 | |
434 | _X_HIDDEN__attribute__((visibility("hidden"))) int |
435 | XftDefaultGetInteger (Display *dpy, const char *object, int screen, int def) |
436 | { |
437 | FcResult r; |
438 | FcValue v; |
439 | |
440 | r = _XftDefaultGet (dpy, object, screen, &v); |
441 | if (r != FcResultMatch || v.type != FcTypeInteger) |
442 | return def; |
443 | return v.u.i; |
444 | } |
445 | |
446 | _X_HIDDEN__attribute__((visibility("hidden"))) double |
447 | XftDefaultGetDouble (Display *dpy, const char *object, int screen, double def) |
448 | { |
449 | FcResult r; |
450 | FcValue v; |
451 | |
452 | r = _XftDefaultGet (dpy, object, screen, &v); |
453 | if (r != FcResultMatch || v.type != FcTypeDouble) |
454 | return def; |
455 | return v.u.d; |
456 | } |
457 | |
458 | _X_EXPORT__attribute__((visibility("default"))) void |
459 | XftDefaultSubstitute (Display *dpy, int screen, FcPattern *pattern) |
460 | { |
461 | FcValue v; |
462 | double dpi; |
463 | |
464 | if (FcPatternGet (pattern, XFT_RENDER"render", 0, &v) == FcResultNoMatch) |
465 | { |
466 | FcPatternAddBool (pattern, XFT_RENDER"render", |
467 | XftDefaultGetBool (dpy, XFT_RENDER"render", screen, |
468 | XftDefaultHasRender (dpy))); |
469 | } |
470 | if (FcPatternGet (pattern, FC_ANTIALIAS"antialias", 0, &v) == FcResultNoMatch) |
471 | { |
472 | FcPatternAddBool (pattern, FC_ANTIALIAS"antialias", |
473 | XftDefaultGetBool (dpy, FC_ANTIALIAS"antialias", screen, |
474 | True1)); |
475 | } |
476 | if (FcPatternGet (pattern, FC_EMBOLDEN"embolden", 0, &v) == FcResultNoMatch) |
477 | { |
478 | FcPatternAddBool (pattern, FC_EMBOLDEN"embolden", |
479 | XftDefaultGetBool (dpy, FC_EMBOLDEN"embolden", screen, |
480 | False0)); |
481 | } |
482 | if (FcPatternGet (pattern, FC_HINTING"hinting", 0, &v) == FcResultNoMatch) |
483 | { |
484 | FcPatternAddBool (pattern, FC_HINTING"hinting", |
485 | XftDefaultGetBool (dpy, FC_HINTING"hinting", screen, |
486 | True1)); |
487 | } |
488 | if (FcPatternGet (pattern, FC_HINT_STYLE"hintstyle", 0, &v) == FcResultNoMatch) |
489 | { |
490 | FcPatternAddInteger (pattern, FC_HINT_STYLE"hintstyle", |
491 | XftDefaultGetInteger (dpy, FC_HINT_STYLE"hintstyle", screen, |
492 | FC_HINT_FULL3)); |
493 | } |
494 | if (FcPatternGet (pattern, FC_AUTOHINT"autohint", 0, &v) == FcResultNoMatch) |
495 | { |
496 | FcPatternAddBool (pattern, FC_AUTOHINT"autohint", |
497 | XftDefaultGetBool (dpy, FC_AUTOHINT"autohint", screen, |
498 | False0)); |
499 | } |
500 | if (FcPatternGet (pattern, FC_RGBA"rgba", 0, &v) == FcResultNoMatch) |
501 | { |
502 | int subpixel = FC_RGBA_UNKNOWN0; |
503 | #if RENDER_MAJOR0 > 0 || RENDER_MINOR11 >= 6 |
504 | if (XftDefaultHasRender (dpy)) |
505 | { |
506 | int render_order = XRenderQuerySubpixelOrder (dpy, screen); |
507 | switch (render_order) { |
508 | default: |
509 | case SubPixelUnknown0: subpixel = FC_RGBA_UNKNOWN0; break; |
510 | case SubPixelHorizontalRGB1: subpixel = FC_RGBA_RGB1; break; |
511 | case SubPixelHorizontalBGR2: subpixel = FC_RGBA_BGR2; break; |
512 | case SubPixelVerticalRGB3: subpixel = FC_RGBA_VRGB3; break; |
513 | case SubPixelVerticalBGR4: subpixel = FC_RGBA_VBGR4; break; |
514 | case SubPixelNone5: subpixel = FC_RGBA_NONE5; break; |
515 | } |
516 | } |
517 | #endif |
518 | FcPatternAddInteger (pattern, FC_RGBA"rgba", |
519 | XftDefaultGetInteger (dpy, FC_RGBA"rgba", screen, |
520 | subpixel)); |
521 | } |
522 | if (FcPatternGet (pattern, FC_LCD_FILTER"lcdfilter", 0, &v) == FcResultNoMatch) |
523 | { |
524 | FcPatternAddInteger (pattern, FC_LCD_FILTER"lcdfilter", |
525 | XftDefaultGetInteger (dpy, FC_LCD_FILTER"lcdfilter", screen, |
526 | FC_LCD_DEFAULT1)); |
527 | } |
528 | if (FcPatternGet (pattern, FC_MINSPACE"minspace", 0, &v) == FcResultNoMatch) |
529 | { |
530 | FcPatternAddBool (pattern, FC_MINSPACE"minspace", |
531 | XftDefaultGetBool (dpy, FC_MINSPACE"minspace", screen, |
532 | False0)); |
533 | } |
534 | if (FcPatternGet (pattern, FC_DPI"dpi", 0, &v) == FcResultNoMatch) |
535 | { |
536 | dpi = (((double) DisplayHeight (dpy, screen)((&((_XPrivDisplay)dpy)->screens[screen])->height) * 25.4) / |
537 | (double) DisplayHeightMM (dpy, screen)((&((_XPrivDisplay)dpy)->screens[screen])->mheight)); |
538 | FcPatternAddDouble (pattern, FC_DPI"dpi", |
539 | XftDefaultGetDouble (dpy, FC_DPI"dpi", screen, |
540 | dpi)); |
541 | } |
542 | if (FcPatternGet (pattern, FC_SCALE"scale", 0, &v) == FcResultNoMatch) |
543 | { |
544 | FcPatternAddDouble (pattern, FC_SCALE"scale", |
545 | XftDefaultGetDouble (dpy, FC_SCALE"scale", screen, 1.0)); |
546 | } |
547 | if (FcPatternGet (pattern, XFT_MAX_GLYPH_MEMORY"maxglyphmemory", 0, &v) == FcResultNoMatch) |
548 | { |
549 | FcPatternAddInteger (pattern, XFT_MAX_GLYPH_MEMORY"maxglyphmemory", |
550 | XftDefaultGetInteger (dpy, XFT_MAX_GLYPH_MEMORY"maxglyphmemory", |
551 | screen, |
552 | XFT_FONT_MAX_GLYPH_MEMORY(1024 * 1024))); |
553 | } |
554 | FcDefaultSubstitute (pattern); |
555 | } |
556 | |