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

Passing character info to renderer #25

Open
dvj opened this issue Mar 17, 2021 · 2 comments
Open

Passing character info to renderer #25

dvj opened this issue Mar 17, 2021 · 2 comments
Assignees
Labels
enhancement New feature or request

Comments

@dvj
Copy link
Contributor

dvj commented Mar 17, 2021

Currently, imtui uses a modified ImFont::RenderText function where it inserts the ascii value of the character to be rendered in the alpha channel of the color (ImDrawVert.col). While this makes imtui possible, it requires a modification to imgui itself achieve, which makes long term maintenance an issue.

Here is a proposed way to pass the character values by using the coordinates in the font texture instead. Proof of concept code below.

    std::unordered_map<int, uint8_t> character_lookup; // <-- needs persistence: global, class var, function param, etc.
    auto io = ImGui::GetIO();

    // tell imgui we have lots of 1x1 custom character glyphs in the texture
    int ids[255]; //store the returned id's
    for (int i = 1;i<255;i++) {
      ids[i] = io.Fonts->AddCustomRectFontGlyph(font, i, 1,1,1);
    }

    // Build atlas [existing code block]
    unsigned char* tex_pixels = NULL;
    int tex_w, tex_h;
    ImGui::GetIO().Fonts->GetTexDataAsRGBA32(&tex_pixels, &tex_w, &tex_h);
  
    // store the texture coordinates in a hashmap
    for (int i = 1;i<255;i++) {
      //lookup the id we got, and get the texture coordinates (in integer pixel values)
      const ImFontAtlas::CustomRect* rect = io.Fonts->GetCustomRectByIndex(ids[i]);
      // store the texture index with the character value
      character_lookup[rect->X + rect->Y*rect->Width] = i;
    }

Then, in the render function, once it's determined this is a textured 1x1 glyph, read the position in the texture to get the character index:

    // get the texture scale (could be stored)
    ImVec2 font_scale = ImGuiIO().Fonts->TexUvScale;
    // uv coords are [0..1], remap to integer values that match the rect we got when storing
    int index = uv0.x/font_scale.x+uv0.y/font_scale.y;
    auto char_code = character_lookup[index];
    cell |= char_code;

I've tested this and it works without issue, with some error handling, etc. Posting here for input and ideas before making a PR.

I believe many of the other changes in the local fork of imgui can be resolved when the work on "style V2" commences. (See, for example, ocornut/imgui#2017)

@ggerganov
Copy link
Owner

Ok, that is pretty clever.

I'll let you know if I get some ideas about this, but at the moment your concept seems much better than the existing one.

@ggerganov ggerganov added the enhancement New feature or request label Nov 6, 2021
@ggerganov ggerganov self-assigned this Nov 11, 2021
@oktonion
Copy link
Contributor

Any progress on this?

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

No branches or pull requests

3 participants