From bfed9520fcaf0795ca2ed09fb0fd6758f492ea0e Mon Sep 17 00:00:00 2001
From: Daniel Collin <daniel@collin.com>
Date: Sun, 19 Jan 2025 15:15:32 +0100
Subject: [PATCH] SetMesureText and SetQueryScrollOffset takes userData

---
 clay.h                                        | 32 +++++++++++--------
 examples/SDL2-video-demo/main.c               | 12 ++++---
 examples/SDL3-simple-demo/main.c              |  6 ++--
 examples/introducing-clay-video-demo/main.c   |  2 +-
 examples/raylib-multi-context/main.c          |  2 +-
 .../raylib-sidebar-scrolling-container/main.c |  2 +-
 renderers/SDL2/clay_renderer_SDL2.c           | 11 ++++---
 renderers/raylib/clay_renderer_raylib.c       |  2 +-
 8 files changed, 41 insertions(+), 28 deletions(-)

diff --git a/clay.h b/clay.h
index df42f87..23cbef6 100644
--- a/clay.h
+++ b/clay.h
@@ -1,4 +1,4 @@
-// VERSION: 0.11
+// VERSION: 0.12
 
 /*
     NOTE: In order to use this library you must define
@@ -527,8 +527,8 @@ bool Clay_Hovered(void);
 void Clay_OnHover(void (*onHoverFunction)(Clay_ElementId elementId, Clay_PointerData pointerData, intptr_t userData), intptr_t userData);
 bool Clay_PointerOver(Clay_ElementId elementId);
 Clay_ScrollContainerData Clay_GetScrollContainerData(Clay_ElementId id);
-void Clay_SetMeasureTextFunction(Clay_Dimensions (*measureTextFunction)(Clay_String *text, Clay_TextElementConfig *config));
-void Clay_SetQueryScrollOffsetFunction(Clay_Vector2 (*queryScrollOffsetFunction)(uint32_t elementId));
+void Clay_SetMeasureTextFunction(Clay_Dimensions (*measureTextFunction)(Clay_String *text, Clay_TextElementConfig *config, uintptr_t userData), uintptr_t userData);
+void Clay_SetQueryScrollOffsetFunction(Clay_Vector2 (*queryScrollOffsetFunction)(uint32_t elementId, uintptr_t userData), uintptr_t userData);
 Clay_RenderCommand * Clay_RenderCommandArray_Get(Clay_RenderCommandArray* array, int32_t index);
 void Clay_SetDebugModeEnabled(bool enabled);
 bool Clay_IsDebugModeEnabled(void);
@@ -1407,6 +1407,8 @@ struct Clay_Context {
     uint32_t debugSelectedElementId;
     uint32_t generation;
     uintptr_t arenaResetOffset;
+    uintptr_t mesureTextUserData;
+    uintptr_t queryScrollOffsetUserData;
     Clay_Arena internalArena;
     // Layout Elements / Render Commands
     Clay_LayoutElementArray layoutElements;
@@ -1480,11 +1482,11 @@ Clay_String Clay__WriteStringToCharBuffer(Clay__CharArray *buffer, Clay_String s
 }
 
 #ifdef CLAY_WASM
-    __attribute__((import_module("clay"), import_name("measureTextFunction"))) Clay_Dimensions Clay__MeasureText(Clay_String *text, Clay_TextElementConfig *config);
-    __attribute__((import_module("clay"), import_name("queryScrollOffsetFunction"))) Clay_Vector2 Clay__QueryScrollOffset(uint32_t elementId);
+    __attribute__((import_module("clay"), import_name("measureTextFunction"))) Clay_Dimensions Clay__MeasureText(Clay_String *text, Clay_TextElementConfig *config, uintptr_t userData);
+    __attribute__((import_module("clay"), import_name("queryScrollOffsetFunction"))) Clay_Vector2 Clay__QueryScrollOffset(uint32_t elementId, uintptr_t userData);
 #else
-    Clay_Dimensions (*Clay__MeasureText)(Clay_String *text, Clay_TextElementConfig *config);
-    Clay_Vector2 (*Clay__QueryScrollOffset)(uint32_t elementId);
+    Clay_Dimensions (*Clay__MeasureText)(Clay_String *text, Clay_TextElementConfig *config, uintptr_t userData);
+    Clay_Vector2 (*Clay__QueryScrollOffset)(uint32_t elementId, uintptr_t userData);
 #endif
 
 Clay_LayoutElement* Clay__GetOpenLayoutElement(void) {
@@ -1699,7 +1701,7 @@ Clay__MeasureTextCacheItem *Clay__MeasureTextCached(Clay_String *text, Clay_Text
     float lineWidth = 0;
     float measuredWidth = 0;
     float measuredHeight = 0;
-    float spaceWidth = Clay__MeasureText(&CLAY__SPACECHAR, config).width;
+    float spaceWidth = Clay__MeasureText(&CLAY__SPACECHAR, config, context->mesureTextUserData).width;
     Clay__MeasuredWord tempWord = { .next = -1 };
     Clay__MeasuredWord *previousWord = &tempWord;
     while (end < text->length) {
@@ -1717,7 +1719,7 @@ Clay__MeasureTextCacheItem *Clay__MeasureTextCached(Clay_String *text, Clay_Text
         if (current == ' ' || current == '\n') {
             int32_t length = end - start;
             Clay_String word = { .length = length, .chars = &text->chars[start] };
-            Clay_Dimensions dimensions = Clay__MeasureText(&word, config);
+            Clay_Dimensions dimensions = Clay__MeasureText(&word, config, context->mesureTextUserData);
             measuredHeight = CLAY__MAX(measuredHeight, dimensions.height);
             if (current == ' ') {
                 dimensions.width += spaceWidth;
@@ -1740,7 +1742,7 @@ Clay__MeasureTextCacheItem *Clay__MeasureTextCached(Clay_String *text, Clay_Text
     }
     if (end - start > 0) {
         Clay_String lastWord = { .length = end - start, .chars = &text->chars[start] };
-        Clay_Dimensions dimensions = Clay__MeasureText(&lastWord, config);
+        Clay_Dimensions dimensions = Clay__MeasureText(&lastWord, config, context->mesureTextUserData);
         Clay__AddMeasuredWord(CLAY__INIT(Clay__MeasuredWord) { .startOffset = start, .length = end - start, .width = dimensions.width, .next = -1 }, previousWord);
         lineWidth += dimensions.width;
         measuredHeight = CLAY__MAX(measuredHeight, dimensions.height);
@@ -1902,7 +1904,7 @@ void Clay__ElementPostConfiguration(void) {
                     scrollOffset = Clay__ScrollContainerDataInternalArray_Add(&context->scrollContainerDatas, CLAY__INIT(Clay__ScrollContainerDataInternal){.layoutElement = openLayoutElement, .scrollOrigin = {-1,-1}, .elementId = openLayoutElement->id, .openThisFrame = true});
                 }
                 if (context->externalScrollHandlingEnabled) {
-                    scrollOffset->scrollPosition = Clay__QueryScrollOffset(scrollOffset->elementId);
+                    scrollOffset->scrollPosition = Clay__QueryScrollOffset(scrollOffset->elementId, context->queryScrollOffsetUserData);
                 }
                 break;
             }
@@ -3678,11 +3680,15 @@ Clay_Arena Clay_CreateArenaWithCapacityAndMemory(uint32_t capacity, void *offset
 }
 
 #ifndef CLAY_WASM
-void Clay_SetMeasureTextFunction(Clay_Dimensions (*measureTextFunction)(Clay_String *text, Clay_TextElementConfig *config)) {
+void Clay_SetMeasureTextFunction(Clay_Dimensions (*measureTextFunction)(Clay_String *text, Clay_TextElementConfig *config, uintptr_t userData), uintptr_t userData) {
+    Clay_Context* context = Clay_GetCurrentContext();
     Clay__MeasureText = measureTextFunction;
+    context->mesureTextUserData = userData;
 }
-void Clay_SetQueryScrollOffsetFunction(Clay_Vector2 (*queryScrollOffsetFunction)(uint32_t elementId)) {
+void Clay_SetQueryScrollOffsetFunction(Clay_Vector2 (*queryScrollOffsetFunction)(uint32_t elementId, uintptr_t userData), uintptr_t userData) {
+    Clay_Context* context = Clay_GetCurrentContext();
     Clay__QueryScrollOffset = queryScrollOffsetFunction;
+    context->queryScrollOffsetUserData = userData;
 }
 #endif
 
diff --git a/examples/SDL2-video-demo/main.c b/examples/SDL2-video-demo/main.c
index 3bcd24d..e8c3413 100644
--- a/examples/SDL2-video-demo/main.c
+++ b/examples/SDL2-video-demo/main.c
@@ -299,7 +299,10 @@ int main(int argc, char *argv[]) {
         fprintf(stderr, "Error: could not load font: %s\n", TTF_GetError());
         return 1;
     }
-    SDL2_fonts[FONT_ID_BODY_16] = (SDL2_Font) {
+
+    SDL2_Font fonts[1] = {};
+
+    fonts[FONT_ID_BODY_16] = (SDL2_Font) {
         .fontId = FONT_ID_BODY_16,
         .font = font,
     };
@@ -315,12 +318,13 @@ int main(int argc, char *argv[]) {
     uint64_t totalMemorySize = Clay_MinMemorySize();
     Clay_Arena clayMemory = Clay_CreateArenaWithCapacityAndMemory(totalMemorySize, malloc(totalMemorySize));
 
-    Clay_SetMeasureTextFunction(SDL2_MeasureText);
-
     int windowWidth = 0;
     int windowHeight = 0;
     SDL_GetWindowSize(window, &windowWidth, &windowHeight);
     Clay_Initialize(clayMemory, (Clay_Dimensions) { (float)windowWidth, (float)windowHeight }, (Clay_ErrorHandler) { HandleClayErrors });
+
+    Clay_SetMeasureTextFunction(SDL2_MeasureText, (uintptr_t)&fonts);
+
     Uint64 NOW = SDL_GetPerformanceCounter();
     Uint64 LAST = 0;
     double deltaTime = 0;
@@ -361,7 +365,7 @@ int main(int argc, char *argv[]) {
         SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
         SDL_RenderClear(renderer);
 
-        Clay_SDL2_Render(renderer, renderCommands);
+        Clay_SDL2_Render(renderer, renderCommands, fonts);
 
         SDL_RenderPresent(renderer);
     }
diff --git a/examples/SDL3-simple-demo/main.c b/examples/SDL3-simple-demo/main.c
index e2d7fb6..a1bfd15 100644
--- a/examples/SDL3-simple-demo/main.c
+++ b/examples/SDL3-simple-demo/main.c
@@ -21,8 +21,10 @@ typedef struct app_state {
     SDL_Renderer *renderer;
 } AppState;
 
-static inline Clay_Dimensions SDL_MeasureText(Clay_String *text, Clay_TextElementConfig *config)
+static inline Clay_Dimensions SDL_MeasureText(Clay_String *text, Clay_TextElementConfig *config, uintptr_t userData)
 {
+
+
     TTF_Font *font = gFonts[config->fontId];
     int width, height;
 
@@ -114,7 +116,7 @@ SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
 
     int width, height;
     SDL_GetWindowSize(state->window, &width, &height);
-    Clay_SetMeasureTextFunction(SDL_MeasureText);
+    Clay_SetMeasureTextFunction(SDL_MeasureText, 0);
     Clay_Initialize(clayMemory, (Clay_Dimensions) { (float) width, (float) height }, (Clay_ErrorHandler) { HandleClayErrors });
 
     *appstate = state;
diff --git a/examples/introducing-clay-video-demo/main.c b/examples/introducing-clay-video-demo/main.c
index 9f6d526..2e7b227 100644
--- a/examples/introducing-clay-video-demo/main.c
+++ b/examples/introducing-clay-video-demo/main.c
@@ -84,7 +84,7 @@ int main(void) {
        .width = GetScreenWidth(),
        .height = GetScreenHeight()
     }, (Clay_ErrorHandler) { HandleClayErrors }); // This final argument is new since the video was published
-    Clay_SetMeasureTextFunction(Raylib_MeasureText);
+    Clay_SetMeasureTextFunction(Raylib_MeasureText, 0);
     Raylib_fonts[FONT_ID_BODY_16] = (Raylib_Font) {
         .font = LoadFontEx("resources/Roboto-Regular.ttf", 48, 0, 400),
         .fontId = FONT_ID_BODY_16
diff --git a/examples/raylib-multi-context/main.c b/examples/raylib-multi-context/main.c
index 7ae697a..8490447 100644
--- a/examples/raylib-multi-context/main.c
+++ b/examples/raylib-multi-context/main.c
@@ -247,7 +247,7 @@ int main(void) {
             .height = GetScreenHeight() / 2
     }, (Clay_ErrorHandler) { HandleClayErrors }); // This final argument is new since the video was published
 
-    Clay_SetMeasureTextFunction(Raylib_MeasureText);
+    Clay_SetMeasureTextFunction(Raylib_MeasureText, 0);
     Raylib_fonts[FONT_ID_BODY_16] = (Raylib_Font) {
         .font = LoadFontEx("resources/Roboto-Regular.ttf", 48, 0, 400),
         .fontId = FONT_ID_BODY_16
diff --git a/examples/raylib-sidebar-scrolling-container/main.c b/examples/raylib-sidebar-scrolling-container/main.c
index b7d7ec4..630eaa0 100644
--- a/examples/raylib-sidebar-scrolling-container/main.c
+++ b/examples/raylib-sidebar-scrolling-container/main.c
@@ -218,7 +218,7 @@ void HandleClayErrors(Clay_ErrorData errorData) {
 int main(void) {
     uint64_t totalMemorySize = Clay_MinMemorySize();
     Clay_Arena clayMemory = Clay_CreateArenaWithCapacityAndMemory(totalMemorySize, malloc(totalMemorySize));
-    Clay_SetMeasureTextFunction(Raylib_MeasureText);
+    Clay_SetMeasureTextFunction(Raylib_MeasureText, 0);
     Clay_Initialize(clayMemory, (Clay_Dimensions) { (float)GetScreenWidth(), (float)GetScreenHeight() }, (Clay_ErrorHandler) { HandleClayErrors });
     Clay_Raylib_Initialize(1024, 768, "Clay - Raylib Renderer Example", FLAG_VSYNC_HINT | FLAG_WINDOW_RESIZABLE | FLAG_WINDOW_HIGHDPI | FLAG_MSAA_4X_HINT);
     profilePicture = LoadTextureFromImage(LoadImage("resources/profile-picture.png"));
diff --git a/renderers/SDL2/clay_renderer_SDL2.c b/renderers/SDL2/clay_renderer_SDL2.c
index 30eb8a4..c78a916 100644
--- a/renderers/SDL2/clay_renderer_SDL2.c
+++ b/renderers/SDL2/clay_renderer_SDL2.c
@@ -12,11 +12,12 @@ typedef struct
     TTF_Font *font;
 } SDL2_Font;
 
-static SDL2_Font SDL2_fonts[1];
 
-static Clay_Dimensions SDL2_MeasureText(Clay_String *text, Clay_TextElementConfig *config)
+static Clay_Dimensions SDL2_MeasureText(Clay_String *text, Clay_TextElementConfig *config, uintptr_t userData)
 {
-    TTF_Font *font = SDL2_fonts[config->fontId].font;
+    SDL2_Font *fonts = (SDL2_Font*)userData;
+
+    TTF_Font *font = fonts[config->fontId].font;
     char *chars = (char *)calloc(text->length + 1, 1);
     memcpy(chars, text->chars, text->length);
     int width = 0;
@@ -34,7 +35,7 @@ static Clay_Dimensions SDL2_MeasureText(Clay_String *text, Clay_TextElementConfi
 
 SDL_Rect currentClippingRectangle;
 
-static void Clay_SDL2_Render(SDL_Renderer *renderer, Clay_RenderCommandArray renderCommands)
+static void Clay_SDL2_Render(SDL_Renderer *renderer, Clay_RenderCommandArray renderCommands, SDL2_Font *fonts)
 {
     for (uint32_t i = 0; i < renderCommands.length; i++)
     {
@@ -60,7 +61,7 @@ static void Clay_SDL2_Render(SDL_Renderer *renderer, Clay_RenderCommandArray ren
                 Clay_String text = renderCommand->text;
                 char *cloned = (char *)calloc(text.length + 1, 1);
                 memcpy(cloned, text.chars, text.length);
-                TTF_Font* font = SDL2_fonts[config->fontId].font;
+                TTF_Font* font = fonts[config->fontId].font;
                 SDL_Surface *surface = TTF_RenderUTF8_Blended(font, cloned, (SDL_Color) {
                         .r = (Uint8)config->textColor.r,
                         .g = (Uint8)config->textColor.g,
diff --git a/renderers/raylib/clay_renderer_raylib.c b/renderers/raylib/clay_renderer_raylib.c
index 0fe545a..4fc4bd9 100644
--- a/renderers/raylib/clay_renderer_raylib.c
+++ b/renderers/raylib/clay_renderer_raylib.c
@@ -89,7 +89,7 @@ Ray GetScreenToWorldPointWithZDistance(Vector2 position, Camera camera, int scre
 
 uint32_t measureCalls = 0;
 
-static inline Clay_Dimensions Raylib_MeasureText(Clay_String *text, Clay_TextElementConfig *config) {
+static inline Clay_Dimensions Raylib_MeasureText(Clay_String *text, Clay_TextElementConfig *config, uintptr_t userData) {
     measureCalls++;
     // Measure string size for Font
     Clay_Dimensions textSize = { 0 };