1 /* xscreensaver, Copyright (c) 2014-2015 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, red_len;
198 int green_shift, green_len;
199 int blue_shift, blue_len;
201 red_shift = maskbase (visual->red_mask);
202 red_len = masklen (visual->red_mask);
203 green_shift = maskbase (visual->green_mask);
204 green_len = masklen (visual->green_mask);
205 blue_shift = maskbase (visual->blue_mask);
206 blue_len = masklen (visual->blue_mask);
207 result->pixel = (((color->red >> (16 - red_len)) << red_shift) |
208 ((color->green >> (16 - green_len)) << green_shift) |
209 ((color->blue >> (16 - blue_len)) << blue_shift));
211 result->pixel |= BlackPixel(dpy, 0); /* alpha */
217 xcolor.red = color->red;
218 xcolor.green = color->green;
219 xcolor.blue = color->blue;
220 if (!XAllocColor (dpy, cmap, &xcolor))
222 result->pixel = xcolor.pixel;
224 result->color.red = color->red;
225 result->color.green = color->green;
226 result->color.blue = color->blue;
227 result->color.alpha = color->alpha;
233 XftColorFree (Display *dpy,
238 if (!dpy || !visual || !color) abort();
239 if (visual->class != TrueColor)
240 XFreeColors (dpy, cmap, &color->pixel, 1, 0);
245 XftDrawCreate (Display *dpy,
250 XftDraw *dd = (XftDraw *) calloc (1, sizeof(*dd));
251 if (!dpy || !drawable || !visual) abort();
255 dd->drawable = drawable;
257 dd->colormap = colormap;
258 dd->gc = XCreateGC (dpy, drawable, 0, 0);
264 XftDrawDestroy (XftDraw *draw)
267 XFreeGC (draw->dpy, draw->gc);
273 XftTextExtentsUtf8 (Display *dpy,
275 _Xconst FcChar8 *string,
281 if (!dpy || !font || !string || !extents) abort();
283 # ifdef HAVE_XUTF8DRAWSTRING
287 Xutf8TextExtents (font->fontset, (const char *) string, len, &ink, 0);
288 XmbRectangle_to_XCharStruct (ink, overall, advancement);
290 # else /* !HAVE_XUTF8DRAWSTRING */
292 char *s2 = (char *) malloc (len + 1);
293 int direction, ascent, descent;
296 strncpy (s2, (char *) string, len);
298 s16 = utf8_to_XChar2b (s2, &s16_len);
299 XTextExtents16 (font->xfont, s16, s16_len,
300 &direction, &ascent, &descent, &overall);
304 # endif /* !HAVE_XUTF8DRAWSTRING */
306 XCharStruct_to_XGlyphInfo (overall, *extents);
311 XftDrawStringUtf8 (XftDraw *draw,
312 _Xconst XftColor *color,
316 _Xconst FcChar8 *string,
319 if (!draw || !color || !font || !string) abort();
321 if (color->pixel != draw->pixel)
323 XSetForeground (draw->dpy, draw->gc, color->pixel);
324 draw->pixel = color->pixel;
326 if (font->xfont->fid != draw->fid)
328 XSetFont (draw->dpy, draw->gc, font->xfont->fid);
329 draw->fid = font->xfont->fid;
332 # ifdef HAVE_XUTF8DRAWSTRING
333 /* If we have Xutf8DrawString, use it instead of XDrawString16 because
334 there is some chance it will handle characters of more than 16 bits
335 (beyond the Basic Multilingual Plane).
338 /* #### I guess I don't really understand how FontSet works, because when
339 using the real X11 implementation of Xutf8DrawString, this seems
340 to just truncate the text at the first non-ASCII character.
342 The XDrawString16() path works, however, at the expense of losing
343 everything above Basic Multilingual. However, that path is only
344 taken on X11 systems that are old enough to not have libXft,
345 which means that the chance of Unicode working was already slim.
347 Xutf8DrawString (draw->dpy, draw->drawable, font->fontset, draw->gc, x, y,
348 (const char *) string, len);
352 char *s2 = (char *) malloc (len + 1);
354 strncpy (s2, (char *) string, len);
356 s16 = utf8_to_XChar2b (s2, &s16_len);
358 XDrawString16 (draw->dpy, draw->drawable, draw->gc, x, y, s16, s16_len);
366 const int Wempty_translation_unit_is_a_dumb_warning = 0;
368 #endif /* HAVE_XFT */