pango_layout_move_cursor_visually() Gets Stuck Between Runs in Bidirectional Text
I was working on a text editor, and I came across an issue with pango_layout_move_cursor_visually()
that seems to be a bug, but I could be doing something wrong.
When a weak cursor is in-between two runs, and the weak direction is LTR, the cursor cannot be moved to the left, away from the strong run. I wasn't able to recreate the issue when the weak direction is RTL, but I was able to create a code snippet that replicates the issue for me.
The Pango version is 1.51.1.
#include <pango/pangocairo.h>
#include <iostream>
#include <string>
#include <string_view>
int main(int argc, const char* argv[])
{
PangoFontMap* fontMap = pango_cairo_font_map_get_default();
PangoContext* context = pango_font_map_create_context(fontMap);
PangoLayout* layout = pango_layout_new(context);
//std::string_view text = "בּבּבּבּבּבּבּבּggg";
// I had to manually put in the char codes because MSVC was messing up the string contents
std::string_view text = "\xD7\x91\xD6\xBC\xD7\x91\xD6\xBC\xD7\x91\xD6\xBC\xD7\x91\xD6\xBC\xD7\x91\xD6\xBC\xD7\x91\xD6\xBC\xD7\x91\xD6\xBC\xD7\x91\xD6\xBCggg";
pango_layout_set_text(layout, text.data(), text.length());
//// render the text to make sure it looks right
//int width, height;
//pango_layout_get_size(layout, &width, &height);
//cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width / PANGO_SCALE, height / PANGO_SCALE);
//cairo_t* cr = cairo_create(surface);
//cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
//cairo_paint(cr);
//cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
//pango_cairo_show_layout(cr, layout);
//cairo_destroy(cr);
//cairo_surface_write_to_png(surface, "test.png");
//cairo_surface_destroy(surface);
// find the index of the first 'g'
int index = 0;
while (text[index] != 'g')
{
++index;
}
int trailing = 0;
// the cursor should be weak for this entire test,
// since we are only moving along the 'g' chars.
bool strong = false;
// move forward 3 positions visually
for (int i = 0; i < 3; ++i)
{
pango_layout_move_cursor_visually(layout, strong, index, trailing, +1, &index, &trailing);
}
// prints 34
std::cout << "index: " << (index == G_MAXINT ? "G_MAXINT" : std::to_string(index)) << std::endl;
// move backward 1 position visually
pango_layout_move_cursor_visually(layout, strong, index, trailing, -1, &index, &trailing);
// prints G_MAXINT (unable to move back)
std::cout << "index: " << (index == G_MAXINT ? "G_MAXINT" : std::to_string(index)) << std::endl;
g_object_unref(layout);
g_object_unref(context);
g_object_unref(fontMap);
return 0;
}
I have a workaround for now, which is to move the cursor forward one space to get a strong cursor, and then move back two spaces. I think that I am either misunderstanding something, or this isn't the intended behavior.
Any info or help on this issue would be very much appreciated!