SDL_ttf: Cleanup and polish on the new TTF_Text API

From 40e606fb1e83d632139185d8672b34d2db0a629d Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 21 Oct 2024 02:42:09 -0700
Subject: [PATCH] Cleanup and polish on the new TTF_Text API

* showfont uses the API to show the caption
* showfont now has an -editbox command line option to show the editbox
* TTF_MeasureString() returns width in pixels and max_length in bytes
* Removed TTF_CreateText_Wrapped()
* TTF_SetTextWrapping() has been renamed TTF_SetTextWrapWidth()
* TTF_GetTextWrapping() has been renamed TTF_GetTextWrapWidth()

Fixes https://github.com/libsdl-org/SDL_ttf/issues/418
---
 examples/editbox.c         |   5 +-
 examples/showfont.c        | 116 ++++++++--------
 examples/testapp.c         |   6 +-
 include/SDL3_ttf/SDL_ttf.h | 219 +++++++++++++----------------
 src/SDL_ttf.c              | 273 ++++++++++++++++---------------------
 src/SDL_ttf.sym            |   5 +-
 6 files changed, 277 insertions(+), 347 deletions(-)

diff --git a/examples/editbox.c b/examples/editbox.c
index f5f701a9..53f1449a 100644
--- a/examples/editbox.c
+++ b/examples/editbox.c
@@ -335,7 +335,7 @@ EditBox *EditBox_Create(SDL_Window *window, SDL_Renderer *renderer, TTF_TextEngi
     edit->window = window;
     edit->renderer = renderer;
     edit->font = font;
-    edit->text = TTF_CreateText_Wrapped(engine, font, NULL, 0, (int)SDL_floorf(rect->w));
+    edit->text = TTF_CreateText(engine, font, NULL, 0);
     if (!edit->text) {
         EditBox_Destroy(edit);
         return NULL;
@@ -344,6 +344,9 @@ EditBox *EditBox_Create(SDL_Window *window, SDL_Renderer *renderer, TTF_TextEngi
     edit->highlight1 = -1;
     edit->highlight2 = -1;
 
+    /* Wrap the editbox text within the editbox area */
+    TTF_SetTextWrapWidth(edit->text, (int)SDL_floorf(rect->w));
+
     /* Show the whitespace when wrapping, so it can be edited */
     TTF_SetTextWrapWhitespaceVisible(edit->text, true);
 
diff --git a/examples/showfont.c b/examples/showfont.c
index 9ff9c6d0..244abad1 100644
--- a/examples/showfont.c
+++ b/examples/showfont.c
@@ -40,7 +40,7 @@
 
 
 #define TTF_SHOWFONT_USAGE \
-"Usage: %s [-textengine surface|renderer] [-shaded] [-blended] [-wrapped] [-b] [-i] [-u] [-s] [-outline size] [-hintlight|-hintmono|-hintnone] [-nokerning] [-wrap] [-align left|center|right] [-fgcol r,g,b,a] [-bgcol r,g,b,a] <font>.ttf [ptsize] [text]\n"
+"Usage: %s [-textengine surface|renderer] [-shaded] [-blended] [-wrapped] [-b] [-i] [-u] [-s] [-outline size] [-hintlight|-hintmono|-hintnone] [-nokerning] [-wrap] [-align left|center|right] [-fgcol r,g,b,a] [-bgcol r,g,b,a] [-editbox] <font>.ttf [ptsize] [text]\n"
 
 typedef enum
 {
@@ -61,8 +61,8 @@ typedef struct {
     SDL_Surface *window_surface;
     SDL_Renderer *renderer;
     TTF_Font *font;
-    SDL_Texture *caption;
-    SDL_FRect captionRect;
+    TTF_Text *caption;
+    SDL_Rect captionRect;
     SDL_Texture *message;
     SDL_FRect messageRect;
     TextEngine textEngine;
@@ -96,7 +96,20 @@ static void DrawScene(Scene *scene)
         EditBox_Draw(scene->edit);
     }
 
-    SDL_RenderTexture(renderer, scene->caption, NULL, &scene->captionRect);
+    switch (scene->textEngine) {
+    case TextEngineSurface:
+        /* Flush the renderer so we can draw directly to the window surface */
+        SDL_FlushRenderer(renderer);
+        TTF_DrawSurfaceText(scene->caption, scene->captionRect.w, scene->captionRect.h, scene->window_surface);
+        break;
+    case TextEngineRenderer:
+        TTF_DrawRendererText(scene->caption, (float)scene->captionRect.x, (float)scene->captionRect.y);
+        break;
+    default:
+        SDL_assert(!"Unknown text engine");
+        break;
+    }
+
     SDL_RenderTexture(renderer, scene->message, NULL, &scene->messageRect);
     SDL_RenderPresent(renderer);
 
@@ -269,26 +282,20 @@ int main(int argc, char *argv[])
     SDL_Color *backcol;
     SDL_Event event;
     TTF_TextEngine *engine = NULL;
-    TextRenderMethod rendermethod;
-    int renderstyle;
-    int outline;
-    int hinting;
-    int kerning;
-    int wrap;
+    TextRenderMethod rendermethod = TextRenderShaded;
+    int renderstyle = TTF_STYLE_NORMAL;
+    int outline = 0;
+    int hinting = TTF_HINTING_NORMAL;
+    int kerning = 1;
+    bool wrap = false;
     TTF_HorizontalAlignment align = TTF_HORIZONTAL_ALIGN_LEFT;
-    int dump;
+    bool editbox = false;
+    bool dump = false;
     char *message, string[128];
 
-    /* Look for special execution mode */
-    dump = 0;
-    /* Look for special rendering types */
     SDL_zero(scene);
-    rendermethod = TextRenderShaded;
-    renderstyle = TTF_STYLE_NORMAL;
-    outline = 0;
-    hinting = TTF_HINTING_NORMAL;
-    kerning = 1;
-    wrap = 0;
+    scene.textEngine = TextEngineRenderer;
+
     /* Default is black and white */
     forecol = &black;
     backcol = &white;
@@ -341,7 +348,7 @@ int main(int argc, char *argv[])
             kerning = 0;
         } else
         if (SDL_strcmp(argv[i], "-wrap") == 0) {
-            wrap = 1;
+            wrap = true;
         } else
         if (SDL_strcmp(argv[i], "-align") == 0 && argv[i+1]) {
             ++i;
@@ -356,9 +363,6 @@ int main(int argc, char *argv[])
                 return (1);
             }
         } else
-        if (SDL_strcmp(argv[i], "-dump") == 0) {
-            dump = 1;
-        } else
         if (SDL_strcmp(argv[i], "-fgcol") == 0 && argv[i+1]) {
             int r, g, b, a = SDL_ALPHA_OPAQUE;
             if (SDL_sscanf(argv[++i], "%d,%d,%d,%d", &r, &g, &b, &a) < 3) {
@@ -380,6 +384,12 @@ int main(int argc, char *argv[])
             backcol->g = (Uint8)g;
             backcol->b = (Uint8)b;
             backcol->a = (Uint8)a;
+        } else
+        if (SDL_strcmp(argv[i], "-editbox") == 0) {
+            editbox = true;
+        } else
+        if (SDL_strcmp(argv[i], "-dump") == 0) {
+            dump = true;
         } else {
             SDL_Log(TTF_SHOWFONT_USAGE, argv0);
             return(1);
@@ -467,24 +477,32 @@ int main(int argc, char *argv[])
         Cleanup(2);
     }
 
-    /* Show which font file we're looking at */
-    SDL_snprintf(string, sizeof(string), "Font file: %s", argv[0]);  /* possible overflow */
-    switch (rendermethod) {
-    case TextRenderShaded:
-        text = TTF_RenderText_Shaded(font, string, 0, *forecol, *backcol);
+    switch (scene.textEngine) {
+    case TextEngineSurface:
+        engine = TTF_CreateSurfaceTextEngine();
+        if (!engine) {
+            SDL_Log("Couldn't create surface text engine: %s\n", SDL_GetError());
+            Cleanup(2);
+        }
         break;
-    case TextRenderBlended:
-        text = TTF_RenderText_Blended(font, string, 0, *forecol);
+    case TextEngineRenderer:
+        engine = TTF_CreateRendererTextEngine(scene.renderer);
+        if (!engine) {
+            SDL_Log("Couldn't create renderer text engine: %s\n", SDL_GetError());
+            Cleanup(2);
+        }
+        break;
+    default:
         break;
     }
-    if (text != NULL) {
-        scene.captionRect.x = 4.0f;
-        scene.captionRect.y = 4.0f;
-        scene.captionRect.w = (float)text->w;
-        scene.captionRect.h = (float)text->h;
-        scene.caption = SDL_CreateTextureFromSurface(scene.renderer, text);
-        SDL_DestroySurface(text);
-    }
+
+    /* Show which font file we're looking at */
+    SDL_snprintf(string, sizeof(string), "Font file: %s", argv[0]);  /* possible overflow */
+    scene.caption = TTF_CreateText(engine, font, string, 0);
+    TTF_SetTextColor(scene.caption, forecol->r, forecol->g, forecol->b, forecol->a);
+    scene.captionRect.x = 4;
+    scene.captionRect.y = 4;
+    TTF_GetTextSize(scene.caption, &scene.captionRect.w, &scene.captionRect.h);
 
     /* Render and center the message */
     if (argc > 2) {
@@ -521,23 +539,7 @@ int main(int argc, char *argv[])
     SDL_Log("Font is generally %d big, and string is %d big\n",
                         TTF_GetFontHeight(font), text->h);
 
-    switch (scene.textEngine) {
-    case TextEngineSurface:
-        engine = TTF_CreateSurfaceTextEngine();
-        if (!engine) {
-            SDL_Log("Couldn't create surface text engine: %s\n", SDL_GetError());
-        }
-        break;
-    case TextEngineRenderer:
-        engine = TTF_CreateRendererTextEngine(scene.renderer);
-        if (!engine) {
-            SDL_Log("Couldn't create renderer text engine: %s\n", SDL_GetError());
-        }
-        break;
-    default:
-        break;
-    }
-    if (engine) {
+    if (editbox) {
         scene.textRect.x = 8.0f;
         scene.textRect.y = scene.captionRect.y + scene.captionRect.h + 4.0f;
         scene.textRect.w = WIDTH / 2 - scene.textRect.x * 2;
@@ -601,7 +603,7 @@ int main(int argc, char *argv[])
     default:
         break;
     }
-    SDL_DestroyTexture(scene.caption);
+    TTF_DestroyText(scene.caption);
     SDL_DestroyTexture(scene.message);
     Cleanup(0);
 
diff --git a/examples/testapp.c b/examples/testapp.c
index 7950b276..57cd4590 100644
--- a/examples/testapp.c
+++ b/examples/testapp.c
@@ -1064,9 +1064,11 @@ int main(void)
                             break;
                     }
                 } else if (textengine_mode == 1) {
-                    text_obj = TTF_CreateText_Wrapped(engine_surface, font, text, 0, wrap_size);
+                    text_obj = TTF_CreateText(engine_surface, font, text, 0);
+                    TTF_SetTextWrapWidth(text_obj, wrap_size);
                 } else {
-                    text_obj = TTF_CreateText_Wrapped(engine_renderer, font, text, 0, wrap_size);
+                    text_obj = TTF_CreateText(engine_renderer, font, text, 0);
+                    TTF_SetTextWrapWidth(text_obj, wrap_size);
                 }
 
                 if (print_elapsed_ticks) {
diff --git a/include/SDL3_ttf/SDL_ttf.h b/include/SDL3_ttf/SDL_ttf.h
index 3671fd08..43043c50 100644
--- a/include/SDL3_ttf/SDL_ttf.h
+++ b/include/SDL3_ttf/SDL_ttf.h
@@ -993,15 +993,15 @@ extern SDL_DECLSPEC bool SDLCALL TTF_GetStringSize(TTF_Font *font, const char *t
  * specified string will take to fully render.
  *
  * Text is wrapped to multiple lines on line endings and on word boundaries if
- * it extends beyond `wrapLength` in pixels.
+ * it extends beyond `wrap_width` in pixels.
  *
- * If wrapLength is 0, this function will only wrap on newline characters.
+ * If wrap_width is 0, this function will only wrap on newline characters.
  *
  * \param font the font to query.
  * \param text text to calculate, in UTF-8 encoding.
  * \param length the length of the text, in bytes, or 0 for null terminated
  *               text.
- * \param wrapLength the maximum width or 0 to wrap on newline characters.
+ * \param wrap_width the maximum width or 0 to wrap on newline characters.
  * \param w will be filled with width, in pixels, on return.
  * \param h will be filled with height, in pixels, on return.
  * \returns true on success or false on failure; call SDL_GetError() for more
@@ -1012,13 +1012,13 @@ extern SDL_DECLSPEC bool SDLCALL TTF_GetStringSize(TTF_Font *font, const char *t
  *
  * \since This function is available since SDL_ttf 3.0.0.
  */
-extern SDL_DECLSPEC bool SDLCALL TTF_GetStringSizeWrapped(TTF_Font *font, const char *text, size_t length, int wrapLength, int *w, int *h);
+extern SDL_DECLSPEC bool SDLCALL TTF_GetStringSizeWrapped(TTF_Font *font, const char *text, size_t length, int wrap_width, int *w, int *h);
 
 /**
  * Calculate how much of a UTF-8 string will fit in a given width.
  *
  * This reports the number of characters that can be rendered before reaching
- * `measure_width`.
+ * `max_width`.
  *
  * This does not need to render the string to do this calculation.
  *
@@ -1026,10 +1026,9 @@ extern SDL_DECLSPEC bool SDLCALL TTF_GetStringSizeWrapped(TTF_Font *font, const
  * \param text text to calculate, in UTF-8 encoding.
  * \param length the length of the text, in bytes, or 0 for null terminated
  *               text.
- * \param measure_width maximum width, in pixels, available for the string.
- * \param extent on return, filled with latest calculated width.
- * \param count on return, filled with number of characters that can be
- *              rendered.
+ * \param max_width maximum width, in pixels, available for the string, or 0 for unbounded width.
+ * \param measured_width a pointer filled in with the width, in pixels, of the string that will fit, may be NULL.
+ * \param measured_length a pointer filled in with the length, in bytes, of the string that will fit, may be NULL.
  * \returns true on success or false on failure; call SDL_GetError() for more
  *          information.
  *
@@ -1038,7 +1037,7 @@ extern SDL_DECLSPEC bool SDLCALL TTF_GetStringSizeWrapped(TTF_Font *font, const
  *
  * \since This function is available since SDL_ttf 3.0.0.
  */
-extern SDL_DECLSPEC bool SDLCALL TTF_MeasureString(TTF_Font *font, const char *text, size_t length, int measure_width, int *extent, int *count);
+extern SDL_DECLSPEC bool SDLCALL TTF_MeasureString(TTF_Font *font, const char *text, size_t length, int max_width, int *measured_width, size_t *measured_length);
 
 /**
  * Render UTF-8 text at high quality to a new 8-bit surface.
@@ -1083,9 +1082,9 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Shaded(TTF_Font *font,
  * surface, or NULL if there was an error.
  *
  * Text is wrapped to multiple lines on line endings and on word boundaries if
- * it extends beyond `wrapLength` in pixels.
+ * it extends beyond `wrap_width` in pixels.
  *
- * If wrapLength is 0, this function will only wrap on newline characters.
+ * If wrap_width is 0, this function will only wrap on newline characters.
  *
  * \param font the font to render with.
  * \param text text to render, in UTF-8 encoding.
@@ -1093,7 +1092,7 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Shaded(TTF_Font *font,
  *               text.
  * \param fg the foreground color for the text.
  * \param bg the background color for the text.
- * \param wrapLength the maximum width of the text surface or 0 to wrap on
+ * \param wrap_width the maximum width of the text surface or 0 to wrap on
  *                   newline characters.
  * \returns a new 8-bit, palettized surface, or NULL if there was an error.
  *
@@ -1106,7 +1105,7 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Shaded(TTF_Font *font,
  * \sa TTF_RenderText_LCD_Wrapped
  * \sa TTF_RenderText_Shaded
  */
-extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Shaded_Wrapped(TTF_Font *font, const char *text, size_t length, SDL_Color fg, SDL_Color bg, int wrapLength);
+extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Shaded_Wrapped(TTF_Font *font, const char *text, size_t length, SDL_Color fg, SDL_Color bg, int wrap_width);
 
 /**
  * Render a single UNICODE codepoint at high quality to a new 8-bit surface.
@@ -1175,16 +1174,16 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended(TTF_Font *font,
  * new surface, or NULL if there was an error.
  *
  * Text is wrapped to multiple lines on line endings and on word boundaries if
- * it extends beyond `wrapLength` in pixels.
+ * it extends beyond `wrap_width` in pixels.
  *
- * If wrapLength is 0, this function will only wrap on newline characters.
+ * If wrap_width is 0, this function will only wrap on newline characters.
  *
  * \param font the font to render with.
  * \param text text to render, in UTF-8 encoding.
  * \param length the length of the text, in bytes, or 0 for null terminated
  *               text.
  * \param fg the foreground color for the text.
- * \param wrapLength the maximum width of the text surface or 0 to wrap on
+ * \param wrap_width the maximum width of the text surface or 0 to wrap on
  *                   newline characters.
  * \returns a new 32-bit, ARGB surface, or NULL if there was an error.
  *
@@ -1197,7 +1196,7 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended(TTF_Font *font,
  * \sa TTF_RenderText_LCD_Wrapped
  * \sa TTF_RenderText_Shaded_Wrapped
  */
-extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended_Wrapped(TTF_Font *font, const char *text, size_t length, SDL_Color fg, int wrapLength);
+extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_Blended_Wrapped(TTF_Font *font, const char *text, size_t length, SDL_Color fg, int wrap_width);
 
 /**
  * Render a single UNICODE codepoint at high quality to a new ARGB surface.
@@ -1266,9 +1265,9 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_LCD(TTF_Font *font, con
  * returns the new surface, or NULL if there was an error.
  *
  * Text is wrapped to multiple lines on line endings and on word boundaries if
- * it extends beyond `wrapLength` in pixels.
+ * it extends beyond `wrap_width` in pixels.
  *
- * If wrapLength is 0, this function will only wrap on newline characters.
+ * If wrap_width is 0, this function will only wrap on newline characters.
  *
  * \param font the font to render with.
  * \param text text to render, in UTF-8 encoding.
@@ -1276,7 +1275,7 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_LCD(TTF_Font *font, con
  *               text.
  * \param fg the foreground color for the text.
  * \param bg the background color for the text.
- * \param wrapLength the maximum width of the text surface or 0 to wrap on
+ * \param wrap_width the maximum width of the text surface or 0 to wrap on
  *                   newline characters.
  * \returns a new 32-bit, ARGB surface, or NULL if there was an error.
  *
@@ -1289,7 +1288,7 @@ extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_LCD(TTF_Font *font, con
  * \sa TTF_RenderText_LCD
  * \sa TTF_RenderText_Shaded_Wrapped
  */
-extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_LCD_Wrapped(TTF_Font *font, const char *text, size_t length, SDL_Color fg, SDL_Color bg, int wrapLength);
+extern SDL_DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_LCD_Wrapped(TTF_Font *font, const char *text, size_t length, SDL_Color fg, SDL_Color bg, int wrap_width);
 
 /**
  * Render a single UNICODE codepoint at LCD subpixel quality to a new ARGB
@@ -1334,7 +1333,6 @@ typedef struct TTF_TextData TTF_TextData;
  * \since This struct is available since SDL_ttf 3.0.0.
  *
  * \sa TTF_CreateText
- * \sa TTF_CreateText_Wrapped
  * \sa TTF_GetTextProperties
  * \sa TTF_DestroyText
  */
@@ -1386,7 +1384,6 @@ extern SDL_DECLSPEC TTF_TextEngine * SDLCALL TTF_CreateSurfaceTextEngine(void);
  *
  * \sa TTF_CreateSurfaceTextEngine
  * \sa TTF_CreateText
- * \sa TTF_CreateText_Wrapped
  */
 extern SDL_DECLSPEC bool SDLCALL TTF_DrawSurfaceText(TTF_Text *text, int x, int y, SDL_Surface *surface);
 
@@ -1446,7 +1443,6 @@ extern SDL_DECLSPEC TTF_TextEngine * SDLCALL TTF_CreateRendererTextEngine(SDL_Re
  *
  * \sa TTF_CreateRendererTextEngine
  * \sa TTF_CreateText
- * \sa TTF_CreateText_Wrapped
  */
 extern SDL_DECLSPEC bool SDLCALL TTF_DrawRendererText(TTF_Text *text, float x, float y);
 
@@ -1471,9 +1467,6 @@ extern SDL_DECLSPEC void SDLCALL TTF_DestroyRendererTextEngine(TTF_TextEngine *e
 /**
  * Create a text object from UTF-8 text and a text engine.
  *
- * This function is equivalent to `TTF_CreateText_Wrapped(engine, font, text,
- * 0)` and will wrap on newline characters.
- *
  * \param engine the text engine to use when creating the text object, may be
  *               NULL.
  * \param font the font to render with.
@@ -1488,40 +1481,10 @@ extern SDL_DECLSPEC void SDLCALL TTF_DestroyRendererTextEngine(TTF_TextEngine *e
  *
  * \since This function is available since SDL_ttf 3.0.0.
  *
- * \sa TTF_CreateText_Wrapped
  * \sa TTF_DestroyText
  */
 extern SDL_DECLSPEC TTF_Text * SDLCALL TTF_CreateText(TTF_TextEngine *engine, TTF_Font *font, const char *text, size_t length);
 
-/**
- * Create a text object from word-wrapped UTF-8 text and a text engine.
- *
- * Text is wrapped to multiple lines on line endings and on word boundaries if
- * it extends beyond `wrapLength` in pixels.
- *
- * If wrapLength is 0, this function will only wrap on newline characters.
- *
- * \param engine the text engine to use when creating the text object, may be
- *               NULL.
- * \param font the font to render with.
- * \param text the text to use, in UTF-8 encoding.
- * \param length the length of the text, in bytes, or 0 for null terminated
- *               text.
- * \param wrapLength the maximum width of the text surface or 0 to wrap on
- *                   newline characters.
- * \returns a TTF_Text object or NULL on failure; call SDL_GetError() for more
- *          information.
- *
- * \threadsafety This function should be called on the thread that created the
- *               font.
- *
- * \since This function is available since SDL_ttf 3.0.0.
- *
- * \sa TTF_CreateText
- * \sa TTF_DestroyText
- */
-extern SDL_DECLSPEC TTF_Text * SDLCALL TTF_CreateText_Wrapped(TTF_TextEngine *engine, TTF_Font *font, const char *text, size_t length, int wrapLength);
-
 /**
  * Get the properties associated with a text object.
  *
@@ -1738,12 +1701,11 @@ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextPosition(TTF_Text *text, int x, int
 extern SDL_DECLSPEC bool SDLCALL TTF_GetTextPosition(TTF_Text *text, int *x, int *y);
 
 /**
- * Set the UTF-8 text used by a text object.
+ * Set whether wrapping is enabled on a text object.
  *
  * \param text the TTF_Text to modify.
- * \param string the UTF-8 text to use, may be NULL.
- * \param length the length of the text, in bytes, or 0 for null terminated
- *               text.
+ * \param wrap_width the maximum width in pixels, 0 to wrap on newline
+ *                   characters.
  * \returns true on success or false on failure; call SDL_GetError() for more
  *          information.
  *
@@ -1752,23 +1714,16 @@ extern SDL_DECLSPEC bool SDLCALL TTF_GetTextPosition(TTF_Text *text, int *x, int
  *
  * \since This function is available since SDL_ttf 3.0.0.
  *
- * \sa TTF_AppendTextString
- * \sa TTF_DeleteTextString
- * \sa TTF_InsertTextString
+ * \sa TTF_GetTextWrapWidth
  */
-extern SDL_DECLSPEC bool SDLCALL TTF_SetTextString(TTF_Text *text, const char *string, size_t length);
+extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapWidth(TTF_Text *text, int wrap_width);
 
 /**
- * Insert UTF-8 text into a text object.
+ * Get whether wrapping is enabled on a text object.
  *
- * \param text the TTF_Text to modify.
- * \param offset the offset, in bytes, from the beginning of the string if >=
- *               0, the offset from the end of the string if < 0. Note that
- *               this does not do UTF-8 validation, so you should only insert
- *               at UTF-8 sequence boundaries.
- * \param string the UTF-8 text to insert.
- * \param length the length of the text, in bytes, or 0 for null terminated
- *               text.
+ * \param text the TTF_Text to query.
+ * \param wrap_width a pointer filled in with the maximum width in pixels or 0
+ *                   if the text is being wrapped on newline characters.
  * \returns true on success or false on failure; call SDL_GetError() for more
  *          information.
  *
@@ -1777,19 +1732,21 @@ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextString(TTF_Text *text, const char *s
  *
  * \since This function is available since SDL_ttf 3.0.0.
  *
- * \sa TTF_AppendTextString
- * \sa TTF_DeleteTextString
- * \sa TTF_SetTextString
+ * \sa TTF_SetTextWrapWidth
  */
-extern SDL_DECLSPEC bool SDLCALL TTF_InsertTextString(TTF_Text *text, int offset, const char *string, size_t length);
+extern SDL_DECLSPEC bool SDLCALL TTF_GetTextWrapWidth(TTF_Text *text, int *wrap_width);
 
 /**
- * Append UTF-8 text to a text object.
+ * Set whether whitespace should be visible when wrapping a text object.
+ *
+ * If the whitespace is visible, it will take up space for purposes of
+ * alignment and wrapping. This is good for editing, but looks better when
+ * centered or aligned if whitespace around line wrapping is hidden. This
+ * defaults false.
  *
  * \param text the TTF_Text to modify.
- * \param string the UTF-8 text to insert.
- * \param length the length of the text, in bytes, or 0 for null terminated
- *               text.
+ * \param visible true to show whitespace when wrapping text, false to hide
+ *                it.
  * \returns true on success or false on failure; call SDL_GetError() for more
  *          information.
  *
@@ -1798,42 +1755,33 @@ extern SDL_DECLSPEC bool SDLCALL TTF_InsertTextString(TTF_Text *text, int offset
  *
  * \since This function is available since SDL_ttf 3.0.0.
  *
- * \sa TTF_DeleteTextString
- * \sa TTF_InsertTextString
- * \sa TTF_SetTextString
+ * \sa TTF_TextWrapWhitespaceVisible
  */
-extern SDL_DECLSPEC bool SDLCALL TTF_AppendTextString(TTF_Text *text, const char *string, size_t length);
+extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapWhitespaceVisible(TTF_Text *text, bool visible);
 
 /**
- * Delete UTF-8 text from a text object.
+ * Return whether whitespace is shown when wrapping a text object.
  *
- * \param text the TTF_Text to modify.
- * \param offset the offset, in bytes, from the beginning of the string if >=
- *               0, the offset from the end of the string if < 0. Note that
- *               this does not do UTF-8 validation, so you should only delete
- *               at UTF-8 sequence boundaries.
- * \param length the length of text to delete, in bytes, or -1 for the
- *               remainder of the string.
- * \returns true on success or false on failure; call SDL_GetError() for more
- *          information.
+ * \param text the TTF_Text to query.
+ * \returns true if whitespace is shown when wrapping text, or false
+ *          otherwise.
  *
  * \threadsafety This function should be called on the thread that created the
  *               text.
  *
  * \since This function is available since SDL_ttf 3.0.0.
  *
- * \sa TTF_AppendTextString
- * \sa TTF_InsertTextString
- * \sa TTF_SetTextString
+ * \sa TTF_SetTextWrapWhitespaceVisible
  */
-extern SDL_DECLSPEC bool SDLCALL TTF_DeleteTextString(TTF_Text *text, int offset, int length);
+extern SDL_DECLSPEC bool SDLCALL TTF_TextWrapWhitespaceVisible(TTF_Text *text);
 
 /**
- * Set whether wrapping is enabled on a text object.
+ * Set the UTF-8 text used by a text object.
  *
  * \param text the TTF_Text to modify.
- * \param wrapLength the maximum width in pixels, 0 to wrap on newline
- *                   characters.
+ * \param string the UTF-8 text to use, may be NULL.
+ * \param length the length of the text, in bytes, or 0 for null terminated
+ *               text.
  * \returns true on success or false on failure; call SDL_GetError() for more
  *          information.
  *
@@ -1842,16 +1790,23 @@ extern SDL_DECLSPEC bool SDLCALL TTF_DeleteTextString(TTF_Text *text, int offset
  *
  * \since This function is available since SDL_ttf 3.0.0.
  *
- * \sa TTF_GetTextWrapping
+ * \sa TTF_AppendTextString
+ * \sa TTF_DeleteTextString
+ * \sa TTF_InsertTextString
  */
-extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapping(TTF_Text *text, int wrapLength);
+extern SDL_DECLSPEC bool SDLCALL TTF_SetTextString(TTF_Text *text, const char *string, size_t length);
 
 /**
- * Get whether wrapping is enabled on a text object.
+ * Insert UTF-8 text into a text object.
  *
- * \param text the TTF_Text to query.
- * \param wrapLength a pointer filled in with the maximum width in pixels or 0
- *                   if the text is being wrapped on newline characters.
+ * \param text the TTF_Text to modify.
+ * \param offset the offset, in bytes, from the beginning of the string if >=
+ *               0, the offset from the end of the string if < 0. Note that
+ *               this does not do UTF-8 validation, so you should only insert
+ *               at UTF-8 sequence boundaries.
+ * \param string the UTF-8 text to insert.
+ * \param length the length of the text, in bytes, or 0 for null terminated
+ *               text.
  * \returns true on success or false on failure; call SDL_GetError() for more
  *          information.
  *
@@ -1860,21 +1815,19 @@ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapping(TTF_Text *text, int wrapLen
  *
  * \since This function is available since SDL_ttf 3.0.0.
  *
- * \sa TTF_SetTextWrapping
+ * \sa TTF_AppendTextString
+ * \sa TTF_DeleteTextString
+ * \sa TTF_SetTextString
  */
-extern SDL_DECLSPEC bool SDLCALL TTF_GetTextWrapping(TTF_Text *text, int *wrapLength);
+extern SDL_DECLSPEC bool SDLCALL TTF_InsertTextString(TTF_Text *text, int offset, const char *string, size_t length);
 
 /**
- * Set whether whitespace should be visible when wrapping a text object.
- *
- * If the whitespace is visible, it will take up space for purposes of
- * alignment and wrapping. This is good for editing, but looks better when
- * centered or aligned if whitespace around line wrapping is hidden. This
- * defaults false.
+ * Append UTF-8 text to a text object.
  *
  * \param text the TTF_Text to modify.
- * \param visible true to show whitespace when wrapping text, false to hide
- *                it.
+ * \param string the UTF-8 text to insert.
+ * \param length the length of the text, in bytes, or 0 for null terminated
+ *               text.
  * \returns true on success or false on failure; call SDL_GetError() for more
  *          information.
  *
@@ -1883,25 +1836,35 @@ extern SDL_DECLSPEC bool SDLCALL TTF_GetTextWrapping(TTF_Text *text, int *wrapLe
  *
  * \since This function is available since SDL_ttf 3.0.0.
  *
- * \sa TTF_TextWrapWhitespaceVisible
+ * \sa TTF_DeleteTextString
+ * \sa TTF_InsertTextString
+ * \sa TTF_SetTextString
  */
-extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapWhitespaceVisible(TTF_Text *text, bool visible);
+extern SDL_DECLSPEC bool SDLCALL TTF_AppendTextString(TTF_Text *text, const char *string, size_t length);
 
 /**
- * Return whether whitespace is shown when wrapping a text object.
+ * Delete UTF-8 text from a text object.
  *
- * \param text the TTF_Text to query.
- * \returns true if whitespace is shown when wrapping text, or false
- *          otherwise.
+ * \param text the TTF_Text to modify.
+ * \param offset the offset, in bytes, from the beginning of the string if >=
+ *               0, the offset from the end of the string if < 0. Note that
+ *               this does not do UTF-8 validation, so you should only delete
+ *               at UTF-8 sequence boundaries.
+ * \param length the length of text to delete, in bytes, or -1 for the
+ *               remainder of the string.
+ * \returns true on success or false on failure; call SDL_GetError() for more
+ *          information.
  *
  * \threadsafety This function should be called on the thread that created the
  *               text.
  *
  * \since This function is available since SDL_ttf 3.0.0.
  *
- * \sa TTF_SetTextWrapWhitespaceVisible
+ * \sa TTF_AppendTextString
+ * \sa TTF_InsertTextString
+ * \sa TTF_SetTextString
  */
-extern SDL_DECLSPEC bool SDLCALL TTF_TextWrapWhitespaceVisible(TTF_Text *text);
+extern SDL_DECLSPEC bool SDLCALL TTF_DeleteTextString(TTF_Text *text, int offset, int length);
 
 /**
  * Get the size of a text object.
diff --git a/src/SDL_ttf.c b/src/SDL_ttf.c
index 37b04bb3..6908a729 100644
--- a/src/SDL_ttf.c
+++ b/src/SDL_ttf.c
@@ -344,7 +344,7 @@ typedef enum {
 } render_mode_t;
 
 #define NO_MEASUREMENT  \
-        0, NULL, NULL
+        false, 0, NULL, NULL
 
 
 static bool Find_GlyphByIndex(TTF_Font *font, FT_UInt idx, int want_pixmap, int want_color, int want_lcd, int want_subpixel, int translation, c_glyph **out_glyph, TTF_Image **out_image);
@@ -2917,7 +2917,7 @@ bool TTF_GetGlyphKerning(TTF_Font *font, Uint32 previous_ch, Uint32 ch, int *ker
     return true;
 }
 
-static bool TTF_Size_Internal(TTF_Font *font, const char *text

(Patch may be truncated, please check the link at the top of this post.)