From 2babfb402663c91e51a9b6645e66850a51679ef5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 16:43:50 +0000 Subject: [PATCH 01/20] Initial plan From 29d4aaf53f32ba3f5827ac9761b3b0f9f4be5977 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 17:22:49 +0000 Subject: [PATCH 02/20] Add ege_setfont implementation with GDI+ Font support Co-authored-by: wysaid <1430725+wysaid@users.noreply.github.com> --- demo/test_ege_setfont.cpp | 73 +++++++++++++++++++++ include/ege.h | 42 ++++++++++++ include/ege.zh_CN.h | 42 ++++++++++++ src/font.cpp | 135 +++++++++++++++++++++++++++++--------- src/image.cpp | 5 ++ src/image.h | 1 + 6 files changed, 267 insertions(+), 31 deletions(-) create mode 100644 demo/test_ege_setfont.cpp diff --git a/demo/test_ege_setfont.cpp b/demo/test_ege_setfont.cpp new file mode 100644 index 00000000..106f048f --- /dev/null +++ b/demo/test_ege_setfont.cpp @@ -0,0 +1,73 @@ +/* + * Test demo for ege_setfont function + * This demo demonstrates the use of floating-point font sizes with GDI+ + */ + +#include +#include + +int main() +{ + // Initialize graphics window + initgraph(800, 600); + setbkcolor(WHITE); + cleardevice(); + + // Test 1: Basic ege_setfont with floating-point size + settextcolor(BLACK); + ege_setfont(24.5f, L"Arial"); + ege_drawtext(L"24.5pt Arial font (floating-point size)", 50.0f, 50.0f); + + // Test 2: Different sizes to show precision + ege_setfont(12.0f, L"Times New Roman"); + ege_drawtext(L"12.0pt Times New Roman", 50.0f, 100.0f); + + ege_setfont(12.5f, L"Times New Roman"); + ege_drawtext(L"12.5pt Times New Roman", 50.0f, 120.0f); + + ege_setfont(13.0f, L"Times New Roman"); + ege_drawtext(L"13.0pt Times New Roman", 50.0f, 140.0f); + + // Test 3: With font styles + ege_setfont(20.0f, L"Arial", FontStyleBold); + ege_drawtext(L"20pt Arial Bold", 50.0f, 200.0f); + + ege_setfont(18.0f, L"Arial", FontStyleItalic); + ege_drawtext(L"18pt Arial Italic", 50.0f, 240.0f); + + ege_setfont(16.0f, L"Arial", FontStyleBold | FontStyleItalic); + ege_drawtext(L"16pt Arial Bold Italic", 50.0f, 280.0f); + + ege_setfont(14.0f, L"Arial", FontStyleUnderline); + ege_drawtext(L"14pt Arial Underline", 50.0f, 320.0f); + + // Test 4: Very precise sizes + ege_setfont(15.25f, L"Courier New"); + ege_drawtext(L"15.25pt Courier New (very precise)", 50.0f, 380.0f); + + // Test 5: Chinese characters with floating-point size + ege_setfont(22.5f, L"SimSun"); + ege_drawtext(L"22.5点宋体 - 中文测试", 50.0f, 430.0f); + + // Test 6: Compare with measuretext + float width, height; + const wchar_t* testText = L"Test measuretext with GDI+ Font"; + ege_setfont(18.0f, L"Arial"); + measuretext(testText, &width, &height); + + char info[256]; + sprintf(info, "Width: %.2f, Height: %.2f", width, height); + ege_drawtext(testText, 50.0f, 480.0f); + ege_setfont(12.0f, L"Arial"); + ege_drawtext(info, 50.0f, 510.0f); + + // Instructions + ege_setfont(14.0f, L"Arial"); + settextcolor(BLUE); + ege_drawtext(L"Press any key to exit...", 50.0f, 550.0f); + + // Wait for key press + getch(); + closegraph(); + return 0; +} diff --git a/include/ege.h b/include/ege.h index 4e9aac3b..afbb6c3e 100644 --- a/include/ege.h +++ b/include/ege.h @@ -3996,6 +3996,48 @@ void EGEAPI setfont(const LOGFONTA *font, PIMAGE pimg = NULL); EGE_DEPRECATE(getfont, "Please use the 'getfont' function with the LOGFONTW* parameter instead.") void EGEAPI getfont(LOGFONTA *font, PCIMAGE pimg = NULL); +/** + * @brief Set font for GDI+ text rendering with floating-point size + * @param size Font size in ems (floating-point), supports fractional values for precise sizing + * @param typeface Font family name + * @param pimg Target image pointer, NULL means current ege window + * @note This function creates a GDI+ Font directly, allowing floating-point font sizes. + * When set, ege_drawtext will use this GDI+ font instead of converting from GDI HFONT. + */ +void EGEAPI ege_setfont(float size, const char* typeface, PIMAGE pimg = NULL); + +/** + * @brief Set font for GDI+ text rendering with floating-point size (Unicode) + * @param size Font size in ems (floating-point), supports fractional values for precise sizing + * @param typeface Font family name + * @param pimg Target image pointer, NULL means current ege window + * @note This function creates a GDI+ Font directly, allowing floating-point font sizes. + * When set, ege_drawtext will use this GDI+ font instead of converting from GDI HFONT. + */ +void EGEAPI ege_setfont(float size, const wchar_t* typeface, PIMAGE pimg = NULL); + +/** + * @brief Set font for GDI+ text rendering with floating-point size and style + * @param size Font size in ems (floating-point), supports fractional values for precise sizing + * @param typeface Font family name + * @param style Font style (combination of Gdiplus::FontStyle flags: FontStyleBold, FontStyleItalic, etc.) + * @param pimg Target image pointer, NULL means current ege window + * @note This function creates a GDI+ Font directly, allowing floating-point font sizes and GDI+ font styles. + * When set, ege_drawtext will use this GDI+ font instead of converting from GDI HFONT. + */ +void EGEAPI ege_setfont(float size, const char* typeface, int style, PIMAGE pimg = NULL); + +/** + * @brief Set font for GDI+ text rendering with floating-point size and style (Unicode) + * @param size Font size in ems (floating-point), supports fractional values for precise sizing + * @param typeface Font family name + * @param style Font style (combination of Gdiplus::FontStyle flags: FontStyleBold, FontStyleItalic, etc.) + * @param pimg Target image pointer, NULL means current ege window + * @note This function creates a GDI+ Font directly, allowing floating-point font sizes and GDI+ font styles. + * When set, ege_drawtext will use this GDI+ font instead of converting from GDI HFONT. + */ +void EGEAPI ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg = NULL); + /// @} #define getmaxx getwidth diff --git a/include/ege.zh_CN.h b/include/ege.zh_CN.h index a22561a4..58c933ec 100644 --- a/include/ege.zh_CN.h +++ b/include/ege.zh_CN.h @@ -3991,6 +3991,48 @@ void EGEAPI setfont(const LOGFONTA *font, PIMAGE pimg = NULL); EGE_DEPRECATE(getfont, "Please use the 'getfont' function with the LOGFONTW* parameter instead.") void EGEAPI getfont(LOGFONTA *font, PCIMAGE pimg = NULL); +/** + * @brief 设置用于GDI+文字渲染的浮点数大小字体 + * @param size 字体大小(单位:em,浮点数),支持小数以实现精确的字体大小 + * @param typeface 字体名称 + * @param pimg 目标图像指针,NULL 表示当前ege窗口 + * @note 此函数直接创建GDI+ Font,允许使用浮点数字体大小。 + * 设置后,ege_drawtext将使用此GDI+字体,而不是从GDI HFONT转换。 + */ +void EGEAPI ege_setfont(float size, const char* typeface, PIMAGE pimg = NULL); + +/** + * @brief 设置用于GDI+文字渲染的浮点数大小字体(Unicode版本) + * @param size 字体大小(单位:em,浮点数),支持小数以实现精确的字体大小 + * @param typeface 字体名称 + * @param pimg 目标图像指针,NULL 表示当前ege窗口 + * @note 此函数直接创建GDI+ Font,允许使用浮点数字体大小。 + * 设置后,ege_drawtext将使用此GDI+字体,而不是从GDI HFONT转换。 + */ +void EGEAPI ege_setfont(float size, const wchar_t* typeface, PIMAGE pimg = NULL); + +/** + * @brief 设置用于GDI+文字渲染的浮点数大小和样式字体 + * @param size 字体大小(单位:em,浮点数),支持小数以实现精确的字体大小 + * @param typeface 字体名称 + * @param style 字体样式(Gdiplus::FontStyle标志的组合:FontStyleBold、FontStyleItalic等) + * @param pimg 目标图像指针,NULL 表示当前ege窗口 + * @note 此函数直接创建GDI+ Font,允许使用浮点数字体大小和GDI+字体样式。 + * 设置后,ege_drawtext将使用此GDI+字体,而不是从GDI HFONT转换。 + */ +void EGEAPI ege_setfont(float size, const char* typeface, int style, PIMAGE pimg = NULL); + +/** + * @brief 设置用于GDI+文字渲染的浮点数大小和样式字体(Unicode版本) + * @param size 字体大小(单位:em,浮点数),支持小数以实现精确的字体大小 + * @param typeface 字体名称 + * @param style 字体样式(Gdiplus::FontStyle标志的组合:FontStyleBold、FontStyleItalic等) + * @param pimg 目标图像指针,NULL 表示当前ege窗口 + * @note 此函数直接创建GDI+ Font,允许使用浮点数字体大小和GDI+字体样式。 + * 设置后,ege_drawtext将使用此GDI+字体,而不是从GDI HFONT转换。 + */ +void EGEAPI ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg = NULL); + /// @} #define getmaxx getwidth diff --git a/src/font.cpp b/src/font.cpp index c5087057..bf9654f9 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -325,8 +325,16 @@ void measuretext(const wchar_t* text, float* width, float* height, PCIMAGE pimg) if (!isEmpty(text) && img && img->m_hDC) { using namespace Gdiplus; - HFONT hFont = (HFONT)GetCurrentObject(img->m_hDC, OBJ_FONT); - Font font(img->m_hDC, hFont); + // Use stored GDI+ font if available, otherwise create from GDI HFONT + Font* fontPtr = NULL; + bool useStoredFont = (img->m_font != NULL); + + if (useStoredFont) { + fontPtr = img->m_font; + } else { + HFONT hFont = (HFONT)GetCurrentObject(img->m_hDC, OBJ_FONT); + fontPtr = new Font(img->m_hDC, hFont); + } Graphics graphics(img->m_hDC); @@ -345,7 +353,7 @@ void measuretext(const wchar_t* text, float* width, float* height, PCIMAGE pimg) Gdiplus::RectF layoutRect(0, 0, 65535, 65535); Region region; - if (graphics.MeasureCharacterRanges(text, textLength, &font, layoutRect, format, 1, ®ion) == Ok) { + if (graphics.MeasureCharacterRanges(text, textLength, fontPtr, layoutRect, format, 1, ®ion) == Ok) { Gdiplus::RectF boundRect; if (region.GetBounds(&boundRect, &graphics) == Ok) { textWidth = boundRect.Width; @@ -354,6 +362,11 @@ void measuretext(const wchar_t* text, float* width, float* height, PCIMAGE pimg) } delete format; + + // Clean up temporary font if created + if (!useStoredFont) { + delete fontPtr; + } } if (width != NULL) @@ -785,17 +798,24 @@ static void ege_drawtext_p(const wchar_t* textstring, float x, float y, PIMAGE i using namespace Gdiplus; Gdiplus::Graphics* graphics = img->getGraphics(); - HFONT hf = (HFONT)GetCurrentObject(img->m_hDC, OBJ_FONT); - LOGFONTW lf; - GetObjectW(hf, sizeof(LOGFONTW), &lf); - if (wcscmp(lf.lfFaceName, L"System") == 0) { - hf = (HFONT)GetStockObject(DEFAULT_GUI_FONT); + // Use stored GDI+ font if available, otherwise create from GDI HFONT + Gdiplus::Font* fontPtr = NULL; + bool useStoredFont = (img->m_font != NULL); + + if (useStoredFont) { + fontPtr = img->m_font; + } else { + HFONT hf = (HFONT)GetCurrentObject(img->m_hDC, OBJ_FONT); + LOGFONTW lf; + GetObjectW(hf, sizeof(LOGFONTW), &lf); + if (wcscmp(lf.lfFaceName, L"System") == 0) { + hf = (HFONT)GetStockObject(DEFAULT_GUI_FONT); + } + fontPtr = new Gdiplus::Font(img->m_hDC, hf); } - Gdiplus::Font font(img->m_hDC, hf); - - // if (!font.IsAvailable()) { - // fprintf(stderr, "!font.IsAvailable(), hf: %p\n", hf); + // if (!fontPtr->IsAvailable()) { + // fprintf(stderr, "!fontPtr->IsAvailable()\n"); // } Gdiplus::PointF origin(x, y); Gdiplus::SolidBrush brush(img->m_textcolor); @@ -823,25 +843,32 @@ static void ege_drawtext_p(const wchar_t* textstring, float x, float y, PIMAGE i float xScale = 1.0f, angle = 0.0f; - if (lf.lfWidth != 0) { - LONG fixedWidth = lf.lfWidth; - float tmp; - float textCurrentWidth; - measuretext(textstring, &textCurrentWidth, &tmp, img); - lf.lfWidth = 0; - setfont(&lf, img); - float textNormalWidth; - measuretext(textstring, &textNormalWidth, &tmp, img); - lf.lfWidth = fixedWidth; - setfont(&lf, img); - - if ((int)textCurrentWidth != (int)textNormalWidth && ((int)textCurrentWidth != 0) && ((int)textNormalWidth != 0)) { - xScale = textCurrentWidth / textNormalWidth; + // Only apply width scaling and escapement for GDI fonts (not for stored GDI+ fonts) + if (!useStoredFont) { + LOGFONTW lf; + HFONT hf = (HFONT)GetCurrentObject(img->m_hDC, OBJ_FONT); + GetObjectW(hf, sizeof(LOGFONTW), &lf); + + if (lf.lfWidth != 0) { + LONG fixedWidth = lf.lfWidth; + float tmp; + float textCurrentWidth; + measuretext(textstring, &textCurrentWidth, &tmp, img); + lf.lfWidth = 0; + setfont(&lf, img); + float textNormalWidth; + measuretext(textstring, &textNormalWidth, &tmp, img); + lf.lfWidth = fixedWidth; + setfont(&lf, img); + + if ((int)textCurrentWidth != (int)textNormalWidth && ((int)textCurrentWidth != 0) && ((int)textNormalWidth != 0)) { + xScale = textCurrentWidth / textNormalWidth; + } } - } - if (lf.lfEscapement % 3600 != 0) { - angle = (float)(-lf.lfEscapement / 10.0); + if (lf.lfEscapement % 3600 != 0) { + angle = (float)(-lf.lfEscapement / 10.0); + } } if ((xScale != 1.0) || (angle != 0.0f)) { @@ -857,13 +884,59 @@ static void ege_drawtext_p(const wchar_t* textstring, float x, float y, PIMAGE i graphics->ScaleTransform(xScale, 1.0f); } - graphics->DrawString(textstring, -1, &font, Gdiplus::PointF(0, 0), format, &brush); + graphics->DrawString(textstring, -1, fontPtr, Gdiplus::PointF(0, 0), format, &brush); graphics->SetTransform(&oldTransformMatrix); } else { - graphics->DrawString(textstring, -1, &font, origin, format, &brush); + graphics->DrawString(textstring, -1, fontPtr, origin, format, &brush); } delete format; + + // Clean up temporary font if created + if (!useStoredFont) { + delete fontPtr; + } +} + +void ege_setfont(float size, const char* typeface, PIMAGE pimg) +{ + const std::wstring& wFace = mb2w(typeface); + ege_setfont(size, wFace.c_str(), pimg); +} + +void ege_setfont(float size, const wchar_t* typeface, PIMAGE pimg) +{ + ege_setfont(size, typeface, Gdiplus::FontStyleRegular, pimg); +} + +void ege_setfont(float size, const char* typeface, int style, PIMAGE pimg) +{ + const std::wstring& wFace = mb2w(typeface); + ege_setfont(size, wFace.c_str(), style, pimg); +} + +void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) +{ + PIMAGE img = CONVERT_IMAGE(pimg); + if (img) { + // Delete existing GDI+ font if any + if (img->m_font != NULL) { + delete img->m_font; + img->m_font = NULL; + } + + // Create GDI+ FontFamily + Gdiplus::FontFamily fontFamily(typeface); + + // If the font family is not available, try to use a default font + if (!fontFamily.IsAvailable()) { + fontFamily = Gdiplus::FontFamily(L"SimSun"); + } + + // Create new GDI+ Font with floating-point size + img->m_font = new Gdiplus::Font(&fontFamily, size, style, Gdiplus::UnitPoint); + } + CONVERT_IMAGE_END; } } // namespace ege diff --git a/src/image.cpp b/src/image.cpp index a5c29281..a742f9a9 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -58,6 +58,7 @@ void IMAGE::reset() m_graphics = NULL; m_pen = NULL; m_brush = NULL; + m_font = NULL; #endif } @@ -184,6 +185,10 @@ int IMAGE::deleteimage() delete m_brush; } m_brush = NULL; + if (NULL != m_font) { + delete m_font; + } + m_font = NULL; #endif HBITMAP hbmp = (HBITMAP)GetCurrentObject(m_hDC, OBJ_BITMAP); diff --git a/src/image.h b/src/image.h index b0106015..e0c76806 100644 --- a/src/image.h +++ b/src/image.h @@ -98,6 +98,7 @@ class IMAGE Gdiplus::Graphics* m_graphics; Gdiplus::Pen* m_pen; Gdiplus::Brush* m_brush; + Gdiplus::Font* m_font; #endif bool m_aa; void initimage(HDC refDC, int width, int height); From ee4b9e0c5922dc9ff013382dcacfeed278485e3d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 17:23:59 +0000 Subject: [PATCH 03/20] Address code review feedback: improve font fallback and fix sprintf Co-authored-by: wysaid <1430725+wysaid@users.noreply.github.com> --- demo/test_ege_setfont.cpp | 2 +- src/font.cpp | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/demo/test_ege_setfont.cpp b/demo/test_ege_setfont.cpp index 106f048f..68e52671 100644 --- a/demo/test_ege_setfont.cpp +++ b/demo/test_ege_setfont.cpp @@ -56,7 +56,7 @@ int main() measuretext(testText, &width, &height); char info[256]; - sprintf(info, "Width: %.2f, Height: %.2f", width, height); + snprintf(info, sizeof(info), "Width: %.2f, Height: %.2f", width, height); ege_drawtext(testText, 50.0f, 480.0f); ege_setfont(12.0f, L"Arial"); ege_drawtext(info, 50.0f, 510.0f); diff --git a/src/font.cpp b/src/font.cpp index bf9654f9..7e7bcdd1 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -930,11 +930,25 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) // If the font family is not available, try to use a default font if (!fontFamily.IsAvailable()) { - fontFamily = Gdiplus::FontFamily(L"SimSun"); + // Try common fallback fonts in order + fontFamily = Gdiplus::FontFamily(L"Arial"); + if (!fontFamily.IsAvailable()) { + fontFamily = Gdiplus::FontFamily(L"SimSun"); + } } // Create new GDI+ Font with floating-point size - img->m_font = new Gdiplus::Font(&fontFamily, size, style, Gdiplus::UnitPoint); + Gdiplus::Font* newFont = new Gdiplus::Font(&fontFamily, size, style, Gdiplus::UnitPoint); + + // Validate the created font before storing it + if (newFont != NULL && newFont->IsAvailable()) { + img->m_font = newFont; + } else { + // Font creation failed, clean up and don't store + if (newFont != NULL) { + delete newFont; + } + } } CONVERT_IMAGE_END; } From 08f03742a3b15f1cc29efe2c794579eb31cca83a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 17:25:53 +0000 Subject: [PATCH 04/20] Fix demo to use proper GDI+ constants and improve font fallback Co-authored-by: wysaid <1430725+wysaid@users.noreply.github.com> --- demo/test_ege_setfont.cpp | 12 ++++++------ src/font.cpp | 16 ++++++++++++---- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/demo/test_ege_setfont.cpp b/demo/test_ege_setfont.cpp index 68e52671..8113185b 100644 --- a/demo/test_ege_setfont.cpp +++ b/demo/test_ege_setfont.cpp @@ -29,16 +29,16 @@ int main() ege_drawtext(L"13.0pt Times New Roman", 50.0f, 140.0f); // Test 3: With font styles - ege_setfont(20.0f, L"Arial", FontStyleBold); + ege_setfont(20.0f, L"Arial", Gdiplus::FontStyleBold); ege_drawtext(L"20pt Arial Bold", 50.0f, 200.0f); - ege_setfont(18.0f, L"Arial", FontStyleItalic); + ege_setfont(18.0f, L"Arial", Gdiplus::FontStyleItalic); ege_drawtext(L"18pt Arial Italic", 50.0f, 240.0f); - ege_setfont(16.0f, L"Arial", FontStyleBold | FontStyleItalic); + ege_setfont(16.0f, L"Arial", Gdiplus::FontStyleBold | Gdiplus::FontStyleItalic); ege_drawtext(L"16pt Arial Bold Italic", 50.0f, 280.0f); - ege_setfont(14.0f, L"Arial", FontStyleUnderline); + ege_setfont(14.0f, L"Arial", Gdiplus::FontStyleUnderline); ege_drawtext(L"14pt Arial Underline", 50.0f, 320.0f); // Test 4: Very precise sizes @@ -55,8 +55,8 @@ int main() ege_setfont(18.0f, L"Arial"); measuretext(testText, &width, &height); - char info[256]; - snprintf(info, sizeof(info), "Width: %.2f, Height: %.2f", width, height); + wchar_t info[256]; + swprintf(info, sizeof(info)/sizeof(wchar_t), L"Width: %.2f, Height: %.2f", width, height); ege_drawtext(testText, 50.0f, 480.0f); ege_setfont(12.0f, L"Arial"); ege_drawtext(info, 50.0f, 510.0f); diff --git a/src/font.cpp b/src/font.cpp index 7e7bcdd1..a2d43b46 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -928,12 +928,20 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) // Create GDI+ FontFamily Gdiplus::FontFamily fontFamily(typeface); - // If the font family is not available, try to use a default font + // If the font family is not available, try fallback fonts if (!fontFamily.IsAvailable()) { // Try common fallback fonts in order - fontFamily = Gdiplus::FontFamily(L"Arial"); - if (!fontFamily.IsAvailable()) { - fontFamily = Gdiplus::FontFamily(L"SimSun"); + Gdiplus::FontFamily arialFamily(L"Arial"); + if (arialFamily.IsAvailable()) { + fontFamily = arialFamily; + } else { + Gdiplus::FontFamily simSunFamily(L"SimSun"); + if (simSunFamily.IsAvailable()) { + fontFamily = simSunFamily; + } else { + // Use generic sans serif as final fallback + Gdiplus::FontFamily::GenericSansSerif()->Clone(&fontFamily); + } } } From 88bb75c2d0edfe407527d02525bc375a73606676 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 17:26:55 +0000 Subject: [PATCH 05/20] Fix FontFamily handling to use proper lifetime management Co-authored-by: wysaid <1430725+wysaid@users.noreply.github.com> --- src/font.cpp | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/font.cpp b/src/font.cpp index a2d43b46..6bdefdb6 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -925,28 +925,34 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) img->m_font = NULL; } - // Create GDI+ FontFamily - Gdiplus::FontFamily fontFamily(typeface); + // Create GDI+ FontFamily - try requested font first, then fallbacks + Gdiplus::FontFamily* fontFamily = new Gdiplus::FontFamily(typeface); // If the font family is not available, try fallback fonts - if (!fontFamily.IsAvailable()) { - // Try common fallback fonts in order - Gdiplus::FontFamily arialFamily(L"Arial"); - if (arialFamily.IsAvailable()) { - fontFamily = arialFamily; - } else { - Gdiplus::FontFamily simSunFamily(L"SimSun"); - if (simSunFamily.IsAvailable()) { - fontFamily = simSunFamily; - } else { + if (!fontFamily->IsAvailable()) { + delete fontFamily; + + // Try Arial + fontFamily = new Gdiplus::FontFamily(L"Arial"); + if (!fontFamily->IsAvailable()) { + delete fontFamily; + + // Try SimSun (common Chinese font) + fontFamily = new Gdiplus::FontFamily(L"SimSun"); + if (!fontFamily->IsAvailable()) { + delete fontFamily; + // Use generic sans serif as final fallback - Gdiplus::FontFamily::GenericSansSerif()->Clone(&fontFamily); + fontFamily = Gdiplus::FontFamily::GenericSansSerif()->Clone(); } } } // Create new GDI+ Font with floating-point size - Gdiplus::Font* newFont = new Gdiplus::Font(&fontFamily, size, style, Gdiplus::UnitPoint); + Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, size, style, Gdiplus::UnitPoint); + + // Clean up font family (Font makes its own copy) + delete fontFamily; // Validate the created font before storing it if (newFont != NULL && newFont->IsAvailable()) { From dbefef373555d636aa3d7f8d897d3ef4816d38d9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 17:27:45 +0000 Subject: [PATCH 06/20] Use safer swprintf_s and optimize GenericSansSerif usage Co-authored-by: wysaid <1430725+wysaid@users.noreply.github.com> --- demo/test_ege_setfont.cpp | 4 ++++ src/font.cpp | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/demo/test_ege_setfont.cpp b/demo/test_ege_setfont.cpp index 8113185b..f9db8721 100644 --- a/demo/test_ege_setfont.cpp +++ b/demo/test_ege_setfont.cpp @@ -56,7 +56,11 @@ int main() measuretext(testText, &width, &height); wchar_t info[256]; +#if defined(_MSC_VER) && (_MSC_VER >= 1400) + swprintf_s(info, sizeof(info)/sizeof(wchar_t), L"Width: %.2f, Height: %.2f", width, height); +#else swprintf(info, sizeof(info)/sizeof(wchar_t), L"Width: %.2f, Height: %.2f", width, height); +#endif ege_drawtext(testText, 50.0f, 480.0f); ege_setfont(12.0f, L"Arial"); ege_drawtext(info, 50.0f, 510.0f); diff --git a/src/font.cpp b/src/font.cpp index 6bdefdb6..2a7a03e8 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -943,7 +943,10 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) delete fontFamily; // Use generic sans serif as final fallback - fontFamily = Gdiplus::FontFamily::GenericSansSerif()->Clone(); + // Get name from static family to avoid cloning overhead + WCHAR familyName[LF_FACESIZE]; + Gdiplus::FontFamily::GenericSansSerif()->GetFamilyName(familyName); + fontFamily = new Gdiplus::FontFamily(familyName); } } } From 7d2bf54d6701c65bd235043fd97e41eb5db7de57 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 17:29:17 +0000 Subject: [PATCH 07/20] Code quality improvements: simplify array size and null checks Co-authored-by: wysaid <1430725+wysaid@users.noreply.github.com> --- demo/test_ege_setfont.cpp | 4 ++-- src/font.cpp | 13 ++++--------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/demo/test_ege_setfont.cpp b/demo/test_ege_setfont.cpp index f9db8721..b17ea372 100644 --- a/demo/test_ege_setfont.cpp +++ b/demo/test_ege_setfont.cpp @@ -57,9 +57,9 @@ int main() wchar_t info[256]; #if defined(_MSC_VER) && (_MSC_VER >= 1400) - swprintf_s(info, sizeof(info)/sizeof(wchar_t), L"Width: %.2f, Height: %.2f", width, height); + swprintf_s(info, 256, L"Width: %.2f, Height: %.2f", width, height); #else - swprintf(info, sizeof(info)/sizeof(wchar_t), L"Width: %.2f, Height: %.2f", width, height); + swprintf(info, 256, L"Width: %.2f, Height: %.2f", width, height); #endif ege_drawtext(testText, 50.0f, 480.0f); ege_setfont(12.0f, L"Arial"); diff --git a/src/font.cpp b/src/font.cpp index 2a7a03e8..0ac610aa 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -942,11 +942,8 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) if (!fontFamily->IsAvailable()) { delete fontFamily; - // Use generic sans serif as final fallback - // Get name from static family to avoid cloning overhead - WCHAR familyName[LF_FACESIZE]; - Gdiplus::FontFamily::GenericSansSerif()->GetFamilyName(familyName); - fontFamily = new Gdiplus::FontFamily(familyName); + // Use generic sans serif as final fallback (always available) + fontFamily = Gdiplus::FontFamily::GenericSansSerif()->Clone(); } } } @@ -958,13 +955,11 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) delete fontFamily; // Validate the created font before storing it - if (newFont != NULL && newFont->IsAvailable()) { + if (newFont->IsAvailable()) { img->m_font = newFont; } else { // Font creation failed, clean up and don't store - if (newFont != NULL) { - delete newFont; - } + delete newFont; } } CONVERT_IMAGE_END; From 558aacdc5407abc162f13336fe67829d9db9a30f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 17:30:26 +0000 Subject: [PATCH 08/20] Add input validation for typeface and size parameters Co-authored-by: wysaid <1430725+wysaid@users.noreply.github.com> --- demo/test_ege_setfont.cpp | 7 ++++--- src/font.cpp | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/demo/test_ege_setfont.cpp b/demo/test_ege_setfont.cpp index b17ea372..66af5a60 100644 --- a/demo/test_ege_setfont.cpp +++ b/demo/test_ege_setfont.cpp @@ -55,11 +55,12 @@ int main() ege_setfont(18.0f, L"Arial"); measuretext(testText, &width, &height); - wchar_t info[256]; + const size_t INFO_BUFFER_SIZE = 256; + wchar_t info[INFO_BUFFER_SIZE]; #if defined(_MSC_VER) && (_MSC_VER >= 1400) - swprintf_s(info, 256, L"Width: %.2f, Height: %.2f", width, height); + swprintf_s(info, INFO_BUFFER_SIZE, L"Width: %.2f, Height: %.2f", width, height); #else - swprintf(info, 256, L"Width: %.2f, Height: %.2f", width, height); + swprintf(info, INFO_BUFFER_SIZE, L"Width: %.2f, Height: %.2f", width, height); #endif ege_drawtext(testText, 50.0f, 480.0f); ege_setfont(12.0f, L"Arial"); diff --git a/src/font.cpp b/src/font.cpp index 0ac610aa..449766f3 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -919,6 +919,17 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) { PIMAGE img = CONVERT_IMAGE(pimg); if (img) { + // Validate input parameters + if (typeface == NULL || typeface[0] == L'\0') { + typeface = L"Arial"; // Use safe default + } + + // Validate size (reasonable range for font sizes) + if (size <= 0.0f || size > 1000.0f) { + CONVERT_IMAGE_END; + return; // Invalid size, do nothing + } + // Delete existing GDI+ font if any if (img->m_font != NULL) { delete img->m_font; @@ -942,8 +953,14 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) if (!fontFamily->IsAvailable()) { delete fontFamily; - // Use generic sans serif as final fallback (always available) - fontFamily = Gdiplus::FontFamily::GenericSansSerif()->Clone(); + // Use generic sans serif as final fallback + const Gdiplus::FontFamily* genericFamily = Gdiplus::FontFamily::GenericSansSerif(); + if (genericFamily != NULL) { + fontFamily = genericFamily->Clone(); + } else { + // Last resort: try to create a basic font family + fontFamily = new Gdiplus::FontFamily(L"Sans Serif"); + } } } } From 3f7585b11f1b15ad70e4353226065f8d72c62ca8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 17 Dec 2025 17:31:44 +0000 Subject: [PATCH 09/20] Fix const parameter modification and add final fallback validation Co-authored-by: wysaid <1430725+wysaid@users.noreply.github.com> --- src/font.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/font.cpp b/src/font.cpp index 449766f3..d3f4ace5 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -920,8 +920,9 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) PIMAGE img = CONVERT_IMAGE(pimg); if (img) { // Validate input parameters - if (typeface == NULL || typeface[0] == L'\0') { - typeface = L"Arial"; // Use safe default + const wchar_t* validatedTypeface = typeface; + if (validatedTypeface == NULL || validatedTypeface[0] == L'\0') { + validatedTypeface = L"Arial"; // Use safe default } // Validate size (reasonable range for font sizes) @@ -937,7 +938,7 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) } // Create GDI+ FontFamily - try requested font first, then fallbacks - Gdiplus::FontFamily* fontFamily = new Gdiplus::FontFamily(typeface); + Gdiplus::FontFamily* fontFamily = new Gdiplus::FontFamily(validatedTypeface); // If the font family is not available, try fallback fonts if (!fontFamily->IsAvailable()) { @@ -958,13 +959,23 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) if (genericFamily != NULL) { fontFamily = genericFamily->Clone(); } else { - // Last resort: try to create a basic font family - fontFamily = new Gdiplus::FontFamily(L"Sans Serif"); + // Last resort: return without setting font (use GDI fallback) + CONVERT_IMAGE_END; + return; } } } } + // Validate font family is available before creating font + if (fontFamily == NULL || !fontFamily->IsAvailable()) { + if (fontFamily != NULL) { + delete fontFamily; + } + CONVERT_IMAGE_END; + return; + } + // Create new GDI+ Font with floating-point size Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, size, style, Gdiplus::UnitPoint); From ddfd07067ec01f3bedbe533115a01e70d21a7718 Mon Sep 17 00:00:00 2001 From: FeJS8888 Date: Sat, 20 Dec 2025 20:49:45 +0800 Subject: [PATCH 10/20] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/image.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/image.h b/src/image.h index e0c76806..b2d83913 100644 --- a/src/image.h +++ b/src/image.h @@ -92,14 +92,14 @@ class IMAGE color_t m_fillcolor; color_t m_textcolor; color_t m_bk_color; - -private: #ifdef EGE_GDIPLUS Gdiplus::Graphics* m_graphics; Gdiplus::Pen* m_pen; Gdiplus::Brush* m_brush; Gdiplus::Font* m_font; #endif + +private: bool m_aa; void initimage(HDC refDC, int width, int height); void construct(int width, int height); From 302425922e964f91c390d8bcd04b059d6363984b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 01:50:00 +0000 Subject: [PATCH 11/20] Fix documentation and use UnitPixel for size consistency with GDI Co-authored-by: FeJS8888 <110683147+FeJS8888@users.noreply.github.com> --- demo/test_ege_setfont.cpp | 21 +++++++++++---------- include/ege.h | 12 ++++++++---- include/ege.zh_CN.h | 12 ++++++++---- src/font.cpp | 3 ++- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/demo/test_ege_setfont.cpp b/demo/test_ege_setfont.cpp index 66af5a60..b910fb73 100644 --- a/demo/test_ege_setfont.cpp +++ b/demo/test_ege_setfont.cpp @@ -1,6 +1,7 @@ /* * Test demo for ege_setfont function * This demo demonstrates the use of floating-point font sizes with GDI+ + * Font sizes are in pixels to match the existing setfont() behavior */ #include @@ -16,38 +17,38 @@ int main() // Test 1: Basic ege_setfont with floating-point size settextcolor(BLACK); ege_setfont(24.5f, L"Arial"); - ege_drawtext(L"24.5pt Arial font (floating-point size)", 50.0f, 50.0f); + ege_drawtext(L"24.5px Arial font (floating-point size)", 50.0f, 50.0f); // Test 2: Different sizes to show precision ege_setfont(12.0f, L"Times New Roman"); - ege_drawtext(L"12.0pt Times New Roman", 50.0f, 100.0f); + ege_drawtext(L"12.0px Times New Roman", 50.0f, 100.0f); ege_setfont(12.5f, L"Times New Roman"); - ege_drawtext(L"12.5pt Times New Roman", 50.0f, 120.0f); + ege_drawtext(L"12.5px Times New Roman", 50.0f, 120.0f); ege_setfont(13.0f, L"Times New Roman"); - ege_drawtext(L"13.0pt Times New Roman", 50.0f, 140.0f); + ege_drawtext(L"13.0px Times New Roman", 50.0f, 140.0f); // Test 3: With font styles ege_setfont(20.0f, L"Arial", Gdiplus::FontStyleBold); - ege_drawtext(L"20pt Arial Bold", 50.0f, 200.0f); + ege_drawtext(L"20px Arial Bold", 50.0f, 200.0f); ege_setfont(18.0f, L"Arial", Gdiplus::FontStyleItalic); - ege_drawtext(L"18pt Arial Italic", 50.0f, 240.0f); + ege_drawtext(L"18px Arial Italic", 50.0f, 240.0f); ege_setfont(16.0f, L"Arial", Gdiplus::FontStyleBold | Gdiplus::FontStyleItalic); - ege_drawtext(L"16pt Arial Bold Italic", 50.0f, 280.0f); + ege_drawtext(L"16px Arial Bold Italic", 50.0f, 280.0f); ege_setfont(14.0f, L"Arial", Gdiplus::FontStyleUnderline); - ege_drawtext(L"14pt Arial Underline", 50.0f, 320.0f); + ege_drawtext(L"14px Arial Underline", 50.0f, 320.0f); // Test 4: Very precise sizes ege_setfont(15.25f, L"Courier New"); - ege_drawtext(L"15.25pt Courier New (very precise)", 50.0f, 380.0f); + ege_drawtext(L"15.25px Courier New (very precise)", 50.0f, 380.0f); // Test 5: Chinese characters with floating-point size ege_setfont(22.5f, L"SimSun"); - ege_drawtext(L"22.5点宋体 - 中文测试", 50.0f, 430.0f); + ege_drawtext(L"22.5像素宋体 - 中文测试", 50.0f, 430.0f); // Test 6: Compare with measuretext float width, height; diff --git a/include/ege.h b/include/ege.h index afbb6c3e..4ba80f76 100644 --- a/include/ege.h +++ b/include/ege.h @@ -3998,43 +3998,47 @@ void EGEAPI getfont(LOGFONTA *font, PCIMAGE pimg = NULL); /** * @brief Set font for GDI+ text rendering with floating-point size - * @param size Font size in ems (floating-point), supports fractional values for precise sizing + * @param size Font size in pixels (floating-point), supports fractional values for precise sizing * @param typeface Font family name * @param pimg Target image pointer, NULL means current ege window * @note This function creates a GDI+ Font directly, allowing floating-point font sizes. * When set, ege_drawtext will use this GDI+ font instead of converting from GDI HFONT. + * The size is in pixels to maintain consistency with the existing setfont() function. */ void EGEAPI ege_setfont(float size, const char* typeface, PIMAGE pimg = NULL); /** * @brief Set font for GDI+ text rendering with floating-point size (Unicode) - * @param size Font size in ems (floating-point), supports fractional values for precise sizing + * @param size Font size in pixels (floating-point), supports fractional values for precise sizing * @param typeface Font family name * @param pimg Target image pointer, NULL means current ege window * @note This function creates a GDI+ Font directly, allowing floating-point font sizes. * When set, ege_drawtext will use this GDI+ font instead of converting from GDI HFONT. + * The size is in pixels to maintain consistency with the existing setfont() function. */ void EGEAPI ege_setfont(float size, const wchar_t* typeface, PIMAGE pimg = NULL); /** * @brief Set font for GDI+ text rendering with floating-point size and style - * @param size Font size in ems (floating-point), supports fractional values for precise sizing + * @param size Font size in pixels (floating-point), supports fractional values for precise sizing * @param typeface Font family name * @param style Font style (combination of Gdiplus::FontStyle flags: FontStyleBold, FontStyleItalic, etc.) * @param pimg Target image pointer, NULL means current ege window * @note This function creates a GDI+ Font directly, allowing floating-point font sizes and GDI+ font styles. * When set, ege_drawtext will use this GDI+ font instead of converting from GDI HFONT. + * The size is in pixels to maintain consistency with the existing setfont() function. */ void EGEAPI ege_setfont(float size, const char* typeface, int style, PIMAGE pimg = NULL); /** * @brief Set font for GDI+ text rendering with floating-point size and style (Unicode) - * @param size Font size in ems (floating-point), supports fractional values for precise sizing + * @param size Font size in pixels (floating-point), supports fractional values for precise sizing * @param typeface Font family name * @param style Font style (combination of Gdiplus::FontStyle flags: FontStyleBold, FontStyleItalic, etc.) * @param pimg Target image pointer, NULL means current ege window * @note This function creates a GDI+ Font directly, allowing floating-point font sizes and GDI+ font styles. * When set, ege_drawtext will use this GDI+ font instead of converting from GDI HFONT. + * The size is in pixels to maintain consistency with the existing setfont() function. */ void EGEAPI ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg = NULL); diff --git a/include/ege.zh_CN.h b/include/ege.zh_CN.h index 58c933ec..e0e5d099 100644 --- a/include/ege.zh_CN.h +++ b/include/ege.zh_CN.h @@ -3993,43 +3993,47 @@ void EGEAPI getfont(LOGFONTA *font, PCIMAGE pimg = NULL); /** * @brief 设置用于GDI+文字渲染的浮点数大小字体 - * @param size 字体大小(单位:em,浮点数),支持小数以实现精确的字体大小 + * @param size 字体大小(单位:像素,浮点数),支持小数以实现精确的字体大小 * @param typeface 字体名称 * @param pimg 目标图像指针,NULL 表示当前ege窗口 * @note 此函数直接创建GDI+ Font,允许使用浮点数字体大小。 * 设置后,ege_drawtext将使用此GDI+字体,而不是从GDI HFONT转换。 + * 大小单位为像素,与现有的 setfont() 函数保持一致。 */ void EGEAPI ege_setfont(float size, const char* typeface, PIMAGE pimg = NULL); /** * @brief 设置用于GDI+文字渲染的浮点数大小字体(Unicode版本) - * @param size 字体大小(单位:em,浮点数),支持小数以实现精确的字体大小 + * @param size 字体大小(单位:像素,浮点数),支持小数以实现精确的字体大小 * @param typeface 字体名称 * @param pimg 目标图像指针,NULL 表示当前ege窗口 * @note 此函数直接创建GDI+ Font,允许使用浮点数字体大小。 * 设置后,ege_drawtext将使用此GDI+字体,而不是从GDI HFONT转换。 + * 大小单位为像素,与现有的 setfont() 函数保持一致。 */ void EGEAPI ege_setfont(float size, const wchar_t* typeface, PIMAGE pimg = NULL); /** * @brief 设置用于GDI+文字渲染的浮点数大小和样式字体 - * @param size 字体大小(单位:em,浮点数),支持小数以实现精确的字体大小 + * @param size 字体大小(单位:像素,浮点数),支持小数以实现精确的字体大小 * @param typeface 字体名称 * @param style 字体样式(Gdiplus::FontStyle标志的组合:FontStyleBold、FontStyleItalic等) * @param pimg 目标图像指针,NULL 表示当前ege窗口 * @note 此函数直接创建GDI+ Font,允许使用浮点数字体大小和GDI+字体样式。 * 设置后,ege_drawtext将使用此GDI+字体,而不是从GDI HFONT转换。 + * 大小单位为像素,与现有的 setfont() 函数保持一致。 */ void EGEAPI ege_setfont(float size, const char* typeface, int style, PIMAGE pimg = NULL); /** * @brief 设置用于GDI+文字渲染的浮点数大小和样式字体(Unicode版本) - * @param size 字体大小(单位:em,浮点数),支持小数以实现精确的字体大小 + * @param size 字体大小(单位:像素,浮点数),支持小数以实现精确的字体大小 * @param typeface 字体名称 * @param style 字体样式(Gdiplus::FontStyle标志的组合:FontStyleBold、FontStyleItalic等) * @param pimg 目标图像指针,NULL 表示当前ege窗口 * @note 此函数直接创建GDI+ Font,允许使用浮点数字体大小和GDI+字体样式。 * 设置后,ege_drawtext将使用此GDI+字体,而不是从GDI HFONT转换。 + * 大小单位为像素,与现有的 setfont() 函数保持一致。 */ void EGEAPI ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg = NULL); diff --git a/src/font.cpp b/src/font.cpp index d3f4ace5..f18a19ba 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -977,7 +977,8 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) } // Create new GDI+ Font with floating-point size - Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, size, style, Gdiplus::UnitPoint); + // Use UnitPixel instead of UnitPoint to match GDI behavior (size in pixels) + Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, size, style, Gdiplus::UnitPixel); // Clean up font family (Font makes its own copy) delete fontFamily; From adabb6d81bf60314c39c30e489ad4f7fa9ec77f6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 02:00:08 +0000 Subject: [PATCH 12/20] Fix GDI+ font size to match GDI by using Font(HDC, HFONT) conversion Co-authored-by: FeJS8888 <110683147+FeJS8888@users.noreply.github.com> --- src/font.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 11 deletions(-) diff --git a/src/font.cpp b/src/font.cpp index f18a19ba..52042c63 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -976,19 +976,77 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) return; } - // Create new GDI+ Font with floating-point size - // Use UnitPixel instead of UnitPoint to match GDI behavior (size in pixels) - Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, size, style, Gdiplus::UnitPixel); + // Create a temporary LOGFONT to understand GDI font metrics + // This helps us match the size that Font(HDC, HFONT) would produce + LOGFONTW tempLf = {0}; + tempLf.lfHeight = (LONG)size; // Use positive value as passed + tempLf.lfWidth = 0; + tempLf.lfEscapement = 0; + tempLf.lfOrientation = 0; + tempLf.lfWeight = (style & Gdiplus::FontStyleBold) ? FW_BOLD : FW_NORMAL; + tempLf.lfItalic = (style & Gdiplus::FontStyleItalic) ? TRUE : FALSE; + tempLf.lfUnderline = (style & Gdiplus::FontStyleUnderline) ? TRUE : FALSE; + tempLf.lfStrikeOut = (style & Gdiplus::FontStyleStrikeout) ? TRUE : FALSE; + tempLf.lfCharSet = DEFAULT_CHARSET; + tempLf.lfOutPrecision = OUT_DEFAULT_PRECIS; + tempLf.lfClipPrecision = CLIP_DEFAULT_PRECIS; + tempLf.lfQuality = DEFAULT_QUALITY; + tempLf.lfPitchAndFamily = DEFAULT_PITCH; + lstrcpyW(tempLf.lfFaceName, fontFamily->GetFamilyName(NULL) == Gdiplus::Ok ? validatedTypeface : L"Arial"); - // Clean up font family (Font makes its own copy) - delete fontFamily; - - // Validate the created font before storing it - if (newFont->IsAvailable()) { - img->m_font = newFont; + // Create temporary HFONT and let GDI+ convert it properly + HFONT tempHfont = CreateFontIndirectW(&tempLf); + if (tempHfont != NULL) { + // Create Font from HFONT - this will do the proper conversion + Gdiplus::Font* tempFont = new Gdiplus::Font(img->m_hDC, tempHfont); + + if (tempFont->IsAvailable()) { + // Get the actual size that GDI+ computed + Gdiplus::REAL actualSize = tempFont->GetSize(); + Gdiplus::Unit unit = tempFont->GetUnit(); + + // Clean up temporary font and HFONT + delete tempFont; + DeleteObject(tempHfont); + + // Now create the font with the corrected size + Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, actualSize, style, unit); + + // Clean up font family (Font makes its own copy) + delete fontFamily; + + // Validate the created font before storing it + if (newFont->IsAvailable()) { + img->m_font = newFont; + } else { + // Font creation failed, clean up and don't store + delete newFont; + } + } else { + // Failed to create temp font, fall back to direct creation + delete tempFont; + DeleteObject(tempHfont); + + // Use UnitPixel as fallback + Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, size, style, Gdiplus::UnitPixel); + delete fontFamily; + + if (newFont->IsAvailable()) { + img->m_font = newFont; + } else { + delete newFont; + } + } } else { - // Font creation failed, clean up and don't store - delete newFont; + // Couldn't create HFONT, use direct method as fallback + Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, size, style, Gdiplus::UnitPixel); + delete fontFamily; + + if (newFont->IsAvailable()) { + img->m_font = newFont; + } else { + delete newFont; + } } } CONVERT_IMAGE_END; From b4a768d380b9ffc539f9be4b6199472d10241f3d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 02:10:16 +0000 Subject: [PATCH 13/20] Fix measuretext to match ege_drawtext_p StringFormat flags Co-authored-by: FeJS8888 <110683147+FeJS8888@users.noreply.github.com> --- src/font.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/font.cpp b/src/font.cpp index 52042c63..7d1d5c3e 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -345,7 +345,11 @@ void measuretext(const wchar_t* text, float* width, float* height, PCIMAGE pimg) case RIGHT_TEXT: format->SetAlignment(StringAlignmentFar); break; default: break; } - format->SetFormatFlags(StringFormatFlagsMeasureTrailingSpaces); + + // Match the behavior in ege_drawtext_p: only measure trailing spaces for non-left alignment + if (img->m_texttype.horiz != LEFT_TEXT) { + format->SetFormatFlags(format->GetFormatFlags() | StringFormatFlagsMeasureTrailingSpaces); + } int textLength = (int)wcslen(text); CharacterRange charRange(0, textLength); From fa9fd88c9504f9694c83c5e1b21058957384da3a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 02:15:08 +0000 Subject: [PATCH 14/20] Use MeasureString instead of MeasureCharacterRanges for accurate bounds Co-authored-by: FeJS8888 <110683147+FeJS8888@users.noreply.github.com> --- src/font.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/font.cpp b/src/font.cpp index 7d1d5c3e..72fae089 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -352,17 +352,14 @@ void measuretext(const wchar_t* text, float* width, float* height, PCIMAGE pimg) } int textLength = (int)wcslen(text); - CharacterRange charRange(0, textLength); - format->SetMeasurableCharacterRanges(1, &charRange); - + + // Use MeasureString instead of MeasureCharacterRanges for better accuracy + // MeasureString gives bounds that match what DrawString actually renders + Gdiplus::RectF boundRect; Gdiplus::RectF layoutRect(0, 0, 65535, 65535); - Region region; - if (graphics.MeasureCharacterRanges(text, textLength, fontPtr, layoutRect, format, 1, ®ion) == Ok) { - Gdiplus::RectF boundRect; - if (region.GetBounds(&boundRect, &graphics) == Ok) { - textWidth = boundRect.Width; - textHeight = boundRect.Height; - } + if (graphics.MeasureString(text, textLength, fontPtr, layoutRect, format, &boundRect) == Ok) { + textWidth = boundRect.Width; + textHeight = boundRect.Height; } delete format; From c0569ac342d7b900821ad5241ae53ffac1365769 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 02:26:58 +0000 Subject: [PATCH 15/20] Fix floating-point font size precision by scaling from rounded LOGFONT Co-authored-by: FeJS8888 <110683147+FeJS8888@users.noreply.github.com> --- src/font.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/font.cpp b/src/font.cpp index 72fae089..1432d8ef 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -980,7 +980,7 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) // Create a temporary LOGFONT to understand GDI font metrics // This helps us match the size that Font(HDC, HFONT) would produce LOGFONTW tempLf = {0}; - tempLf.lfHeight = (LONG)size; // Use positive value as passed + tempLf.lfHeight = (LONG)(size + 0.5f); // Round to nearest integer for LOGFONT tempLf.lfWidth = 0; tempLf.lfEscapement = 0; tempLf.lfOrientation = 0; @@ -1002,7 +1002,7 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) Gdiplus::Font* tempFont = new Gdiplus::Font(img->m_hDC, tempHfont); if (tempFont->IsAvailable()) { - // Get the actual size that GDI+ computed + // Get the actual size and unit that GDI+ computed Gdiplus::REAL actualSize = tempFont->GetSize(); Gdiplus::Unit unit = tempFont->GetUnit(); @@ -1010,8 +1010,13 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) delete tempFont; DeleteObject(tempHfont); - // Now create the font with the corrected size - Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, actualSize, style, unit); + // Calculate the scaling factor to preserve the floating-point precision + // If input was 24.5 but LOGFONT used 25, we scale actualSize proportionally + float scaleFactor = size / (float)(LONG)(size + 0.5f); + Gdiplus::REAL adjustedSize = actualSize * scaleFactor; + + // Now create the font with the adjusted size to preserve float precision + Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, adjustedSize, style, unit); // Clean up font family (Font makes its own copy) delete fontFamily; From d84cb5e0ef82c3c5c0bed546e605565397f7bd61 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Dec 2025 02:32:26 +0000 Subject: [PATCH 16/20] Simplify ege_setfont to use direct Font creation with UnitPixel Co-authored-by: FeJS8888 <110683147+FeJS8888@users.noreply.github.com> --- src/font.cpp | 85 +++++++--------------------------------------------- 1 file changed, 11 insertions(+), 74 deletions(-) diff --git a/src/font.cpp b/src/font.cpp index 1432d8ef..e1bf9d4f 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -977,82 +977,19 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) return; } - // Create a temporary LOGFONT to understand GDI font metrics - // This helps us match the size that Font(HDC, HFONT) would produce - LOGFONTW tempLf = {0}; - tempLf.lfHeight = (LONG)(size + 0.5f); // Round to nearest integer for LOGFONT - tempLf.lfWidth = 0; - tempLf.lfEscapement = 0; - tempLf.lfOrientation = 0; - tempLf.lfWeight = (style & Gdiplus::FontStyleBold) ? FW_BOLD : FW_NORMAL; - tempLf.lfItalic = (style & Gdiplus::FontStyleItalic) ? TRUE : FALSE; - tempLf.lfUnderline = (style & Gdiplus::FontStyleUnderline) ? TRUE : FALSE; - tempLf.lfStrikeOut = (style & Gdiplus::FontStyleStrikeout) ? TRUE : FALSE; - tempLf.lfCharSet = DEFAULT_CHARSET; - tempLf.lfOutPrecision = OUT_DEFAULT_PRECIS; - tempLf.lfClipPrecision = CLIP_DEFAULT_PRECIS; - tempLf.lfQuality = DEFAULT_QUALITY; - tempLf.lfPitchAndFamily = DEFAULT_PITCH; - lstrcpyW(tempLf.lfFaceName, fontFamily->GetFamilyName(NULL) == Gdiplus::Ok ? validatedTypeface : L"Arial"); + // Create new GDI+ Font with floating-point size directly + // Use UnitPixel to specify size in pixels (matching GDI behavior) + Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, size, style, Gdiplus::UnitPixel); - // Create temporary HFONT and let GDI+ convert it properly - HFONT tempHfont = CreateFontIndirectW(&tempLf); - if (tempHfont != NULL) { - // Create Font from HFONT - this will do the proper conversion - Gdiplus::Font* tempFont = new Gdiplus::Font(img->m_hDC, tempHfont); - - if (tempFont->IsAvailable()) { - // Get the actual size and unit that GDI+ computed - Gdiplus::REAL actualSize = tempFont->GetSize(); - Gdiplus::Unit unit = tempFont->GetUnit(); - - // Clean up temporary font and HFONT - delete tempFont; - DeleteObject(tempHfont); - - // Calculate the scaling factor to preserve the floating-point precision - // If input was 24.5 but LOGFONT used 25, we scale actualSize proportionally - float scaleFactor = size / (float)(LONG)(size + 0.5f); - Gdiplus::REAL adjustedSize = actualSize * scaleFactor; - - // Now create the font with the adjusted size to preserve float precision - Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, adjustedSize, style, unit); - - // Clean up font family (Font makes its own copy) - delete fontFamily; - - // Validate the created font before storing it - if (newFont->IsAvailable()) { - img->m_font = newFont; - } else { - // Font creation failed, clean up and don't store - delete newFont; - } - } else { - // Failed to create temp font, fall back to direct creation - delete tempFont; - DeleteObject(tempHfont); - - // Use UnitPixel as fallback - Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, size, style, Gdiplus::UnitPixel); - delete fontFamily; - - if (newFont->IsAvailable()) { - img->m_font = newFont; - } else { - delete newFont; - } - } + // Clean up font family (Font makes its own copy) + delete fontFamily; + + // Validate the created font before storing it + if (newFont->IsAvailable()) { + img->m_font = newFont; } else { - // Couldn't create HFONT, use direct method as fallback - Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, size, style, Gdiplus::UnitPixel); - delete fontFamily; - - if (newFont->IsAvailable()) { - img->m_font = newFont; - } else { - delete newFont; - } + // Font creation failed, clean up and don't store + delete newFont; } } CONVERT_IMAGE_END; From cbabbe79d137cc540e52ea491184f04c99b8c9d1 Mon Sep 17 00:00:00 2001 From: FeJS8888 Date: Sun, 21 Dec 2025 10:44:36 +0800 Subject: [PATCH 17/20] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=86=20GDI+=20?= =?UTF-8?q?=E7=BB=98=E5=88=B6=E6=96=87=E5=AD=97=E5=92=8C=20GDI=20=E7=BB=98?= =?UTF-8?q?=E5=88=B6=E5=A4=A7=E5=B0=8F=E4=B8=8D=E5=8C=B9=E9=85=8D=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/font.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/font.cpp b/src/font.cpp index e1bf9d4f..ee037e51 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -977,9 +977,15 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) return; } - // Create new GDI+ Font with floating-point size directly - // Use UnitPixel to specify size in pixels (matching GDI behavior) - Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, size, style, Gdiplus::UnitPixel); + Gdiplus::REAL emSize = size; + + // 获取该字体族的“留白”比例 + Gdiplus::REAL cellHeight = (Gdiplus::REAL)fontFamily->GetLineSpacing(style); + Gdiplus::REAL emHeight = (Gdiplus::REAL)fontFamily->GetEmHeight(style); + // 缩放 size,去掉留白部分,得到 GDI+ 需要的纯像素大小 + Gdiplus::REAL adjustedSize = size * emHeight / cellHeight; + + Gdiplus::Font* newFont = new Gdiplus::Font(fontFamily, adjustedSize, style, Gdiplus::UnitPixel); // Clean up font family (Font makes its own copy) delete fontFamily; From 11bc687d3b5d1dc7dc0a28e3c2ba98469ce2da38 Mon Sep 17 00:00:00 2001 From: FeJS8888 Date: Sun, 21 Dec 2025 10:53:05 +0800 Subject: [PATCH 18/20] =?UTF-8?q?=E7=A7=BB=E9=99=A4=E4=BA=86=E6=97=A0?= =?UTF-8?q?=E7=94=A8=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/font.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/font.cpp b/src/font.cpp index ee037e51..1221f902 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -977,9 +977,6 @@ void ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg) return; } - Gdiplus::REAL emSize = size; - - // 获取该字体族的“留白”比例 Gdiplus::REAL cellHeight = (Gdiplus::REAL)fontFamily->GetLineSpacing(style); Gdiplus::REAL emHeight = (Gdiplus::REAL)fontFamily->GetEmHeight(style); // 缩放 size,去掉留白部分,得到 GDI+ 需要的纯像素大小 From 7802c194adce7318ea45beac0b33bfa11d1d5a31 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 22 Dec 2025 04:10:47 +0000 Subject: [PATCH 19/20] Add NULL checks to ANSI ege_setfont functions for security Co-authored-by: FeJS8888 <110683147+FeJS8888@users.noreply.github.com> --- src/font.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/font.cpp b/src/font.cpp index 1221f902..8a29b2ee 100644 --- a/src/font.cpp +++ b/src/font.cpp @@ -901,7 +901,11 @@ static void ege_drawtext_p(const wchar_t* textstring, float x, float y, PIMAGE i void ege_setfont(float size, const char* typeface, PIMAGE pimg) { - const std::wstring& wFace = mb2w(typeface); + const char* validatedTypeface = typeface; + if (validatedTypeface == NULL || validatedTypeface[0] == '\0') { + validatedTypeface = "Arial"; + } + const std::wstring& wFace = mb2w(validatedTypeface); ege_setfont(size, wFace.c_str(), pimg); } @@ -912,7 +916,11 @@ void ege_setfont(float size, const wchar_t* typeface, PIMAGE pimg) void ege_setfont(float size, const char* typeface, int style, PIMAGE pimg) { - const std::wstring& wFace = mb2w(typeface); + const char* validatedTypeface = typeface; + if (validatedTypeface == NULL || validatedTypeface[0] == '\0') { + validatedTypeface = "Arial"; + } + const std::wstring& wFace = mb2w(validatedTypeface); ege_setfont(size, wFace.c_str(), style, pimg); } From 4b34902e0f0eec63cf595ca3a92b1e3b483fdc44 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 22 Dec 2025 11:52:18 +0000 Subject: [PATCH 20/20] Update documentation to clarify size adjustment for GDI compatibility Co-authored-by: FeJS8888 <110683147+FeJS8888@users.noreply.github.com> --- include/ege.h | 20 ++++++++++++-------- include/ege.zh_CN.h | 20 ++++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/include/ege.h b/include/ege.h index 4ba80f76..a7f9109d 100644 --- a/include/ege.h +++ b/include/ege.h @@ -3998,47 +3998,51 @@ void EGEAPI getfont(LOGFONTA *font, PCIMAGE pimg = NULL); /** * @brief Set font for GDI+ text rendering with floating-point size - * @param size Font size in pixels (floating-point), supports fractional values for precise sizing + * @param size Font size (floating-point), measured in cell height pixels to match GDI setfont() behavior * @param typeface Font family name * @param pimg Target image pointer, NULL means current ege window * @note This function creates a GDI+ Font directly, allowing floating-point font sizes. * When set, ege_drawtext will use this GDI+ font instead of converting from GDI HFONT. - * The size is in pixels to maintain consistency with the existing setfont() function. + * The size represents the cell height (like GDI's LOGFONT.lfHeight). The implementation + * adjusts this to GDI+'s em height internally to ensure the rendered size matches GDI fonts. */ void EGEAPI ege_setfont(float size, const char* typeface, PIMAGE pimg = NULL); /** * @brief Set font for GDI+ text rendering with floating-point size (Unicode) - * @param size Font size in pixels (floating-point), supports fractional values for precise sizing + * @param size Font size (floating-point), measured in cell height pixels to match GDI setfont() behavior * @param typeface Font family name * @param pimg Target image pointer, NULL means current ege window * @note This function creates a GDI+ Font directly, allowing floating-point font sizes. * When set, ege_drawtext will use this GDI+ font instead of converting from GDI HFONT. - * The size is in pixels to maintain consistency with the existing setfont() function. + * The size represents the cell height (like GDI's LOGFONT.lfHeight). The implementation + * adjusts this to GDI+'s em height internally to ensure the rendered size matches GDI fonts. */ void EGEAPI ege_setfont(float size, const wchar_t* typeface, PIMAGE pimg = NULL); /** * @brief Set font for GDI+ text rendering with floating-point size and style - * @param size Font size in pixels (floating-point), supports fractional values for precise sizing + * @param size Font size (floating-point), measured in cell height pixels to match GDI setfont() behavior * @param typeface Font family name * @param style Font style (combination of Gdiplus::FontStyle flags: FontStyleBold, FontStyleItalic, etc.) * @param pimg Target image pointer, NULL means current ege window * @note This function creates a GDI+ Font directly, allowing floating-point font sizes and GDI+ font styles. * When set, ege_drawtext will use this GDI+ font instead of converting from GDI HFONT. - * The size is in pixels to maintain consistency with the existing setfont() function. + * The size represents the cell height (like GDI's LOGFONT.lfHeight). The implementation + * adjusts this to GDI+'s em height internally to ensure the rendered size matches GDI fonts. */ void EGEAPI ege_setfont(float size, const char* typeface, int style, PIMAGE pimg = NULL); /** * @brief Set font for GDI+ text rendering with floating-point size and style (Unicode) - * @param size Font size in pixels (floating-point), supports fractional values for precise sizing + * @param size Font size (floating-point), measured in cell height pixels to match GDI setfont() behavior * @param typeface Font family name * @param style Font style (combination of Gdiplus::FontStyle flags: FontStyleBold, FontStyleItalic, etc.) * @param pimg Target image pointer, NULL means current ege window * @note This function creates a GDI+ Font directly, allowing floating-point font sizes and GDI+ font styles. * When set, ege_drawtext will use this GDI+ font instead of converting from GDI HFONT. - * The size is in pixels to maintain consistency with the existing setfont() function. + * The size represents the cell height (like GDI's LOGFONT.lfHeight). The implementation + * adjusts this to GDI+'s em height internally to ensure the rendered size matches GDI fonts. */ void EGEAPI ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg = NULL); diff --git a/include/ege.zh_CN.h b/include/ege.zh_CN.h index e0e5d099..71c2fa42 100644 --- a/include/ege.zh_CN.h +++ b/include/ege.zh_CN.h @@ -3993,47 +3993,51 @@ void EGEAPI getfont(LOGFONTA *font, PCIMAGE pimg = NULL); /** * @brief 设置用于GDI+文字渲染的浮点数大小字体 - * @param size 字体大小(单位:像素,浮点数),支持小数以实现精确的字体大小 + * @param size 字体大小(浮点数),以单元格高度像素为单位,与GDI setfont()行为保持一致 * @param typeface 字体名称 * @param pimg 目标图像指针,NULL 表示当前ege窗口 * @note 此函数直接创建GDI+ Font,允许使用浮点数字体大小。 * 设置后,ege_drawtext将使用此GDI+字体,而不是从GDI HFONT转换。 - * 大小单位为像素,与现有的 setfont() 函数保持一致。 + * 大小表示单元格高度(类似GDI的LOGFONT.lfHeight)。实现内部会将其调整为 + * GDI+的em高度,以确保渲染大小与GDI字体一致。 */ void EGEAPI ege_setfont(float size, const char* typeface, PIMAGE pimg = NULL); /** * @brief 设置用于GDI+文字渲染的浮点数大小字体(Unicode版本) - * @param size 字体大小(单位:像素,浮点数),支持小数以实现精确的字体大小 + * @param size 字体大小(浮点数),以单元格高度像素为单位,与GDI setfont()行为保持一致 * @param typeface 字体名称 * @param pimg 目标图像指针,NULL 表示当前ege窗口 * @note 此函数直接创建GDI+ Font,允许使用浮点数字体大小。 * 设置后,ege_drawtext将使用此GDI+字体,而不是从GDI HFONT转换。 - * 大小单位为像素,与现有的 setfont() 函数保持一致。 + * 大小表示单元格高度(类似GDI的LOGFONT.lfHeight)。实现内部会将其调整为 + * GDI+的em高度,以确保渲染大小与GDI字体一致。 */ void EGEAPI ege_setfont(float size, const wchar_t* typeface, PIMAGE pimg = NULL); /** * @brief 设置用于GDI+文字渲染的浮点数大小和样式字体 - * @param size 字体大小(单位:像素,浮点数),支持小数以实现精确的字体大小 + * @param size 字体大小(浮点数),以单元格高度像素为单位,与GDI setfont()行为保持一致 * @param typeface 字体名称 * @param style 字体样式(Gdiplus::FontStyle标志的组合:FontStyleBold、FontStyleItalic等) * @param pimg 目标图像指针,NULL 表示当前ege窗口 * @note 此函数直接创建GDI+ Font,允许使用浮点数字体大小和GDI+字体样式。 * 设置后,ege_drawtext将使用此GDI+字体,而不是从GDI HFONT转换。 - * 大小单位为像素,与现有的 setfont() 函数保持一致。 + * 大小表示单元格高度(类似GDI的LOGFONT.lfHeight)。实现内部会将其调整为 + * GDI+的em高度,以确保渲染大小与GDI字体一致。 */ void EGEAPI ege_setfont(float size, const char* typeface, int style, PIMAGE pimg = NULL); /** * @brief 设置用于GDI+文字渲染的浮点数大小和样式字体(Unicode版本) - * @param size 字体大小(单位:像素,浮点数),支持小数以实现精确的字体大小 + * @param size 字体大小(浮点数),以单元格高度像素为单位,与GDI setfont()行为保持一致 * @param typeface 字体名称 * @param style 字体样式(Gdiplus::FontStyle标志的组合:FontStyleBold、FontStyleItalic等) * @param pimg 目标图像指针,NULL 表示当前ege窗口 * @note 此函数直接创建GDI+ Font,允许使用浮点数字体大小和GDI+字体样式。 * 设置后,ege_drawtext将使用此GDI+字体,而不是从GDI HFONT转换。 - * 大小单位为像素,与现有的 setfont() 函数保持一致。 + * 大小表示单元格高度(类似GDI的LOGFONT.lfHeight)。实现内部会将其调整为 + * GDI+的em高度,以确保渲染大小与GDI字体一致。 */ void EGEAPI ege_setfont(float size, const wchar_t* typeface, int style, PIMAGE pimg = NULL);