SDL_ttf: Simplified the SDL_ttf API and added support for substrings

From c96f8fb1d9d7ad6c5ad69ecfbfd385d46e88dfbd Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 26 Sep 2024 11:28:41 -0700
Subject: [PATCH] Simplified the SDL_ttf API and added support for substrings

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.

Fixes https://github.com/libsdl-org/SDL_ttf/issues/134
Fixes https://github.com/libsdl-org/SDL_ttf/issues/230
Fixes https://github.com/libsdl-org/SDL_ttf/issues/281
Fixes https://github.com/libsdl-org/SDL_ttf/issues/371
---
 VisualC/glfont/glfont.vcxproj     |   10 +-
 VisualC/showfont/showfont.vcxproj |   10 +-
 build-scripts/SDL_migration.cocci |   90 +++
 build-scripts/rename_api.py       |  158 ++++
 build-scripts/rename_symbols.py   |  130 +++
 docs/README-migration.md          |   69 ++
 examples/glfont.c                 |   42 +-
 examples/showfont.c               |  120 +--
 examples/testapp.c                |   34 +-
 include/SDL3_ttf/SDL_ttf.h        | 1244 ++++-------------------------
 src/SDL_ttf.c                     |  793 ++++--------------
 src/SDL_ttf.sym                   |   30 +-
 12 files changed, 839 insertions(+), 1891 deletions(-)
 create mode 100644 build-scripts/SDL_migration.cocci
 create mode 100755 build-scripts/rename_api.py
 create mode 100755 build-scripts/rename_symbols.py
 create mode 100644 docs/README-migration.md

diff --git a/VisualC/glfont/glfont.vcxproj b/VisualC/glfont/glfont.vcxproj
index d07993d4..fb982bb5 100644
--- a/VisualC/glfont/glfont.vcxproj
+++ b/VisualC/glfont/glfont.vcxproj
@@ -84,19 +84,19 @@
     <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <IncludePath>$(SolutionDir)..\..\SDL\include;$(IncludePath)</IncludePath>
+    <IncludePath>$(SolutionDir)..\..\SDL\include;$(SolutionDir)..\include;$(IncludePath)</IncludePath>
     <LibraryPath>$(SolutionDir)..\..\SDL\VisualC\$(PlatformName)\$(Configuration);$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <IncludePath>$(SolutionDir)..\..\SDL\include;$(IncludePath)</IncludePath>
+    <IncludePath>$(SolutionDir)..\..\SDL\include;$(SolutionDir)..\include;$(IncludePath)</IncludePath>
     <LibraryPath>$(SolutionDir)..\..\SDL\VisualC\$(PlatformName)\$(Configuration);$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <IncludePath>$(SolutionDir)..\..\SDL\include;$(IncludePath)</IncludePath>
+    <IncludePath>$(SolutionDir)..\..\SDL\include;$(SolutionDir)..\include;$(IncludePath)</IncludePath>
     <LibraryPath>$(SolutionDir)..\..\SDL\VisualC\$(PlatformName)\$(Configuration);$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <IncludePath>$(SolutionDir)..\..\SDL\include;$(IncludePath)</IncludePath>
+    <IncludePath>$(SolutionDir)..\..\SDL\include;$(SolutionDir)..\include;$(IncludePath)</IncludePath>
     <LibraryPath>$(SolutionDir)..\..\SDL\VisualC\$(PlatformName)\$(Configuration);$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -244,4 +244,4 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
+</Project>
\ No newline at end of file
diff --git a/VisualC/showfont/showfont.vcxproj b/VisualC/showfont/showfont.vcxproj
index 60e7e2b6..fbb7e186 100644
--- a/VisualC/showfont/showfont.vcxproj
+++ b/VisualC/showfont/showfont.vcxproj
@@ -84,19 +84,19 @@
     <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|x64'" />
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
-    <IncludePath>$(SolutionDir)..\..\SDL\include;$(IncludePath)</IncludePath>
+    <IncludePath>$(SolutionDir)..\..\SDL\include;$(SolutionDir)..\include;$(IncludePath)</IncludePath>
     <LibraryPath>$(SolutionDir)..\..\SDL\VisualC\$(PlatformName)\$(Configuration);$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
