SDL_ttf: TTF_GetGlyphKerning() returns bool

From 2efc6fc1489fba89fbf62367600aefd0c2ac816f Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 26 Sep 2024 18:54:22 -0700
Subject: [PATCH] TTF_GetGlyphKerning() returns bool

The actual kerning distance is stored in an output parameter, since -1 is a valid kerning distance.

Fixes https://github.com/libsdl-org/SDL_ttf/issues/55
---
 build-scripts/SDL_migration.cocci |  5 --
 docs/README-migration.md          |  3 +-
 include/SDL3_ttf/SDL_ttf.h        |  6 ++-
 src/SDL_ttf.c                     | 83 ++++++++++++++-----------------
 src/SDL_ttf.sym                   |  2 +-
 5 files changed, 44 insertions(+), 55 deletions(-)

diff --git a/build-scripts/SDL_migration.cocci b/build-scripts/SDL_migration.cocci
index 3d3e066b..6f4f67ea 100644
--- a/build-scripts/SDL_migration.cocci
+++ b/build-scripts/SDL_migration.cocci
@@ -83,8 +83,3 @@
 - TTF_RenderGlyph32_LCD
 + TTF_RenderGlyph_LCD
   (...)
-@@
-@@
-- TTF_GetFontKerningSizeGlyphs32
-+ TTF_GetFontKerningSizeGlyphs
-  (...)
diff --git a/docs/README-migration.md b/docs/README-migration.md
index 966e4d61..c3397373 100644
--- a/docs/README-migration.md
+++ b/docs/README-migration.md
@@ -37,7 +37,6 @@ Several functions have been renamed. We have provided a handy semantic patch to
 In general we have switched to using UTF8 in the API. Functions which had 3 variants, for Latin-1, UTF-8, and UCS2, now accept UTF-8 text. In addition, those functions now have an optional length parameter which allows you to render substrings.
 
 The following functions have been renamed:
-* TTF_GetFontKerningSizeGlyphs32() => TTF_GetFontKerningSizeGlyphs()
 * TTF_GlyphIsProvided32() => TTF_GlyphIsProvided()
 * TTF_GlyphMetrics32() => TTF_GlyphMetrics()
 * TTF_MeasureUTF8() => TTF_MeasureText()
@@ -57,6 +56,8 @@ The following functions have been renamed:
 
 The following functions have been removed:
 * TTF_ByteSwappedUNICODE()
+* TTF_GetFontKerningSizeGlyphs() - replaced with TTF_GetGlyphKerning()
+* TTF_GetFontKerningSizeGlyphs32() - replaced with TTF_GetGlyphKerning()
 * TTF_MeasureUNICODE()
 * TTF_OpenFontDPI() - replaced with TTF_OpenFontWithProperties()
 * TTF_OpenFontDPIIO() - replaced with TTF_OpenFontWithProperties()
diff --git a/include/SDL3_ttf/SDL_ttf.h b/include/SDL3_ttf/SDL_ttf.h
index c983240e..2346aecd 100644
--- a/include/SDL3_ttf/SDL_ttf.h
+++ b/include/SDL3_ttf/SDL_ttf.h
@@ -1181,13 +1181,15 @@ extern SDL_DECLSPEC int SDLCALL TTF_WasInit(void);
  * \param font the font to query.
  * \param previous_ch the previous character's code, 32 bits.
  * \param ch the current character's code, 32 bits.
- * \returns The kerning size between the two specified characters, in pixels, or -1 on failure; call SDL_GetError() for more information.
+ * \param kerning a pointer filled in with the kerning size between the two specified characters, in pixels, may be NULL.
+ * \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 font.
  *
  * \since This function is available since SDL_ttf 3.0.0.
  */
