Pango with xft renderer draws rectangles instead of spaces after Chinese characters.
Arch, X11, Pango 1.50.13.
Hello!
I am writing a simple UI for my program and use Pango with xft renderer for text rendering. I was just testing pango with random strings and found out that if a string contains Chinese characters then any spaces following these characters are drawn as unknown glyphs although fallback attribute is set for the layout. This is an example cpp code to demonstrate what I am describing:
pango-example.cpp
#include <X11/Xft/Xft.h>
#include <X11/Xlib.h>
#include <pango/pango.h>
#include <pango/pangoxft.h>
#include <chrono>
#include <string>
#include <thread>
int main()
{
Display* display{::XOpenDisplay(0)};
Screen* screen{::XDefaultScreenOfDisplay(display)};
int screen_number{::XDefaultScreen(display)};
::Window root{::XDefaultRootWindow(display)};
XftColor xft_color_foreground{};
XftColor xft_color_background{};
XftColorAllocName(display,
DefaultVisual(display, 0),
DefaultColormap(display, 0),
"#D0D0D0",
&xft_color_foreground);
XftColorAllocName(display,
DefaultVisual(display, 0),
DefaultColormap(display, 0),
"#242A33",
&xft_color_background);
::Window window = XCreateWindow(display,
root,
0,
0,
::XWidthOfScreen(screen),
::XHeightOfScreen(screen) / 2,
1,
::XDefaultDepthOfScreen(screen),
InputOutput,
::XDefaultVisualOfScreen(screen),
0,
nullptr);
::Pixmap pixmap = ::XCreatePixmap(display,
root,
::XWidthOfScreen(screen),
::XHeightOfScreen(screen) / 2,
::XDefaultDepthOfScreen(screen));
::XftDraw* xft_draw
= XftDrawCreate(display,
pixmap,
::XDefaultVisual(display, screen_number),
::XDefaultColormap(display, screen_number));
XftDrawRect(xft_draw,
&xft_color_background,
0,
0,
::XWidthOfScreen(screen),
::XHeightOfScreen(screen) / 2);
std::string test_string = "test 大大 大 是 是 的的不不 ";
std::string font_name = "Noto Sans 14";
::PangoFontDescription* font_description
= ::pango_font_description_from_string(font_name.c_str());
::PangoFontMap* font_map = ::pango_xft_get_font_map(display, screen_number);
::PangoContext* context = ::pango_font_map_create_context(font_map);
::PangoAttribute* enable_fallback = ::pango_attr_fallback_new(TRUE);
::PangoAttrList* attrs = ::pango_attr_list_new();
::pango_attr_list_insert(attrs, enable_fallback);
::PangoLayout* layout = ::pango_layout_new(context);
::pango_layout_set_font_description(layout, font_description);
::pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
::pango_layout_set_height(layout, 0);
::pango_layout_set_width(layout,
::pango_units_from_double(static_cast<double>(
::XWidthOfScreen(screen))));
::pango_layout_set_attributes(layout, attrs);
::pango_layout_set_text(layout, test_string.c_str(), test_string.size());
::pango_xft_render_layout(xft_draw, &xft_color_foreground, layout, 0, 0);
::XSetWindowBackgroundPixmap(display, window, pixmap);
::XClearWindow(display, window);
::XMapRaised(display, window);
::XSync(display, false);
std::this_thread::sleep_for(std::chrono::seconds(30));
// cleanup...
return 0;
}
The same results I see with pango-view --font "Noto Sans 14" --backend=xft -t '大 大 test 是 是 的 的 不 不 '
. However, that doesn't happen with --backend=cairo
. I don't know Chinese and used random characters here just for testing, but, as far as I know, there are no space character in Chinese which can explain why spaces are broken, but shouldn't fallback attribute for layout solve this problem by replacing broken glyphs with space glyphs from different font?
The interesting thing is that this issue is not reproducible with older Pango versions. I have tried multiple versions from Arch repos and found out that the problem occurs only with Pango >= 1.50.3. But everything is fine with 1.50.2 and lower. Below is the same example code from above with Pango 1.50.2:
All spaces are drawn correctly here.