-    <IncludePath>$(SolutionDir)..\..\SDL\include;$(IncludePath)</IncludePath>
+    <IncludePath>$(SolutionDir)..\..\SDL\include;$(SolutionDir)..\include;$(IncludePath)</IncludePath>
     <LibraryPath>$(SolutionDir)..\..\SDL\VisualC\$(PlatformName)\$(Configuration);$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
-    <IncludePath>$(SolutionDir)..\..\SDL\include;$(IncludePath)</IncludePath>
+    <IncludePath>$(SolutionDir)..\..\SDL\include;$(SolutionDir)..\include;$(IncludePath)</IncludePath>
     <LibraryPath>$(SolutionDir)..\..\SDL\VisualC\$(PlatformName)\$(Configuration);$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
-    <IncludePath>$(SolutionDir)..\..\SDL\include;$(IncludePath)</IncludePath>
+    <IncludePath>$(SolutionDir)..\..\SDL\include;$(SolutionDir)..\include;$(IncludePath)</IncludePath>
     <LibraryPath>$(SolutionDir)..\..\SDL\VisualC\$(PlatformName)\$(Configuration);$(LibraryPath)</LibraryPath>
   </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@@ -244,4 +244,4 @@
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Label="ExtensionTargets">
   </ImportGroup>
-</Project>
+</Project>
\ No newline at end of file
diff --git a/build-scripts/SDL_migration.cocci b/build-scripts/SDL_migration.cocci
new file mode 100644
index 00000000..3d3e066b
--- /dev/null
+++ b/build-scripts/SDL_migration.cocci
@@ -0,0 +1,90 @@
+@@
+@@
+- TTF_GlyphIsProvided32
++ TTF_GlyphIsProvided
+  (...)
+@@
+@@
+- TTF_GlyphMetrics32
++ TTF_GlyphMetrics
+  (...)
+@@
+@@
+- TTF_SizeUTF8
++ TTF_SizeText
+  (...)
+@@
+@@
+- TTF_MeasureUTF8
++ TTF_MeasureText
+  (...)
+@@
+@@
+- TTF_RenderUTF8_Solid
++ SDL_RenderText_Solid
+  (...)
+@@
+@@
+- TTF_RenderUTF8_Solid_Wrapped
++ TTF_RenderText_Solid_Wrapped
+  (...)
+@@
+@@
+- TTF_RenderGlyph32_Solid
++ TTF_RenderGlyph_Solid
+  (...)
+@@
+@@
+- TTF_RenderGlyph32_Solid
++ TTF_RenderGlyph_Solid
+  (...)
+@@
+@@
+- TTF_RenderUTF8_Shaded
++ TTF_RenderText_Shaded
+  (...)
+@@
+@@
+- TTF_RenderUTF8_Shaded_Wrapped
++ TTF_RenderText_Shaded_Wrapped
+  (...)
+@@
+@@
+- TTF_RenderGlyph32_Shaded
++ TTF_RenderGlyph_Shaded
+  (...)
+@@
+@@
+- TTF_RenderUTF8_Blended
++ TTF_RenderText_Blended
+  (...)
+@@
+@@
+- TTF_RenderUTF8_Blended_Wrapped
++ TTF_RenderText_Blended_Wrapped
+  (...)
+@@
+@@
+- TTF_RenderGlyph32_Blended
++ TTF_RenderGlyph_Blended
+  (...)
+@@
+@@
+- TTF_RenderUTF8_LCD
++ TTF_RenderText_LCD
+  (...)
+@@
+@@
+- TTF_RenderUTF8_LCD_Wrapped
++ TTF_RenderText_LCD_Wrapped
+  (...)
+@@
+@@
+- TTF_RenderGlyph32_LCD
++ TTF_RenderGlyph_LCD
+  (...)
+@@
+@@
+- TTF_GetFontKerningSizeGlyphs32
++ TTF_GetFontKerningSizeGlyphs
+  (...)
diff --git a/build-scripts/rename_api.py b/build-scripts/rename_api.py
new file mode 100755
index 00000000..9410b215
--- /dev/null
+++ b/build-scripts/rename_api.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python3
+#
+# This script renames symbols in the API, updating SDL_oldnames.h and
+# adding documentation for the change.
+
+import argparse
+import os
+import pathlib
+import pprint
+import re
+import sys
+from rename_symbols import create_regex_from_replacements, replace_symbols_in_path
+
+SDL_ROOT = pathlib.Path(__file__).resolve().parents[1]
+
+SDL_INCLUDE_DIR = SDL_ROOT / "include/SDL3_ttf"
+SDL_BUILD_SCRIPTS = SDL_ROOT / "build-scripts"
+
+
+def main():
+    if len(args.args) == 0 or (len(args.args) % 2) != 0:
+        print("Usage: %s [-h] [--skip-header-check] {enum,function,hint,structure,symbol} [old new ...]" % sys.argv[0])
+        exit(1)
+
+    # Check whether we can still modify the ABI
+    header_text = pathlib.Path( SDL_INCLUDE_DIR / "SDL_ttf.h" ).read_text()
+    if not re.search(r"SDL_TTF_MINOR_VERSION\s+[01]\s", header_text):
+        raise Exception("ABI is frozen, symbols cannot be renamed")
+
+    # Replace the symbols in source code
+    replacements = {}
+    i = 0
+    while i < len(args.args):
+        oldname = args.args[i + 0]
+        newname = args.args[i + 1]
+
+        if not args.skip_header_check and not re.search((r"\b%s\b" % oldname), header_text):
+            raise Exception("Couldn't find %s in %s" % (oldname, header))
+
+        replacements[ oldname ] = newname
+        i += 2
+
+    regex = create_regex_from_replacements(replacements)
+    for dir in ["src", "examples", "include", "cmake/test"]:
+        replace_symbols_in_path(SDL_ROOT / dir, regex, replacements)
+
+    # Replace the symbols in documentation
+    i = 0
+    while i < len(args.args):
+        oldname = args.args[i + 0]
+        newname = args.args[i + 1]
+
+        add_symbol_to_migration(args.type, oldname, newname)
+        add_symbol_to_coccinelle(args.type, oldname, newname)
+        i += 2
+
+
+def add_line(lines, i, section):
+    lines.insert(i, section)
+    i += 1
+    return i
+
+
+def add_content(lines, i, content, add_trailing_line):
+    if lines[i - 1] == "":
+        lines[i - 1] = content
+    else:
+        i = add_line(lines, i, content)
+
+    if add_trailing_line:
+        i = add_line(lines, i, "")
+    return i
+
+
+def add_symbol_to_coccinelle(symbol_type, oldname, newname):
+    file = open(SDL_BUILD_SCRIPTS / "SDL_migration.cocci", "a")
+    # Append-adds at last
+
+    if symbol_type == "function":
+        file.write("@@\n")
+        file.write("@@\n")
+        file.write("- %s\n" % oldname)
+        file.write("+ %s\n" % newname)
+        file.write("  (...)\n")
+
+    if symbol_type == "symbol":
+        file.write("@@\n")
+        file.write("@@\n")
+        file.write("- %s\n" % oldname)
+        file.write("+ %s\n" % newname)
+
+    # double check ?
+    if symbol_type == "hint":
+        file.write("@@\n")
+        file.write("@@\n")
+        file.write("- %s\n" % oldname)
+        file.write("+ %s\n" % newname)
+
+    if symbol_type == "enum" or symbol_type == "structure":
+        file.write("@@\n")
+        file.write("typedef %s, %s;\n" % (oldname, newname))
+        file.write("@@\n")
+        file.write("- %s\n" % oldname)
+        file.write("+ %s\n" % newname)
+
+    file.close()
+
+
+def add_symbol_to_migration(symbol_type, oldname, newname):
+    file = (SDL_ROOT / "docs/README-migration.md")
+    lines = file.read_text().splitlines()
+    note = ("The following %ss have been renamed:" % symbol_type)
+    note_added = False
+    if symbol_type == "function":
+        content = ("* %s() => %s()" % (oldname, newname))
+    else:
+        content = ("* %s => %s" % (oldname, newname))
+    content_added = False
+    mode = 0
+    i = 0
+    while i < len(lines):
+        line = lines[i]
+        if not note_added:
+            if note == line:
+                note_added = True
+        elif note_added and not content_added:
+            if content == line:
+                content_added = True
+            elif line == "" or content < line:
+                i = add_line(lines, i, content)
+                content_added = True
+        i += 1
+
+    if not note_added:
+        i = add_line(lines, i, note)
+
+    if not content_added:
+        i = add_content(lines, i, content, True)
+
+    file.write_text("\n".join(lines) + "\n")
+
+
+if __name__ == "__main__":
+
+    parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
+    parser.add_argument("--skip-header-check", action="store_true")
+    parser.add_argument("type", choices=["enum", "function", "hint", "structure", "symbol"])
+    parser.add_argument("args", nargs="*")
+    args = parser.parse_args()
+
+    try:
+        main()
+    except Exception as e:
+        print(e)
+        exit(-1)
+
+    exit(0)
+
diff --git a/build-scripts/rename_symbols.py b/build-scripts/rename_symbols.py
new file mode 100755
index 00000000..33a92dde
--- /dev/null
+++ b/build-scripts/rename_symbols.py
@@ -0,0 +1,130 @@
+#!/usr/bin/env python3
+#
+# This script renames symbols in the specified paths
+
+import argparse
+import os
+import pathlib
+import re
+import sys
+
+
+SDL_ROOT = pathlib.Path(__file__).resolve().parents[1]
+
+SDL_INCLUDE_DIR = SDL_ROOT / "include/SDL3"
+
+
+def main():
+    if args.all_symbols:
+        if len(args.args) < 1:
+            print("Usage: %s --all-symbols files_or_directories ..." % sys.argv[0])
+            exit(1)
+
+        replacements = get_all_replacements()
+        entries = args.args
+
+    else:
+        if len(args.args) < 3:
+            print("Usage: %s [--substring] oldname newname files_or_directories ..." % sys.argv[0])
+            exit(1)
+
+        replacements = { args.args[0]: args.args[1] }
+        entries = args.args[2:]
+
+    if args.substring:
+        regex = create_substring_regex_from_replacements(replacements)
+    else:
+        regex = create_regex_from_replacements(replacements)
+
+    for entry in entries:
+        path = pathlib.Path(entry)
+        if not path.exists():
+            print("%s doesn't exist, skipping" % entry)
+            continue
+
+        replace_symbols_in_path(path, regex, replacements)
+
+
+def get_all_replacements():
+    replacements = {}
+    file = (SDL_INCLUDE_DIR / "SDL_oldnames.h")
+    mode = 0
+    for line in file.read_text().splitlines():
+        if line == "#ifdef SDL_ENABLE_OLD_NAMES":
+            if mode == 0:
+                mode = 1
+            else:
+                raise Exception("get_all_replacements(): expected mode 0")
+        elif line == "#elif !defined(SDL_DISABLE_OLD_NAMES)":
+            if mode == 1:
+                mode = 2
+            else:
+                raise Exception("get_all_replacements(): expected mode 1")
+        elif line == "#endif /* SDL_ENABLE_OLD_NAMES */":
+            if mode == 2:
+                mode = 3
+            else:
+                raise Exception("add_symbol_to_oldnames(): expected mode 2")
+        elif mode == 1 and line.startswith("#define "):
+            words = line.split()
+            replacements[words[1]] = words[2]
+            # In case things are accidentally renamed to the "X_renamed_Y" symbol
+            #replacements[words[1] + "_renamed_" + words[2]] = words[2]
+
+    return replacements
+
+
+def create_regex_from_replacements(replacements):
+    return re.compile(r"\b(%s)\b" % "|".join(map(re.escape, replacements.keys())))
+
+
+def create_substring_regex_from_replacements(replacements):
+    return re.compile(r"(%s)" % "|".join(map(re.escape, replacements.keys())))
+
+
+def replace_symbols_in_file(file, regex, replacements):
+    try:
+        with file.open("r", encoding="UTF-8", newline="") as rfp:
+            original = rfp.read()
+            contents = regex.sub(lambda mo: replacements[mo.string[mo.start():mo.end()]], original)
+            if contents != original:
+                with file.open("w", encoding="UTF-8", newline="") as wfp:
+                    wfp.write(contents)
+    except UnicodeDecodeError:
+        print("%s is not text, skipping" % file)
+    except Exception as err:
+        print("%s" % err)
+
+
+def replace_symbols_in_dir(path, regex, replacements):
+    for entry in path.glob("*"):
+        if entry.is_dir():
+            replace_symbols_in_dir(entry, regex, replacements)
+        else:
+            print("Processing %s" % entry)
+            replace_symbols_in_file(entry, regex, replacements)
+
+
+def replace_symbols_in_path(path, regex, replacements):
+        if path.is_dir():
+            replace_symbols_in_dir(path, regex, replacements)
+        else:
+            replace_symbols_in_file(path, regex, replacements)
+
+
+if __name__ == "__main__":
+
+    parser = argparse.ArgumentParser(fromfile_prefix_chars='@')
+    parser.add_argument("--all-symbols", action="store_true")
+    parser.add_argument("--substring", action="store_true")
+    parser.add_argument("args", nargs="*")
+    args = parser.parse_args()
+
+    try:
+        main()
+    except Exception as e:
+        print(e)
+        exit(-1)
+
+    exit(0)
+
diff --git a/docs/README-migration.md b/docs/README-migration.md
new file mode 100644
index 00000000..2e75a466
--- /dev/null
+++ b/docs/README-migration.md
@@ -0,0 +1,69 @@
+
+# Migrating to SDL_ttf 3.0
+
+This guide provides useful information for migrating applications from SDL_ttf 2.0 to SDL_ttf 3.0.
+
+Functions that previously returned a negative error code now return bool.
+
+Code that used to look like this:
+```c
+    if (TTF_Function() < 0 || TTF_Function() == -1) {
+        /* Failure... */
+    }
+```
+or
+```c
+    if (TTF_Function() == 0) {
+        /* Success... */
+    }
+```
+or
+```c
+    if (!TTF_Function()) {
+        /* Success... */
+    }
+```
+should be changed to:
+```c
+    if (TTF_Function()) {
+        /* Success... */
+    } else {
+        /* Failure... */
+    }
+```
+
+Several functions have been renamed. We have provided a handy semantic patch to migrate more easily to SDL3: [SDL_migration.cocci](https://github.com/libsdl-org/SDL_ttf/blob/main/build-scripts/SDL_migration.cocci)
+
+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()
+* TTF_RenderGlyph32_Blended() => TTF_RenderGlyph_Blended()
+* TTF_RenderGlyph32_LCD() => TTF_RenderGlyph_LCD()
+* TTF_RenderGlyph32_Shaded() => TTF_RenderGlyph_Shaded()
+* TTF_RenderGlyph32_Solid() => TTF_RenderGlyph_Solid()
+* TTF_RenderUTF8_Blended() => TTF_RenderText_Blended()
+* TTF_RenderUTF8_Blended_Wrapped() => TTF_RenderText_Blended_Wrapped()
+* TTF_RenderUTF8_LCD() => TTF_RenderText_LCD()
+* TTF_RenderUTF8_LCD_Wrapped() => TTF_RenderText_LCD_Wrapped()
+* TTF_RenderUTF8_Shaded() => TTF_RenderText_Shaded()
+* TTF_RenderUTF8_Shaded_Wrapped() => TTF_RenderText_Shaded_Wrapped()
+* TTF_RenderUTF8_Solid() => SDL_RenderText_Solid()
+* TTF_RenderUTF8_Solid_Wrapped() => TTF_RenderText_Solid_Wrapped()
+* TTF_SizeUTF8() => TTF_SizeText()
+
+The following functions have been removed:
+* TTF_ByteSwappedUNICODE()
+* TTF_MeasureUNICODE()
+* TTF_RenderUNICODE_Blended()
+* TTF_RenderUNICODE_Blended_Wrapped()
+* TTF_RenderUNICODE_LCD()
+* TTF_RenderUNICODE_LCD_Wrapped()
+* TTF_RenderUNICODE_Shaded()
+* TTF_RenderUNICODE_Shaded_Wrapped()
+* TTF_RenderUNICODE_Solid()
+* TTF_RenderUNICODE_Solid_Wrapped()
+* TTF_SizeUNICODE()
diff --git a/examples/glfont.c b/examples/glfont.c
index 4d1aa8eb..20d59c79 100644
--- a/examples/glfont.c
+++ b/examples/glfont.c
@@ -42,7 +42,7 @@
 #define HEIGHT  480
 
 #define TTF_GLFONT_USAGE \
-"Usage: %s [-utf8|-unicode] [-b] [-i] [-u] [-fgcol r,g,b] [-bgcol r,g,b] \
+"Usage: %s [-b] [-i] [-u] [-fgcol r,g,b] [-bgcol r,g,b] \
 <font>.ttf [ptsize] [text]\n"
 
 static void SDL_GL_Enter2DMode(int width, int height)
@@ -198,28 +198,16 @@ int main(int argc, char *argv[])
     SDL_Event event;
     int renderstyle;
     int dump;
-    enum {
-        RENDER_LATIN1,
-        RENDER_UTF8,
-        RENDER_UNICODE
-    } rendertype;
     char *message;
 
     /* Look for special execution mode */
     dump = 0;
     /* Look for special rendering types */
     renderstyle = TTF_STYLE_NORMAL;
-    rendertype = RENDER_LATIN1;
     /* Default is black and white */
     forecol = &black;
     backcol = &white;
     for (i=1; argv[i] && argv[i][0] == '-'; ++i) {
-        if (SDL_strcmp(argv[i], "-utf8") == 0) {
-            rendertype = RENDER_UTF8;
-        } else
-        if (SDL_strcmp(argv[i], "-unicode") == 0) {
-            rendertype = RENDER_UNICODE;
-        } else
         if (SDL_strcmp(argv[i], "-b") == 0) {
             renderstyle |= TTF_STYLE_BOLD;
         } else
@@ -326,33 +314,7 @@ int main(int argc, char *argv[])
     } else {
         message = DEFAULT_TEXT;
     }
-    switch (rendertype) {
-        case RENDER_LATIN1:
-        text = TTF_RenderText_Blended(font, message, *forecol);
-        break;
-
-        case RENDER_UTF8:
-        text = TTF_RenderUTF8_Blended(font, message, *forecol);
-        break;
-
-        case RENDER_UNICODE:
-        {
-            /* This doesn't actually work because you can't pass
-               UNICODE text in via command line, AFAIK, but...
-             */
-            Uint16 unicode_text[BUFSIZ];
-            int index;
-            for (index = 0; (message[0] || message[1]); ++index) {
-                unicode_text[index]  = ((Uint8 *)message)[0];
-                unicode_text[index] <<= 8;
-                unicode_text[index] |= ((Uint8 *)message)[1];
-                message += 2;
-            }
-            text = TTF_RenderUNICODE_Blended(font,
-                    unicode_text, *forecol);
-        }
-        break;
-    }
+    text = TTF_RenderText_Blended(font, message, 0, *forecol);
     if (text == NULL) {
         fprintf(stderr, "Couldn't render text: %s\n", SDL_GetError());
         TTF_CloseFont(font);
diff --git a/examples/showfont.c b/examples/showfont.c
index 65ff5c7b..335c5110 100644
--- a/examples/showfont.c
+++ b/examples/showfont.c
@@ -35,7 +35,7 @@
 #define HEIGHT  480
 
 #define TTF_SHOWFONT_USAGE \
-"Usage: %s [-solid] [-shaded] [-blended] [-wrapped] [-utf8|-unicode] [-b] [-i] [-u] [-s] [-outline size] [-hintlight|-hintmono|-hintnone] [-nokerning] [-wrap] [-fgcol r,g,b,a] [-bgcol r,g,b,a] <font>.ttf [ptsize] [text]\n"
+"Usage: %s [-solid] [-shaded] [-blended] [-wrapped] [-b] [-i] [-u] [-s] [-outline size] [-hintlight|-hintmono|-hintnone] [-nokerning] [-wrap] [-fgcol r,g,b,a] [-bgcol r,g,b,a] <font>.ttf [ptsize] [text]\n"
 
 typedef enum
 {
@@ -91,11 +91,6 @@ int main(int argc, char *argv[])
     int kerning;
     int wrap;
     int dump;
-    enum {
-        RENDER_LATIN1,
-        RENDER_UTF8,
-        RENDER_UNICODE
-    } rendertype;
     char *message, string[128];
 
     /* Look for special execution mode */
@@ -103,7 +98,6 @@ int main(int argc, char *argv[])
     /* Look for special rendering types */
     rendermethod = TextRenderShaded;
     renderstyle = TTF_STYLE_NORMAL;
-    rendertype = RENDER_LATIN1;
     outline = 0;
     hinting = TTF_HINTING_NORMAL;
     kerning = 1;
@@ -120,12 +114,6 @@ int main(int argc, char *argv[])
         if (SDL_strcmp(argv[i], "-blended") == 0) {
             rendermethod = TextRenderBlended;
         } else
-        if (SDL_strcmp(argv[i], "-utf8") == 0) {
-            rendertype = RENDER_UTF8;
-        } else
-        if (SDL_strcmp(argv[i], "-unicode") == 0) {
-            rendertype = RENDER_UNICODE;
-        } else
         if (SDL_strcmp(argv[i], "-b") == 0) {
             renderstyle |= TTF_STYLE_BOLD;
         } else
@@ -252,13 +240,13 @@ int main(int argc, char *argv[])
     SDL_snprintf(string, sizeof(string), "Font file: %s", argv[0]);  /* possible overflow */
     switch (rendermethod) {
     case TextRenderSolid:
-        text = TTF_RenderText_Solid(font, string, *forecol);
+        text = TTF_RenderText_Solid(font, string, 0, *forecol);
         break;
     case TextRenderShaded:
-        text = TTF_RenderText_Shaded(font, string, *forecol, *backcol);
+        text = TTF_RenderText_Shaded(font, string, 0, *forecol, *backcol);
         break;
     case TextRenderBlended:
-        text = TTF_RenderText_Blended(font, string, *forecol);
+        text = TTF_RenderText_Blended(font, string, 0, *forecol);
         break;
     }
     if (text != NULL) {
@@ -276,86 +264,26 @@ int main(int argc, char *argv[])
     } else {
         message = DEFAULT_TEXT;
     }
-    switch (rendertype) {
-        case RENDER_LATIN1:
-            switch (rendermethod) {
-            case TextRenderSolid:
-                if (wrap) {
-                    text = TTF_RenderText_Solid_Wrapped(font, message, *forecol, 0);
-                } else {
-                    text = TTF_RenderText_Solid(font, message, *forecol);
-                }
-                break;
-            case TextRenderShaded:
-                if (wrap) {
-                    text = TTF_RenderText_Shaded_Wrapped(font, message, *forecol, *backcol, 0);
-                } else {
-                    text = TTF_RenderText_Shaded(font, message, *forecol, *backcol);
-                }
-                break;
-            case TextRenderBlended:
-                if (wrap) {
-                    text = TTF_RenderText_Blended_Wrapped(font, message, *forecol, 0);
-                } else {
-                    text = TTF_RenderText_Blended(font, message, *forecol);
-                }
-                break;
-            }
-            break;
-
-        case RENDER_UTF8:
-            switch (rendermethod) {
-            case TextRenderSolid:
-                if (wrap) {
-                    text = TTF_RenderUTF8_Solid_Wrapped(font, message, *forecol, 0);
-                } else {
-                    text = TTF_RenderUTF8_Solid(font, message, *forecol);
-                }
-                break;
-            case TextRenderShaded:
-                if (wrap) {
-                    text = TTF_RenderUTF8_Shaded_Wrapped(font, message, *forecol, *backcol, 0);
-                } else {
-                    text = TTF_RenderUTF8_Shaded(font, message, *forecol, *backcol);
-                }
-                break;
-            case TextRenderBlended:
-                if (wrap) {
-                    text = TTF_RenderUTF8_Blended_Wrapped(font, message, *forecol, 0);
-                } else {
-                    text = TTF_RenderUTF8_Blended(font, message, *forecol);
-                }
-                break;
-            }
-            break;
-
-        case RENDER_UNICODE:
-        {
-            Uint16 *unicode_text = SDL_iconv_utf8_ucs2(message);
-            switch (rendermethod) {
-            case TextRenderSolid:
-                if (wrap) {
-                    text = TTF_RenderUNICODE_Solid_Wrapped(font, unicode_text, *forecol, 0);
-                } else {
-                    text = TTF_RenderUNICODE_Solid(font, unicode_text, *forecol);
-                }
-                break;
-            case TextRenderShaded:
-                if (wrap) {
-                    text = TTF_RenderUNICODE_Shaded_Wrapped(font, unicode_text, *forecol, *backcol, 0);
-                } else {
-                    text = TTF_RenderUNICODE_Shaded(font, unicode_text, *forecol, *backcol);
-                }
-                break;
-            case TextRenderBlended:
-                if (wrap) {
-                    text = TTF_RenderUNICODE_Blended_Wrapped(font, unicode_text, *forecol, 0);
-                } else {
-                    text = TTF_RenderUNICODE_Blended(font, unicode_text, *forecol);
-                }
-                break;
-            }
-            SDL_free(unicode_text);
+    switch (rendermethod) {
+    case TextRenderSolid:
+        if (wrap) {
+            text = TTF_RenderText_Solid_Wrapped(font, message, 0, *forecol, 0);
+        } else {
+            text = TTF_RenderText_Solid(font, message, 0, *forecol);
+        }
+        break;
+    case TextRenderShaded:
+        if (wrap) {
+            text = TTF_RenderText_Shaded_Wrapped(font, message, 0, *forecol, *backcol, 0);
+        } else {
+            text = TTF_RenderText_Shaded(font, message, 0, *forecol, *backcol);
+        }
+        break;
+    case TextRenderBlended:
+        if (wrap) {
+            text = TTF_RenderText_Blended_Wrapped(font, message, 0, *forecol, 0);
+        } else {
+            text = TTF_RenderText_Blended(font, message, 0, *forecol);
         }
         break;
     }
diff --git a/examples/testapp.c b/examples/testapp.c
index 802be532..e88d61d5 100644
--- a/examples/testapp.c
+++ b/examples/testapp.c
@@ -898,7 +898,7 @@ int main(void)
              }
           }
 #endif
-          if (!TTF_SizeUTF8(font, text, &w, &h)) {
+          if (!TTF_SizeText(font, text, &w, &h)) {
              SDL_Log("size failed");
           }
           if (w == 0) {
@@ -920,20 +920,20 @@ int main(void)
                 switch (render_mode)
                 {
                    case 1:
-                      text_surface = TTF_RenderUTF8_Blended(font, text, textcol);
+                      text_surface = TTF_RenderText_Blended(font, text, 0, textcol);
                       break;
                    case 2:
-                      text_surface = TTF_RenderUTF8_Shaded(font, text, textcol, boardcol);
+                      text_surface = TTF_RenderText_Shaded(font, text, 0, textcol, boardcol);
                       break;
                    case 3:
 #if defined(HAVE_LCD)
-                      text_surface = TTF_RenderUTF8_LCD(font, text, textcol, boardcol);
+                      text_surface = TTF_RenderText_LCD(font, text, 0, textcol, boardcol);
 #else
-                      text_surface = TTF_RenderUTF8_Shaded(font, text, textcol, boardcol);
+                      text_surface = TTF_RenderText_Shaded(font, text, 0, textcol, boardcol);
 #endif
                       break;
                    case 0:
-                      text_surface = TTF_RenderUTF8_Solid(font, text, textcol);
+                      text_surface = SDL_RenderText_Solid(font, text, 0, textcol);
                       break;
                 }
 
@@ -948,20 +948,20 @@ int main(void)
                 switch (render_mode)
                 {
                    case 1:
-                      text_surface = TTF_RenderUTF8_Blended(font, text, textcol);
+                      text_surface = TTF_RenderText_Blended(font, text, 0, textcol);
                       break;
                    case 2:
-                      text_surface = TTF_RenderUTF8_Shaded(font, text, textcol, boardcol);
+                      text_surface = TTF_RenderText_Shaded(font, text, 0, textcol, boardcol);
                       break;
                    case 3:
 #if defined(HAVE_LCD)
-                      text_surface = TTF_RenderUTF8_LCD(font, text, textcol, boardcol);
+                      text_surface = TTF_RenderText_LCD(font, text, 0, textcol, boardcol);
 #else
-                      text_surface = TTF_RenderUTF8_Shaded(font, text, textcol, boardcol);
+                      text_surface = TTF_RenderText_Shaded(font, text, 0, textcol, boardcol);
 #endif
                       break;
                    case 0:
-                      text_surface = TTF_RenderUTF8_Solid(font, text, textcol);
+                      text_surface = SDL_RenderText_Solid(font, text, 0, textcol);
                       break;
                 }
 
@@ -988,24 +988,24 @@ int main(void)
                 switch (render_mode)
                 {
                    case 1:
-                      text_surface = TTF_RenderUTF8_Blended_Wrapped(font, text, textcol, wrap_size);
+                      text_surface = TTF_RenderText_Blended_Wrapped(font, text, 0, textcol, wrap_size);
                       break;
                    case 2:
-                      text_surface = TTF_RenderUTF8_Shaded_Wrapped(font, text, textcol, boardcol, wrap_size);
+       

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