diff options
author | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
---|---|---|
committer | Simon Rettberg | 2018-10-16 10:08:48 +0200 |
commit | d3a98cf6cbc3bd0b9efc570f58e8812c03931c18 (patch) | |
tree | cbddf8e50f35a9c6e878a5bfe3c6d625d99e12ba /utils/xft.c | |
download | xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.gz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.tar.xz xscreensaver-d3a98cf6cbc3bd0b9efc570f58e8812c03931c18.zip |
Original 5.40
Diffstat (limited to 'utils/xft.c')
-rw-r--r-- | utils/xft.c | 364 |
1 files changed, 364 insertions, 0 deletions
diff --git a/utils/xft.c b/utils/xft.c new file mode 100644 index 0000000..9245752 --- /dev/null +++ b/utils/xft.c @@ -0,0 +1,364 @@ +/* xscreensaver, Copyright (c) 2014-2018 Jamie Zawinski <jwz@jwz.org> + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. No representations are made about the suitability of this + * software for any purpose. It is provided "as is" without express or + * implied warranty. + */ + +/* Compatibility layer using XDrawString, XDrawString16() or Xutf8DrawString(). + This layer is used by X11 systems without Xft, and by MacOS / iOS. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef HAVE_XFT + +# include "utils.h" +# include "resources.h" +# include "xft.h" +# include "utf8wc.h" + +extern const char *progname; + +struct _XftDraw { + Display *dpy; + Drawable drawable; + GC gc; + unsigned long pixel; + Font fid; + Visual *visual; + Colormap colormap; +}; + + +XftFont * +XftFontOpenXlfd (Display *dpy, int screen, _Xconst char *xlfd) +{ + XftFont *ff = (XftFont *) calloc (1, sizeof(*ff)); + + if (!dpy || !xlfd) abort(); + if (!ff) return 0; + ff->xfont = XLoadQueryFont (dpy, xlfd); + if (!ff->xfont) + { + free (ff); + return 0; + } + + ff->name = strdup (xlfd); + ff->ascent = ff->xfont->ascent; + ff->descent = ff->xfont->descent; + ff->height = ff->ascent + ff->descent; + +# ifdef HAVE_XUTF8DRAWSTRING + { + unsigned i; + + // In the event of -*-random-* (under JWXYZ), get the actual XLFD, + // otherwise we'll get another random font that doesn't match ff->xfont. + char *xlfd_resolved = NULL; + + char **missing_charset_list_return; + int missing_charset_count_return; + char *def_string_return; + + char *ss; + + for (i = 0; i != ff->xfont->n_properties; ++i) { + if (ff->xfont->properties[i].name == XA_FONT) { + xlfd_resolved = XGetAtomName (dpy, ff->xfont->properties[i].card32); + if (xlfd_resolved) + xlfd = xlfd_resolved; + break; + } + } + + ss = (char *) malloc (strlen(xlfd) + 10); + strcpy (ss, xlfd); + strcat (ss, ",*"); + ff->fontset = XCreateFontSet (dpy, ss, + &missing_charset_list_return, + &missing_charset_count_return, + &def_string_return); + +# if 0 + { + int i; + for (i = 0; i < missing_charset_count_return; i++) + fprintf (stderr, "%s: missing charset: %s\n", + ss, missing_charset_list_return[i]); + } +# endif + + /* Apparently this is not to be freed. */ + /* if (def_string_return) XFree (def_string_return); */ + + if (missing_charset_list_return) + XFreeStringList (missing_charset_list_return); + + free (ss); + free (xlfd_resolved); + } +# endif + + return ff; +} + + +void +XftFontClose (Display *dpy, XftFont *font) +{ + if (!dpy || !font) abort(); + free (font->name); + XFreeFont (dpy, font->xfont); +# ifdef HAVE_XUTF8DRAWSTRING + XFreeFontSet (dpy, font->fontset); +# endif + free (font); +} + + +Bool +XftColorAllocName (Display *dpy, + _Xconst Visual *visual, + Colormap cmap, + _Xconst char *name, + XftColor *result) +{ + XColor color; + if (!dpy || !visual || !name || !result) abort(); + + if (! XParseColor (dpy, cmap, name, &color)) + { + fprintf (stderr, "%s: can't parse color %s", progname, name); + return False; + } + else if (! XAllocColor (dpy, cmap, &color)) + { + fprintf (stderr, "%s: couldn't allocate color %s", progname, name); + return False; + } + else + { + XRenderColor color2; + color2.red = color.red; + color2.green = color.green; + color2.blue = color.blue; + color2.alpha = 0xFFFF; + XftColorAllocValue (dpy, visual, cmap, &color2, result); + result->pixel = color.pixel; + return True; + } +} + + +static short +maskbase (unsigned long m) +{ + short i; + if (!m) + return 0; + i = 0; + while (! (m&1)) + { + m >>= 1; + i++; + } + return i; +} + + +static short +masklen (unsigned long m) +{ + unsigned long y; + y = (m >> 1) & 033333333333; + y = m - y - ((y >>1) & 033333333333); + return (short) (((y + (y >> 3)) & 030707070707) % 077); +} + + +Bool +XftColorAllocValue (Display *dpy, + _Xconst Visual *visual, + Colormap cmap, + _Xconst XRenderColor *color, + XftColor *result) +{ + if (!dpy || !visual || !color || !result) abort(); + if (visual->class == TrueColor) + { + int red_shift = maskbase (visual->red_mask); + int red_len = masklen (visual->red_mask); + int green_shift = maskbase (visual->green_mask); + int green_len = masklen (visual->green_mask); + int blue_shift = maskbase (visual->blue_mask); + int blue_len = masklen (visual->blue_mask); + result->pixel = (((color->red >> (16 - red_len)) << red_shift) | + ((color->green >> (16 - green_len)) << green_shift) | + ((color->blue >> (16 - blue_len)) << blue_shift)); +# ifdef HAVE_JWXYZ + result->pixel |= BlackPixel(dpy, 0); /* alpha */ +# endif + } + else + { + XColor xcolor; + xcolor.red = color->red; + xcolor.green = color->green; + xcolor.blue = color->blue; + if (!XAllocColor (dpy, cmap, &xcolor)) + return False; + result->pixel = xcolor.pixel; + } + result->color.red = color->red; + result->color.green = color->green; + result->color.blue = color->blue; + result->color.alpha = color->alpha; + return True; +} + + +void +XftColorFree (Display *dpy, + Visual *visual, + Colormap cmap, + XftColor *color) +{ + if (!dpy || !visual || !color) abort(); + if (visual->class != TrueColor) + XFreeColors (dpy, cmap, &color->pixel, 1, 0); +} + + +XftDraw * +XftDrawCreate (Display *dpy, + Drawable drawable, + Visual *visual, + Colormap colormap) +{ + XftDraw *dd = (XftDraw *) calloc (1, sizeof(*dd)); + if (!dpy || !drawable || !visual) abort(); + if (!dd) return 0; + + dd->dpy = dpy; + dd->drawable = drawable; + dd->visual = visual; + dd->colormap = colormap; + dd->gc = XCreateGC (dpy, drawable, 0, 0); + return dd; +} + + +void +XftDrawDestroy (XftDraw *draw) +{ + if (!draw) abort(); + XFreeGC (draw->dpy, draw->gc); + free (draw); +} + + +void +XftTextExtentsUtf8 (Display *dpy, + XftFont *font, + _Xconst FcChar8 *string, + int len, + XGlyphInfo *extents) +{ + XCharStruct overall; + + if (!dpy || !font || !string || !extents) abort(); + +# ifdef HAVE_XUTF8DRAWSTRING + { + XRectangle ink; + int advancement = + Xutf8TextExtents (font->fontset, (const char *) string, len, &ink, 0); + XmbRectangle_to_XCharStruct (ink, overall, advancement); + } +# else /* !HAVE_XUTF8DRAWSTRING */ + { + char *s2 = (char *) malloc (len + 1); + int direction, ascent, descent; + XChar2b *s16; + int s16_len = 0; + strncpy (s2, (char *) string, len); + s2[len] = 0; + s16 = utf8_to_XChar2b (s2, &s16_len); + XTextExtents16 (font->xfont, s16, s16_len, + &direction, &ascent, &descent, &overall); + free (s2); + free (s16); + } +# endif /* !HAVE_XUTF8DRAWSTRING */ + + XCharStruct_to_XGlyphInfo (overall, *extents); +} + + +void +XftDrawStringUtf8 (XftDraw *draw, + _Xconst XftColor *color, + XftFont *font, + int x, + int y, + _Xconst FcChar8 *string, + int len) +{ + if (!draw || !color || !font || !string) abort(); + + if (color->pixel != draw->pixel) + { + XSetForeground (draw->dpy, draw->gc, color->pixel); + draw->pixel = color->pixel; + } + if (font->xfont->fid != draw->fid) + { + XSetFont (draw->dpy, draw->gc, font->xfont->fid); + draw->fid = font->xfont->fid; + } + +# ifdef HAVE_XUTF8DRAWSTRING + /* If we have Xutf8DrawString, use it instead of XDrawString16 because + there is some chance it will handle characters of more than 16 bits + (beyond the Basic Multilingual Plane). + */ + + /* #### I guess I don't really understand how FontSet works, because when + using the real X11 implementation of Xutf8DrawString, this seems + to just truncate the text at the first non-ASCII character. + + The XDrawString16() path works, however, at the expense of losing + everything above Basic Multilingual. However, that path is only + taken on X11 systems that are old enough to not have libXft, + which means that the chance of Unicode working was already slim. + */ + Xutf8DrawString (draw->dpy, draw->drawable, font->fontset, draw->gc, x, y, + (const char *) string, len); +# else + { + int s16_len = 0; + char *s2 = (char *) malloc (len + 1); + XChar2b *s16; + strncpy (s2, (char *) string, len); + s2[len] = 0; + s16 = utf8_to_XChar2b (s2, &s16_len); + free (s2); + XDrawString16 (draw->dpy, draw->drawable, draw->gc, x, y, s16, s16_len); + free (s16); + } +# endif +} + +#else /* HAVE_XFT */ + +const int Wempty_translation_unit_is_a_dumb_warning = 0; + +#endif /* HAVE_XFT */ |