From 5a1d13f0a46241f9de23818c345d581261d6f927 Mon Sep 17 00:00:00 2001 From: Philosoph228 Date: Mon, 24 Mar 2025 05:50:10 +0500 Subject: [PATCH] Add support for font loading and rendering --- examples/win32_gdi/CMakeLists.txt | 6 ++ examples/win32_gdi/main.c | 8 ++- renderers/win32_gdi/clay_renderer_gdi.c | 84 ++++++++++++++++++++++++- 3 files changed, 94 insertions(+), 4 deletions(-) diff --git a/examples/win32_gdi/CMakeLists.txt b/examples/win32_gdi/CMakeLists.txt index 6112f5b..e401e1d 100644 --- a/examples/win32_gdi/CMakeLists.txt +++ b/examples/win32_gdi/CMakeLists.txt @@ -7,3 +7,9 @@ add_executable(win32_gdi WIN32 main.c) target_compile_options(win32_gdi PUBLIC) target_include_directories(win32_gdi PUBLIC .) + +add_custom_command( + TARGET win32_gdi POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${CMAKE_CURRENT_SOURCE_DIR}/resources + ${CMAKE_CURRENT_BINARY_DIR}/resources) diff --git a/examples/win32_gdi/main.c b/examples/win32_gdi/main.c index c28fbd3..03ff247 100644 --- a/examples/win32_gdi/main.c +++ b/examples/win32_gdi/main.c @@ -25,6 +25,7 @@ void CenterWindow(HWND hWnd); long lastMsgTime = 0; bool ui_debug_mode; +HFONT fonts[1]; #define RECTWIDTH(rc) ((rc).right - (rc).left) #define RECTHEIGHT(rc) ((rc).bottom - (rc).top) @@ -116,7 +117,7 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_PAINT: { Clay_RenderCommandArray renderCommands = ClayVideoDemo_CreateLayout(&demo_data); - Clay_Win32_Render(hwnd, renderCommands); + Clay_Win32_Render(hwnd, renderCommands, fonts); break; } @@ -154,7 +155,10 @@ int APIENTRY WinMain( uint64_t clayRequiredMemory = Clay_MinMemorySize(); Clay_Arena clayMemory = Clay_CreateArenaWithCapacityAndMemory(clayRequiredMemory, malloc(clayRequiredMemory)); Clay_Initialize(clayMemory, (Clay_Dimensions){.width = 800, .height = 600}, (Clay_ErrorHandler){HandleClayErrors}); // This final argument is new since the video was published - Clay_SetMeasureTextFunction(Clay_Win32_MeasureText, NULL); + + // Initialize clay fonts and text drawing + fonts[FONT_ID_BODY_16] = Clay_Win32_SimpleCreateFont("resources/Roboto-Regular.ttf", "Roboto", -11, FW_NORMAL); + Clay_SetMeasureTextFunction(Clay_Win32_MeasureText, fonts); ZeroMemory(&wc, sizeof wc); wc.hInstance = hInstance; diff --git a/renderers/win32_gdi/clay_renderer_gdi.c b/renderers/win32_gdi/clay_renderer_gdi.c index e031189..25cfdfd 100644 --- a/renderers/win32_gdi/clay_renderer_gdi.c +++ b/renderers/win32_gdi/clay_renderer_gdi.c @@ -5,7 +5,7 @@ HDC renderer_hdcMem = {0}; HBITMAP renderer_hbmMem = {0}; HANDLE renderer_hOld = {0}; -void Clay_Win32_Render(HWND hwnd, Clay_RenderCommandArray renderCommands) +void Clay_Win32_Render(HWND hwnd, Clay_RenderCommandArray renderCommands, HFONT* fonts) { bool is_clipping = false; HRGN clipping_region = {0}; @@ -48,10 +48,17 @@ void Clay_Win32_Render(HWND hwnd, Clay_RenderCommandArray renderCommands) r.right = boundingBox.x + boundingBox.width + r.right; r.bottom = boundingBox.y + boundingBox.height + r.bottom; + uint16_t font_id = renderCommand->renderData.text.fontId; + HFONT hFont = fonts[font_id]; + HFONT hPrevFont = SelectObject(renderer_hdcMem, hFont); + + // Actually draw text DrawTextA(renderer_hdcMem, renderCommand->renderData.text.stringContents.chars, renderCommand->renderData.text.stringContents.length, &r, DT_TOP | DT_LEFT); + SelectObject(renderer_hdcMem, hPrevFont); + break; } case CLAY_RENDER_COMMAND_TYPE_RECTANGLE: @@ -216,6 +223,37 @@ static inline Clay_Dimensions Clay_Win32_MeasureText(Clay_StringSlice text, Clay { Clay_Dimensions textSize = {0}; + if (userData != NULL) + { + HFONT* fonts = (HFONT*)userData; + HFONT hFont = fonts[config->fontId]; + + if (hFont != NULL) + { + HDC hScreenDC = GetDC(HWND_DESKTOP); + HDC hTempDC = CreateCompatibleDC(hScreenDC); + + if (hTempDC != NULL) + { + HFONT hPrevFont = SelectObject(hTempDC, hFont); + + SIZE size; + GetTextExtentPoint32(hTempDC, text.chars, text.length, &size); + + textSize.width = size.cx; + textSize.height = size.cy; + + SelectObject(hScreenDC, hPrevFont); + DeleteDC(hTempDC); + + return textSize; + } + + ReleaseDC(HWND_DESKTOP, hScreenDC); + } + } + + // Fallback for system bitmap font float maxTextWidth = 0.0f; float lineTextWidth = 0; float textHeight = WIN32_FONT_HEIGHT; @@ -238,4 +276,46 @@ static inline Clay_Dimensions Clay_Win32_MeasureText(Clay_StringSlice text, Clay textSize.height = textHeight; return textSize; -} \ No newline at end of file +} + +HFONT Clay_Win32_SimpleCreateFont(const char* filePath, const char* family, int height, int weight) +{ + // Add the font resource to the application instance + int fontAdded = AddFontResourceEx(filePath, FR_PRIVATE, NULL); + if (fontAdded == 0) { + return NULL; + } + + int fontHeight = height; + + // If negative, treat height as Pt rather than pixels + if (height < 0) { + // Get the screen DPI + HDC hScreenDC = GetDC(HWND_DESKTOP); + int iScreenDPI = GetDeviceCaps(hScreenDC, LOGPIXELSY); + ReleaseDC(HWND_DESKTOP, hScreenDC); + + // Convert font height from points to pixels + fontHeight = MulDiv(height, iScreenDPI, 72); + } + + // Create the font using the calculated height and the font name + HFONT hFont = CreateFont( + fontHeight, // Height + 0, // Width (0 means default width) + 0, // Escapement angle + 0, // Orientation angle + weight, // Font weight + FALSE, // Italic + FALSE, // Underline + FALSE, // Strikeout + ANSI_CHARSET, // Character set + OUT_DEFAULT_PRECIS, // Output precision + CLIP_DEFAULT_PRECIS, // Clipping precision + DEFAULT_QUALITY, // Font quality + DEFAULT_PITCH, // Pitch and family + family // Font name + ); + + return hFont; +}