I find that XftDrawStringUtf8 can not draw color emoji. I test it with
those code:
#include <stdio.h>
#include <stdint.h>
#include <X11/Xlib.h>
#include <X11/Xft/Xft.h>
Display *display;
int screen;
Window root_win, win;
Colormap colormap;
Visual *visual;
int get_utf8_codepoint(const char *str, uint32_t *codepoint)
{
const uint8_t *p=(const uint8_t*)str;
int len=0;
if(*p < 0x80) // 1 byte char
len=1, *codepoint=*p;
else if((*p>>5) == 0x06) // 2 bytes char
len=2, *codepoint=(*p & 0x1F)<<6 | (*(p+1)
& 0x3F);
else if((*p>>4) == 0x0E) // 3 bytes char
len=3, *codepoint=(*p & 0x0F)<<12 | (*(p+1)
& 0x3F)<<6 | (*(p+2) & 0x3F);
else if((*p>>3) == 0x1E) // 4 bytes char
len=4, *codepoint=(*p & 0x07)<<18 | (*(p+1)
& 0x3F)<<12 | (*(p+2) & 0x3F)<<6 | (*(p+3) & 0x3F);
else // not utf8 char
len=0;
return len;
}
void draw_utf8_char(XftFont *font, const char *s, uint32_t codepoint, int len)
{
XftColor color;
XftColorAllocName(display, visual, colormap, "red", &color);
XftDraw *draw=XftDrawCreate(display, win, visual, colormap);
XftDrawStringUtf8(draw, &color, font, 50, 50, s, len);
XftDrawDestroy(draw);
}
void check_font(const char *s, const char *fontname)
{
XftFont *font=XftFontOpenName(display, screen, fontname);
if(font == NULL)
{
fprintf(stderr, "%s not exsit", fontname);
return;
}
uint32_t codepoint;
int len=get_utf8_codepoint(s, &codepoint);
if(XftCharExists(display, font, codepoint))
{
printf("'%s' in %s\n", s, fontname);
draw_utf8_char(font, s, codepoint, len);
}
else
printf("'%s' not in %s\n", s, fontname);
}
int main(int argc, char **argv)
{
display=XOpenDisplay(NULL);
screen=DefaultScreen(display);
root_win=RootWindow(display, screen);
visual=DefaultVisual(display, screen);
colormap=DefaultColormap(display, screen);
win=XCreateSimpleWindow(display, root_win, 0, 0, 100, 100, 2,
0x00ff00, 0);
XSelectInput(display, win, ExposureMask);
XMapWindow(display, win);
if(argc != 3)
{
fprintf(stderr, "usage: %s <char> [fontname]\n",
argv[0]);
exit(1);
}
XEvent e;
while(!XNextEvent(display, &e))
if(e.type == Expose)
check_font(argv[1], argv[2]);
return 0;
}
I tested it like that:
./a.out ?9?4 "Noto Color Emoji"
And can not draw ?9?4.
Those are software info:
libX11-devel-1.8.12-1.fc43.x86_64
libXft-devel-2.3.8-9.fc43.x86_64
google-noto-color-emoji-fonts-20250623-2.fc43.noarch
And the test code can draw color emoji at Fedora 41 and older version.
406643764
[email protected]