-extern SDL_DECLSPEC int TTF_GetFontKerningSizeGlyphs(TTF_Font *font, Uint32 previous_ch, Uint32 ch);
+extern SDL_DECLSPEC bool TTF_GetGlyphKerning(TTF_Font *font, Uint32 previous_ch, Uint32 ch, int *kerning);
 
 /**
  * Enable Signed Distance Field rendering for a font.
diff --git a/src/SDL_ttf.c b/src/SDL_ttf.c
index 5606dab7..08b9fd2d 100644
--- a/src/SDL_ttf.c
+++ b/src/SDL_ttf.c
@@ -333,7 +333,7 @@ static SDL_Surface* TTF_Render_Internal(TTF_Font *font, const char *text, size_t
 
 static SDL_Surface* TTF_Render_Wrapped_Internal(TTF_Font *font, const char *text, size_t length, SDL_Color fg, SDL_Color bg, int wrapLength, render_mode_t render_mode);
 
-static int Find_GlyphByIndex(TTF_Font *font, FT_UInt idx, int want_bitmap, int want_pixmap, int want_color, int want_lcd, int want_subpixel, int translation, c_glyph **out_glyph, TTF_Image **out_image);
+static bool Find_GlyphByIndex(TTF_Font *font, FT_UInt idx, int want_bitmap, int want_pixmap, int want_color, int want_lcd, int want_subpixel, int translation, c_glyph **out_glyph, TTF_Image **out_image);
 
 static void Flush_Cache(TTF_Font *font);
 
@@ -1122,7 +1122,7 @@ static int Render_Line_##NAME(TTF_Font *font, SDL_Surface *textbuf, int xstart,
         int y       = font->pos_buf[i].y;                                                                               \
         TTF_Image *image;                                                                                               \
                                                                                                                         \
-        if (Find_GlyphByIndex(font, idx, WB_WP_WC, WS, x & 63, NULL, &image) == 0) {                                    \
+        if (Find_GlyphByIndex(font, idx, WB_WP_WC, WS, x & 63, NULL, &image)) {                                    \
             int above_w, above_h;                                                                                       \
             Uint32 dstskip;                                                                                             \
             Sint32 srcskip; /* Can be negative */                                                                       \
@@ -2100,7 +2100,7 @@ static void Flush_Cache(TTF_Font *font)
     }
 }
 
