From de16375903d207bc9ed66b7967c2ffeac9f7d2de Mon Sep 17 00:00:00 2001 From: WerWolv Date: Sat, 24 May 2025 22:32:08 +0200 Subject: [PATCH] impr: Slightly simplify subpixel rendering logic and required ImGui patches --- .../backend/source/imgui_impl_opengl3.cpp | 23 +---- .../imgui/imgui/source/imgui_draw.cpp | 19 ++-- plugins/fonts/source/font_loader.cpp | 93 +++++++++---------- 3 files changed, 62 insertions(+), 73 deletions(-) diff --git a/lib/third_party/imgui/backend/source/imgui_impl_opengl3.cpp b/lib/third_party/imgui/backend/source/imgui_impl_opengl3.cpp index 9a8e1aec2..6991e72ef 100644 --- a/lib/third_party/imgui/backend/source/imgui_impl_opengl3.cpp +++ b/lib/third_party/imgui/backend/source/imgui_impl_opengl3.cpp @@ -420,17 +420,13 @@ void ImGui_ImplOpenGL3_NewFrame() } // IMHEX PATCH BEGIN -bool useFontShaders = false; - -void FontShadersOn(const ImDrawList *parent_list, const ImDrawCmd *cmd) { +static bool useFontShaders = false; +void ImGui_ImplOpenGL3_TurnFontShadersOn(const ImDrawList *parent_list, const ImDrawCmd *cmd) { useFontShaders = true; } -void FontShadersOff(const ImDrawList *parent_list, const ImDrawCmd *cmd) { +void ImGui_ImplOpenGL3_TurnFontShadersOff(const ImDrawList *parent_list, const ImDrawCmd *cmd) { useFontShaders = false; } -ImDrawCallback ImGui_ImplOpenGL3_TurnFontShadersOn = &FontShadersOn; -ImDrawCallback ImGui_ImplOpenGL3_TurnFontShadersOff = &FontShadersOff; - // IMHEX PATCH END static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object) @@ -496,10 +492,9 @@ static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_wid // IMHEX PATCH END const float ortho_projection[4][4] = { - // IMHEX PATCH BEGIN + // IMHEX PATCH BEGIN { 2.0f/(R-L), 0.0f, Gamma, 0.0f }, - // { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, - // IMHEX PATCH END + // IMHEX PATCH END { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, { 0.0f, 0.0f, -1.0f, 0.0f }, { (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f }, @@ -639,14 +634,6 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); - // IMHEX PATCH BEGIN - else if (pcmd->UserCallback == ImGui_ImplOpenGL3_TurnFontShadersOn) { - ImGui_ImplOpenGL3_TurnFontShadersOn(cmd_list, pcmd); - ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); - } else if (pcmd->UserCallback == ImGui_ImplOpenGL3_TurnFontShadersOff) { - ImGui_ImplOpenGL3_TurnFontShadersOff(cmd_list, pcmd); - ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object); - } // IMHEX PATCH END else pcmd->UserCallback(cmd_list, pcmd); } diff --git a/lib/third_party/imgui/imgui/source/imgui_draw.cpp b/lib/third_party/imgui/imgui/source/imgui_draw.cpp index 4ef332140..9ab4db2e8 100644 --- a/lib/third_party/imgui/imgui/source/imgui_draw.cpp +++ b/lib/third_party/imgui/imgui/source/imgui_draw.cpp @@ -1695,10 +1695,7 @@ void ImDrawList::AddBezierQuadratic(const ImVec2& p1, const ImVec2& p2, const Im PathBezierQuadraticCurveTo(p2, p3, num_segments); PathStroke(col, 0, thickness); } -// IMHEX PATCH BEGIN -extern ImDrawCallback ImGui_ImplOpenGL3_TurnFontShadersOn; -extern ImDrawCallback ImGui_ImplOpenGL3_TurnFontShadersOff; -// IMHEX PATCH END + void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 col, const char* text_begin, const char* text_end, float wrap_width, const ImVec4* cpu_fine_clip_rect) { if ((col & IM_COL32_A_MASK) == 0) @@ -1732,15 +1729,21 @@ void ImDrawList::AddText(ImFont* font, float font_size, const ImVec2& pos, ImU32 flags = font->ContainerAtlas->FontBuilderFlags; is_subpixel = (flags & ImGuiFreeTypeBuilderFlags_SubPixel) != 0; } - if (is_subpixel) + + void ImGui_ImplOpenGL3_TurnFontShadersOn(const ImDrawList *parent_list, const ImDrawCmd *cmd); + void ImGui_ImplOpenGL3_TurnFontShadersOff(const ImDrawList *parent_list, const ImDrawCmd *cmd); + + if (is_subpixel) { AddCallback(ImGui_ImplOpenGL3_TurnFontShadersOn, NULL); - // IMHEX PATCH END + AddCallback(ImDrawCallback_ResetRenderState, NULL); + } font->RenderText(this, font_size, pos, col, clip_rect, text_begin, text_end, wrap_width, cpu_fine_clip_rect != NULL); - // IMHEX PATCH BEGIN - if (is_subpixel) + if (is_subpixel) { AddCallback(ImGui_ImplOpenGL3_TurnFontShadersOff, NULL); + AddCallback(ImDrawCallback_ResetRenderState, NULL); + } // IMHEX PATCH END } diff --git a/plugins/fonts/source/font_loader.cpp b/plugins/fonts/source/font_loader.cpp index 1fcb9ebeb..6994c284a 100644 --- a/plugins/fonts/source/font_loader.cpp +++ b/plugins/fonts/source/font_loader.cpp @@ -37,96 +37,95 @@ namespace hex::fonts { log::fatal("No font data found"); return false; } else { - ImVector rect_ids; - std::map bitmapLCD; - ImU32 fontCount = io.Fonts->ConfigData.Size; - for (ImU32 i = 0; i < fontCount; i++) { - const auto config = io.Fonts->ConfigData[i]; + ImVector customRectIds; + std::map customRectBitmaps; + for (const auto &config : io.Fonts->ConfigData) { const auto &fontName = config.Name; if (hex::equalsIgnoreCase(fontName, "nonscalable")) { continue; } - if (FT_New_Memory_Face(ft, reinterpret_cast(io.Fonts->ConfigData[i].FontData), io.Fonts->ConfigData[i].FontDataSize, 0, &face) != 0) { + if (FT_New_Memory_Face(ft, static_cast(config.FontData), config.FontDataSize, 0, &face) != 0) { log::fatal("Failed to load face"); return false; } - FT_Size_RequestRec req; - req.type = FT_SIZE_REQUEST_TYPE_REAL_DIM; - req.width = 0; - req.height = (uint32_t)(IM_ROUND(config.SizePixels) * 64.0F); - req.horiResolution = 0; - req.vertResolution = 0; - FT_Request_Size(face, &req); + FT_Size_RequestRec request; + request.type = FT_SIZE_REQUEST_TYPE_REAL_DIM; + request.width = 0; + request.height = (uint32_t)(IM_ROUND(config.SizePixels) * 64.0F); + request.horiResolution = 0; + request.vertResolution = 0; + FT_Request_Size(face, &request); - FT_UInt gIndex; - FT_ULong charCode = FT_Get_First_Char(face, &gIndex); + FT_UInt glyphIndex; + FT_ULong charCode = FT_Get_First_Char(face, &glyphIndex); - while (gIndex != 0) { - FT_UInt glyph_index = FT_Get_Char_Index(face, charCode); - if (FT_Load_Glyph(face, glyph_index, FT_LOAD_TARGET_LCD | FT_LOAD_TARGET_LIGHT | FT_LOAD_RENDER) != 0) { + while (glyphIndex != 0) { + if (FT_Load_Glyph(face, glyphIndex, FT_LOAD_TARGET_LCD | FT_LOAD_TARGET_LIGHT | FT_LOAD_RENDER) != 0) { IM_ASSERT(true && "Failed to load glyph"); return false; } - ft::Bitmap bitmap_lcd = ft::Bitmap(face->glyph->bitmap.width, face->glyph->bitmap.rows, face->glyph->bitmap.pitch, face->glyph->bitmap.buffer); + const ft::Bitmap bitmap = ft::Bitmap(face->glyph->bitmap.width, face->glyph->bitmap.rows, face->glyph->bitmap.pitch, face->glyph->bitmap.buffer); if (face->glyph->bitmap.width * face->glyph->bitmap.rows == 0) { - charCode = FT_Get_Next_Char(face, charCode, &gIndex); + charCode = FT_Get_Next_Char(face, charCode, &glyphIndex); continue; } - auto width = bitmap_lcd.getWidth() / 3.0F; - auto height = bitmap_lcd.getHeight(); - FT_GlyphSlot slot = face->glyph; - FT_Size size = face->size; + const auto width = bitmap.getWidth() / 3.0F; + const auto height = bitmap.getHeight(); + const auto slot = face->glyph; + const auto size = face->size; - ImVec2 offset = ImVec2(face->glyph->bitmap_left, -face->glyph->bitmap_top); + auto offset = ImVec2(face->glyph->bitmap_left, -face->glyph->bitmap_top); offset.x += config.GlyphOffset.x; offset.y += size->metrics.ascender / 64.0F; - ImS32 advance = (float) slot->advance.x / 64.0F; - ImS32 rect_id = io.Fonts->AddCustomRectFontGlyph(io.Fonts->Fonts[0], charCode, width, height, advance, offset); - rect_ids.push_back(rect_id); - bitmapLCD.insert(std::make_pair(rect_id, bitmap_lcd)); - charCode = FT_Get_Next_Char(face, charCode, &gIndex); + const ImS32 advance = slot->advance.x / 64.0F; + + ImS32 rectId = io.Fonts->AddCustomRectFontGlyph(io.Fonts->Fonts[0], charCode, width, height, advance, offset); + customRectIds.push_back(rectId); + customRectBitmaps.insert(std::make_pair(rectId, bitmap)); + + charCode = FT_Get_Next_Char(face, charCode, &glyphIndex); } FT_Done_Face(face); } + fontAtlas->getAtlas()->FontBuilderFlags |= ImGuiFreeTypeBuilderFlags_SubPixel; if (!fontAtlas->build()) return false; - ImU8 *tex_pixels_ch = nullptr; - ImS32 tex_width; + ImU8 *textureColors = nullptr; + ImS32 textureWidth, textureHeight; - ImS32 tex_height; - fontAtlas->getAtlas()->GetTexDataAsRGBA32(&tex_pixels_ch, &tex_width, &tex_height); - ImU32 *tex_pixels = reinterpret_cast(tex_pixels_ch); - for (auto rect_id: rect_ids) { + fontAtlas->getAtlas()->GetTexDataAsRGBA32(&textureColors, &textureWidth, &textureHeight); + auto *texturePixels = reinterpret_cast(textureColors); + for (auto rect_id: customRectIds) { if (const ImFontAtlasCustomRect *rect = io.Fonts->GetCustomRectByIndex(rect_id)) { - if (rect->X == 0xFFFF || rect->Y == 0xFFFF || !bitmapLCD.contains(rect_id)) + if (rect->X == 0xFFFF || rect->Y == 0xFFFF || !customRectBitmaps.contains(rect_id)) continue; - ft::Bitmap bitmapLCDSaved = bitmapLCD.at(rect_id); - ImU32 imageWidth = bitmapLCDSaved.getWidth() / 3; - ImU32 imageHeight = bitmapLCDSaved.getHeight(); - const ImU8 *bitmapBuffer = bitmapLCDSaved.getData(); + const auto &bitmap = customRectBitmaps.at(rect_id); + ImU32 imageWidth = bitmap.getWidth() / 3; + ImU32 imageHeight = bitmap.getHeight(); + const auto &bitmapBuffer = bitmap.getData(); for (ImU32 y = 0; y < imageHeight; y++) { - ImU32 *p = tex_pixels + (rect->Y + y) * tex_width + (rect->X); + ImU32 *pixel = texturePixels + (rect->Y + y) * textureWidth + (rect->X); for (ImU32 x = 0; x < imageWidth; x++) { - const ImU8 *bitmapPtrLCD = &bitmapBuffer[y * bitmapLCDSaved.getPitch() + 3 * x]; - *p++ = ft::RGBA::addAlpha(*bitmapPtrLCD, *(bitmapPtrLCD + 1), *(bitmapPtrLCD + 2)); + const ImU8 *bitmapPixel = &bitmapBuffer[y * bitmap.getPitch() + 3 * x]; + *pixel++ = ft::RGBA::addAlpha(*bitmapPixel, *(bitmapPixel + 1), *(bitmapPixel + 2)); } } } } - for (i64 i = 0; i < tex_width * tex_height; i++) { - if (tex_pixels[i] == 0x00FFFFFF) { - tex_pixels[i] = 0x00000000; + for (i64 i = 0; i < textureWidth * textureHeight; i++) { + if (texturePixels[i] == 0x00FFFFFF) { + texturePixels[i] = 0x00000000; } }