1 /* xscreensaver, Copyright (c) 2014-2018 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 /* Compatibility layer using XDrawString, XDrawString16() or Xutf8DrawString().
13 This layer is used by X11 systems without Xft, and by MacOS / iOS.
23 # include "resources.h"
27 extern const char *progname;
41 XftFontOpenXlfd (Display *dpy, int screen, _Xconst char *xlfd)
43 XftFont *ff = (XftFont *) calloc (1, sizeof(*ff));
45 if (!dpy || !xlfd) abort();
47 ff->xfont = XLoadQueryFont (dpy, xlfd);
54 ff->name = strdup (xlfd);
55 ff->ascent = ff->xfont->ascent;
56 ff->descent = ff->xfont->descent;
57 ff->height = ff->ascent + ff->descent;
59 # ifdef HAVE_XUTF8DRAWSTRING
63 // In the event of -*-random-* (under JWXYZ), get the actual XLFD,
64 // otherwise we'll get another random font that doesn't match ff->xfont.
65 char *xlfd_resolved = NULL;
67 char **missing_charset_list_return;
68 int missing_charset_count_return;
69 char *def_string_return;
73 for (i = 0; i != ff->xfont->n_properties; ++i) {
74 if (ff->xfont->properties[i].name == XA_FONT) {
75 xlfd_resolved = XGetAtomName (dpy, ff->xfont->properties[i].card32);
82 ss = (char *) malloc (strlen(xlfd) + 10);
85 ff->fontset = XCreateFontSet (dpy, ss,
86 &missing_charset_list_return,
87 &missing_charset_count_return,
93 for (i = 0; i < missing_charset_count_return; i++)
94 fprintf (stderr, "%s: missing charset: %s\n",
95 ss, missing_charset_list_return[i]);
99 /* Apparently this is not to be freed. */
100 /* if (def_string_return) XFree (def_string_return); */
102 if (missing_charset_list_return)
103 XFreeStringList (missing_charset_list_return);
106 free (xlfd_resolved);
115 XftFontClose (Display *dpy, XftFont *font)
117 if (!dpy || !font) abort();
119 XFreeFont (dpy, font->xfont);
120 # ifdef HAVE_XUTF8DRAWSTRING
121 XFreeFontSet (dpy, font->fontset);
128 XftColorAllocName (Display *dpy,
129 _Xconst Visual *visual,
135 if (!dpy || !visual || !name || !result) abort();
137 if (! XParseColor (dpy, cmap, name, &color))
139 fprintf (stderr, "%s: can't parse color %s", progname, name);
142 else if (! XAllocColor (dpy, cmap, &color))
144 fprintf (stderr, "%s: couldn't allocate color %s", progname, name);
150 color2.red = color.red;
151 color2.green = color.green;
152 color2.blue = color.blue;
153 color2.alpha = 0xFFFF;
154 XftColorAllocValue (dpy, visual, cmap, &color2, result);
155 result->pixel = color.pixel;
162 maskbase (unsigned long m)
178 masklen (unsigned long m)
181 y = (m >> 1) & 033333333333;
182 y = m - y - ((y >>1) & 033333333333);
183 return (short) (((y + (y >> 3)) & 030707070707) % 077);
188 XftColorAllocValue (Display *dpy,
189 _Xconst Visual *visual,
191 _Xconst XRenderColor *color,
194 if (!dpy || !visual || !color || !result) abort();
195 if (visual->class == TrueColor)
197 int red_shift = maskbase (visual->red_mask);
198 int red_len = masklen (visual->red_mask);
199 int green_shift = maskbase (visual->green_mask);
200 int green_len = masklen (visual->green_mask);
201 int blue_shift = maskbase (visual->blue_mask);
202 int blue_len = masklen (visual->blue_mask);
203 result->pixel = (((color->red >> (16 - red_len)) << red_shift) |
204 ((color->green >> (16 - green_len)) << green_shift) |
205 ((color->blue >> (16 - blue_len)) << blue_shift));
207 result->pixel |= BlackPixel(dpy, 0); /* alpha */
213 xcolor.red = color->red;
214 xcolor.green = color->green;
215 xcolor.blue = color->blue;
216 if (!XAllocColor (dpy, cmap, &xcolor))
218 result->pixel = xcolor.pixel;
220 result->color.red = color->red;
221 result->color.green = color->green;
222 result->color.blue = color->blue;
223 result->color.alpha = color->alpha;
229 XftColorFree (Display *dpy,
234 if (!dpy || !visual || !color) abort();
235 if (visual->class != TrueColor)
236 XFreeColors (dpy, cmap, &color->pixel, 1, 0);
241 XftDrawCreate (Display *dpy,
246 XftDraw *dd = (XftDraw *) calloc (1, sizeof(*dd));
247 if (!dpy || !drawable || !visual) abort();
251 dd->drawable = drawable;
253 dd->colormap = colormap;
254 dd->gc = XCreateGC (dpy, drawable, 0, 0);
260 XftDrawDestroy (XftDraw *draw)
263 XFreeGC (draw->dpy, draw->gc);
269 XftTextExtentsUtf8 (Display *dpy,
271 _Xconst FcChar8 *string,
277 if (!dpy || !font || !string || !extents) abort();
279 # ifdef HAVE_XUTF8DRAWSTRING
283 Xutf8TextExtents (font->fontset, (const char *) string, len, &ink, 0);
284 XmbRectangle_to_XCharStruct (ink, overall, advancement);
286 # else /* !HAVE_XUTF8DRAWSTRING */
288 char *s2 = (char *) malloc (len + 1);
289 int direction, ascent, descent;
292 strncpy (s2, (char *) string, len);
294 s16 = utf8_to_XChar2b (s2, &s16_len);
295 XTextExtents16 (font->xfont, s16, s16_len,
296 &direction, &ascent, &descent, &overall);
300 # endif /* !HAVE_XUTF8DRAWSTRING */
302 XCharStruct_to_XGlyphInfo (overall, *extents);
307 XftDrawStringUtf8 (XftDraw *draw,
308 _Xconst XftColor *color,
312 _Xconst FcChar8 *string,
315 if (!draw || !color || !font || !string) abort();
317 if (color->pixel != draw->pixel)
319 XSetForeground (draw->dpy, draw->gc, color->pixel);
320 draw->pixel = color->pixel;
322 if (font->xfont->fid != draw->fid)
324 XSetFont (draw->dpy, draw->gc, font->xfont->fid);
325 draw->fid = font->xfont->fid;
328 # ifdef HAVE_XUTF8DRAWSTRING
329 /* If we have Xutf8DrawString, use it instead of XDrawString16 because
330 there is some chance it will handle characters of more than 16 bits
331 (beyond the Basic Multilingual Plane).
334 /* #### I guess I don't really understand how FontSet works, because when
335 using the real X11 implementation of Xutf8DrawString, this seems
336 to just truncate the text at the first non-ASCII character.
338 The XDrawString16() path works, however, at the expense of losing
339 everything above Basic Multilingual. However, that path is only
340 taken on X11 systems that are old enough to not have libXft,
341 which means that the chance of Unicode working was already slim.
343 Xutf8DrawString (draw->dpy, draw->drawable, font->fontset, draw->gc, x, y,
344 (const char *) string, len);
348 char *s2 = (char *) malloc (len + 1);
350 strncpy (s2, (char *) string, len);
352 s16 = utf8_to_XChar2b (s2, &s16_len);
354 XDrawString16 (draw->dpy, draw->drawable, draw->gc, x, y, s16, s16_len);
362 const int Wempty_translation_unit_is_a_dumb_warning = 0;
364 #endif /* HAVE_XFT */