-static FT_Error Load_Glyph(TTF_Font *font, c_glyph *cached, int want, int translation)
+static bool Load_Glyph(TTF_Font *font, c_glyph *cached, int want, int translation)
 {
     const int alignment = Get_Alignment() - 1;
     FT_GlyphSlot slot;
@@ -2124,8 +2124,7 @@ static FT_Error Load_Glyph(TTF_Font *font, c_glyph *cached, int want, int transl
 
     if (want & CACHED_LCD) {
         if (slot->format == FT_GLYPH_FORMAT_BITMAP) {
-            SDL_SetError("LCD mode not possible with bitmap font");
-            return -1;
+            return SDL_SetError("LCD mode not possible with bitmap font");
         }
     }
 
@@ -2602,14 +2601,13 @@ static FT_Error Load_Glyph(TTF_Font *font, c_glyph *cached, int want, int transl
     }
 
     /* We're done, this glyph is cached since 'stored' is not 0 */
-    return 0;
+    return true;
 
 ft_failure:
-    TTF_SetFTError("Couldn't find glyph", error);
-    return -1;
+    return TTF_SetFTError("Couldn't find glyph", error);
 }
 
-static int Find_GlyphByIndex(TTF_Font *font, FT_UInt idx,
+static bool Find_GlyphByIndex(TTF_Font *font, FT_UInt idx,
         int want_bitmap, int want_pixmap, int want_color, int want_lcd, int want_subpixel,
         int translation, c_glyph **out_glyph, TTF_Image **out_image)
 {
@@ -2632,7 +2630,6 @@ static int Find_GlyphByIndex(TTF_Font *font, FT_UInt idx,
     {
         /* No a real cache, but if it always advances by integer pixels (eg translation 0 or same as previous),
          * this allows to render as fast as normal mode. */
-        int retval;
         int want = CACHED_METRICS | want_bitmap | want_pixmap | want_color | want_lcd | want_subpixel;
 
         if (glyph->stored && glyph->index != idx) {
@@ -2644,7 +2641,7 @@ static int Find_GlyphByIndex(TTF_Font *font, FT_UInt idx,
         }
 
         if ((glyph->stored & want) == want) {
-            return 0;
+            return true;
         }
 
         if (want_color || want_pixmap || want_lcd) {
@@ -2654,39 +2651,31 @@ static int Find_GlyphByIndex(TTF_Font *font, FT_UInt idx,
         }
 
         glyph->index = idx;
-        retval = Load_Glyph(font, glyph, want, translation);
-        if (retval == 0) {
-            return 0;
-        } else {
-            return -1;
-        }
-    }
-    else
-    {
-        int retval;
+        return Load_Glyph(font, glyph, want, translation);
+    } else {
         const int want = CACHED_METRICS | want_bitmap | want_pixmap | want_color | want_lcd;
 
         /* Faster check as it gets inlined */
         if (want_pixmap) {
             if ((glyph->stored & CACHED_PIXMAP) && glyph->index == idx) {
-                return 0;
+                return true;
             }
         } else if (want_bitmap) {
             if ((glyph->stored & CACHED_BITMAP) && glyph->index == idx) {
-                return 0;
+                return true;
             }
         } else if (want_color) {
             if ((glyph->stored & CACHED_COLOR) && glyph->index == idx) {
-                return 0;
+                return true;
             }
         } else if (want_lcd) {
             if ((glyph->stored & CACHED_LCD) && glyph->index == idx) {
-                return 0;
+                return true;
             }
         } else {
             /* Get metrics */
             if (glyph->stored && glyph->index == idx) {
-                return 0;
+                return true;
             }
         }
 
@@ -2703,12 +2692,7 @@ static int Find_GlyphByIndex(TTF_Font *font, FT_UInt idx,
         }
 
         glyph->index = idx;
-        retval = Load_Glyph(font, glyph, want, 0);
-        if (retval == 0) {
-            return 0;
-        } else {
-            return -1;
-        }
+        return Load_Glyph(font, glyph, want, 0);
     }
 }
 
@@ -2730,7 +2714,7 @@ static FT_UInt get_char_index(TTF_Font *font, Uint32 ch)
 }
 
 
-static int Find_GlyphMetrics(TTF_Font *font, Uint32 ch, c_glyph **out_glyph)
+static bool Find_GlyphMetrics(TTF_Font *font, Uint32 ch, c_glyph **out_glyph)
 {
     FT_UInt idx = get_char_index(font, ch);
     return Find_GlyphByIndex(font, idx, 0, 0, 0, 0, 0, 0, out_glyph, NULL);
@@ -2850,7 +2834,7 @@ bool TTF_GlyphMetrics(TTF_Font *font, Uint32 ch, int *minx, int *maxx, int *miny
 
     TTF_CHECK_FONT(font, false);
 
-    if (Find_GlyphMetrics(font, ch, &glyph) < 0) {
+    if (!Find_GlyphMetrics(font, ch, &glyph)) {
         return false;
     }
 
@@ -3045,7 +3029,7 @@ static bool TTF_Size_Internal(TTF_Font *font, const char *text, size_t length, i
             continue;
         }
 #endif
-        if (Find_GlyphByIndex(font, idx, 0, 0, 0, 0, 0, 0, &glyph, NULL) < 0) {
+        if (!Find_GlyphByIndex(font, idx, 0, 0, 0, 0, 0, 0, &glyph, NULL)) {
             goto failure;
         }
 
@@ -3855,36 +3839,43 @@ int TTF_WasInit(void)
     return SDL_GetAtomicInt(&TTF_state.refcount);
 }
 
-int TTF_GetFontKerningSizeGlyphs(TTF_Font *font, Uint32 previous_ch, Uint32 ch)
+bool TTF_GetGlyphKerning(TTF_Font *font, Uint32 previous_ch, Uint32 ch, int *kerning)
 {
     FT_Error error;
     c_glyph *prev_glyph, *glyph;
     FT_Vector delta;
 
-    TTF_CHECK_FONT(font, -1);
+    if (kerning) {
+        *kerning = 0;
+    }
+
+    TTF_CHECK_FONT(font, false);
 
     if (ch == UNICODE_BOM_NATIVE || ch == UNICODE_BOM_SWAPPED) {
-        return 0;
+        return true;
     }
 
     if (previous_ch == UNICODE_BOM_NATIVE || previous_ch == UNICODE_BOM_SWAPPED) {
-        return 0;
+        return true;
     }
 
-    if (Find_GlyphMetrics(font, ch, &glyph) < 0) {
-        return -1;
+    if (!Find_GlyphMetrics(font, ch, &glyph)) {
+        return false;
     }
 
-    if (Find_GlyphMetrics(font, previous_ch, &prev_glyph) < 0) {
-        return -1;
+    if (!Find_GlyphMetrics(font, previous_ch, &prev_glyph)) {
+        return false;
     }
 
     error = FT_Get_Kerning(font->face, prev_glyph->index, glyph->index, FT_KERNING_DEFAULT, &delta);
     if (error) {
-        TTF_SetFTError("Couldn't get glyph kerning", error);
-        return -1;
+        return TTF_SetFTError("Couldn't get glyph kerning", error);
     }
-    return (int)(delta.x >> 6);
+
+    if (kerning) {
+        *kerning = (int)(delta.x >> 6);
+    }
+    return true;
 }
 
 bool TTF_IsFontScalable(const TTF_Font *font)
diff --git a/src/SDL_ttf.sym b/src/SDL_ttf.sym
index 85750db6..06e57b9e 100644
--- a/src/SDL_ttf.sym
+++ b/src/SDL_ttf.sym
@@ -11,12 +11,12 @@ SDL3_ttf_0.0.0 {
     TTF_FontLineSkip;
     TTF_GetFontHinting;
     TTF_GetFontKerning;
-    TTF_GetFontKerningSizeGlyphs;
     TTF_GetFontOutline;
     TTF_GetFontSDF;
     TTF_GetFontStyle;
     TTF_GetFontWrappedAlign;
     TTF_GetFreeTypeVersion;
+    TTF_GetGlyphKerning;
     TTF_GetHarfBuzzVersion;
     TTF_GlyphIsProvided;
     TTF_GlyphMetrics;