如何从XftFont获取XFontStruct?X11可缩放时钟字体问题
解决方案:用Xft实现可缩放的X11时钟文本绘制
1. 修复XftDrawString的BadPicture错误
BadPicture错误几乎都是因为XftDraw对象创建不规范导致的。正确的创建方式需要和窗口的Visual、Colormap严格匹配:
// 基于当前窗口的默认Visual和Colormap创建XftDraw XftDraw* xft_draw = XftDrawCreate(dpy, window, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen));
绘制完成后务必销毁资源:
XftDrawDestroy(xft_draw);
不要手动创建Picture对象混用,Xft的绘图上下文需要单独管理。
2. 理清Xlib与Xft的绘图边界
不要在同一段绘图逻辑里混合Xlib的XSetForeground、XDrawString和Xft函数。建议拆分职责:
- 用Xlib绘制钟面的线条、指针等矢量图形
- 用Xft专门处理文本渲染,单独维护Xft的颜色和绘图对象
文本绘制示例代码
// 定义文本颜色(以白色为例) XftColor xft_color; XRenderColor render_color = {0xffff, 0xffff, 0xffff, 0xffff}; XftColorAllocValue(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), &render_color, &xft_color); // 创建Xft绘图上下文 XftDraw* draw = XftDrawCreate(dpy, window, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen)); // 动态加载对应字号的字体(字号可根据窗口尺寸计算) int font_size = MIN(window_width, window_height) / 12; char font_spec[64]; snprintf(font_spec, sizeof(font_spec), "Sans:size=%d", font_size); XftFont* font = XftFontOpenName(dpy, screen, font_spec); // 计算文本位置(以数字12为例,居中顶部) XftFontExtents* extents = XftFontExtents(dpy, font); int x_pos = (window_width - font->max_advance_width) / 2; int y_pos = extents->max_height; // 基线位置,可根据需求微调 // 绘制文本 XftDrawStringUtf8(draw, &xft_color, font, x_pos, y_pos, (FcChar8*)"12", strlen("12")); // 清理资源 XftFontClose(dpy, font); XftDrawDestroy(draw); XftColorFree(dpy, DefaultVisual(dpy, screen), DefaultColormap(dpy, screen), &xft_color);
3. 关于XftFont获取XFontStruct的说明
现代Xft库(2.x及以上)已经完全基于FreeType和XRender实现,不再依赖Xlib的传统字体系统,因此XftFont结构中不再包含直接的XFontStruct指针——xft(3)手册中的描述是针对旧版Xft 1.x的,现已过时。
如果坚持要用Xlib的XDrawString绘制缩放文本,有两个替代方向:
- 使用
XCreateFontSet加载可缩放字体(如Type1/TrueType),但灵活性远不如Xft - 通过XRender扩展手动渲染FreeType glyph,实现复杂度高,性价比低
4. 动态适配窗口大小的字号计算
根据窗口的最小边尺寸动态调整字号,保证数字始终适配钟面:
XWindowAttributes attr; XGetWindowAttributes(dpy, window, &attr); int min_edge = MIN(attr.width, attr.height); int font_size = min_edge / 12; // 可根据视觉效果调整比例
内容的提问来源于stack exchange,提问作者Lenik
相关产品推荐
相关产品推荐

