Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C string gets corrupted when passed to the TextCommand handler #53

Open
J-Cake opened this issue Oct 11, 2021 · 3 comments
Open

C string gets corrupted when passed to the TextCommand handler #53

J-Cake opened this issue Oct 11, 2021 · 3 comments

Comments

@J-Cake
Copy link

J-Cake commented Oct 11, 2021

I'm playing around with the demo program, and am noticing that the text rendering function receives a corrupt copy of the text to print. I've also noticed that the source it receives each time is different, meaning it's being corrupted along the way. It's received correctly in the text_width function, but I can't find where it could possibly become changed.

In short, my code is this:

void text(mu_TextCommand cmd) {
    std::string str = std::string(cmd.str);

    std::cout << str << std::endl; // Prints mangled copy

    cairo_select_font_face(cr, "raleway", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size(cr, 12.);
    cairo_set_source_rgba(cr, (double)cmd.color.r / 255, (double)cmd.color.g / 255, (double)cmd.color.b / 255, (double)cmd.color.a / 255);
    cairo_move_to(cr, cmd.pos.x, cmd.pos.y + text_height(cmd.font));
    cairo_text_path(cr, cmd.str);

    cairo_fill(cr);
}

...

int text_width(mu_Font font, const char *str, int len) {
    if (len == -1) len = strlen(str);

    std::cout << str << std::endl; // Prints correctly

    cairo_select_font_face(cr, "raleway", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
    cairo_set_font_size(cr, 12.);

    cairo_text_extents_t extents;
    cairo_text_extents(cr, str, &extents);

    return extents.width;
}

...

while (getElapsedTime(start) < 10) { // has it been 10s since the program started?
    mu_begin(ctx);

    cairo_set_source_rgba(cr, 1., 1., 1., 1.);
    cairo_rectangle(cr, 0, 0, dev->width, dev->height);
    cairo_fill(cr);

    if (mu_begin_window(ctx, window_title, mu_rect(10, 10, 720, 480))) {
        mu_label(ctx, window_title);

        mu_end_window(ctx);
    }

    mu_end(ctx);

    flush(ctx, dev);
}

I can't seem to find the source of the issue. My guess was some sort of memory overwriting, but I removed all memory management calls, and still got the same result.

Some details:

  • I've compiled microui as a shared library
  • I'm using C++ 20 with G++
  • I'm using the cairo library as a drawing backend.
@nlapinski
Copy link

Try and null terminate your strings. This worked for me implementing a renderer in GDI

void r_draw_text(const char* text, mu_Vec2 pos, mu_Color color) {
    char buff[1024] = { 0 };
    
    strcat(buff, text);
    strcat(buff, "\0");

    SelectObject(Memhdc, hFont);
    SetBkMode(Memhdc, TRANSPARENT);
    SetTextColor(Memhdc, RGB(color.r, color.g, color.b));
    ExtTextOutA(Memhdc, pos.x, pos.y, ETO_OPAQUE, NULL, (LPCSTR)buff, sizeof(text), NULL);

}

or since you are using C++ try a std::string and somestring.c_str() to retrieve the char*

I think it is indeed reading into the next byte and not terminating properly, I think this might how GDI (and maybe cairo?) are handling string termination.

@nlapinski
Copy link

image

aand the fix
image

@J-Cake
Copy link
Author

J-Cake commented Sep 13, 2022

I haven't had a chance to test this yet, but something tells me that'll do it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants