+int
+jwxyz_draw_string (Display *dpy, Drawable d, GC gc, int x, int y,
+ const char *str, size_t len, int utf8_p)
+{
+ const XGCValues *gcv = VTBL->gc_gcv (gc);
+ Font ff = gcv->font;
+ XCharStruct cs;
+
+ char *data = 0;
+ jwxyz_render_text (dpy, jwxyz_native_font (ff), str, len, utf8_p,
+ gcv->antialias_p, &cs, &data);
+ int w = cs.rbearing - cs.lbearing;
+ int h = cs.ascent + cs.descent;
+
+ if (w < 0 || h < 0) abort();
+ if (w == 0 || h == 0) {
+ if (data) free(data);
+ return 0;
+ }
+
+ XImage *img = XCreateImage (dpy, VTBL->visual (dpy), 32,
+ ZPixmap, 0, data, w, h, 0, 0);
+
+ /* The image of text is a 32-bit image, in white.
+ Take the green channel for intensity and use that as alpha.
+ replace RGB with the GC's foreground color.
+ This expects that XPutImage respects alpha and only writes
+ the bits that are not masked out.
+ */
+ {
+# define ROTL(x, rot) (((x) << ((rot) & 31)) | ((x) >> (32 - ((rot) & 31))))
+
+ const unsigned long *masks =
+ DefaultVisualOfScreen (DefaultScreenOfDisplay(dpy))->rgba_masks;
+ unsigned shift = (i_log2 (masks[3]) - i_log2 (masks[1])) & 31;
+ uint32_t mask = ROTL(masks[1], shift) & masks[3],
+ color = gcv->foreground & ~masks[3];
+ uint32_t *s = (uint32_t *)data;
+ uint32_t *end = s + (w * h);
+ while (s < end) {
+
+ *s = (ROTL(*s, shift) & mask) | color;
+ ++s;
+ }
+ }
+
+ {
+ Bool old_alpha = gcv->alpha_allowed_p;
+ jwxyz_XSetAlphaAllowed (dpy, gc, True);
+ XPutImage (dpy, d, gc, img, 0, 0,
+ x + cs.lbearing,
+ y - cs.ascent,
+ w, h);
+ jwxyz_XSetAlphaAllowed (dpy, gc, old_alpha);
+ XDestroyImage (img);
+ }
+
+ return 0;
+}
+
+