SDL_ttf: Fixed sharing an SDL_IOStream with multiple fonts

From 64ed11225a51294a74a40a18325154e75823a5cd Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 26 Sep 2024 21:23:47 -0700
Subject: [PATCH] Fixed sharing an SDL_IOStream with multiple fonts

We'll use an absolute offset from the beginning of the stream instead of the current offset at the time the font is opened. This can be set per-font using TTF_PROP_FONT_IOSTREAM_OFFSET_NUMBER if necessary.

Fixes https://github.com/libsdl-org/SDL_ttf/issues/267
---
 include/SDL3_ttf/SDL_ttf.h |  2 ++
 src/SDL_ttf.c              | 17 +++++++++--------
 2 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/include/SDL3_ttf/SDL_ttf.h b/include/SDL3_ttf/SDL_ttf.h
index cebe9e1c..87c8b835 100644
--- a/include/SDL3_ttf/SDL_ttf.h
+++ b/include/SDL3_ttf/SDL_ttf.h
@@ -198,6 +198,7 @@ extern SDL_DECLSPEC TTF_Font * SDLCALL TTF_OpenFontIO(SDL_IOStream *src, bool cl
  * - `TTF_PROP_FONT_IOSTREAM_POINTER`: an SDL_IOStream containing the font to
  *   be opened. This should not be closed until the font is closed. This is
  *   required if `TTF_PROP_FONT_FILENAME_STRING` isn't set.
+ * - `TTF_PROP_FONT_IOSTREAM_OFFSET_NUMBER`: the offset in the iostream for the beginning of the font, defaults to 0.
  * - `TTF_PROP_FONT_IOSTREAM_AUTOCLOSE_BOOLEAN`: true if closing the font
  *   should also close the associated SDL_IOStream.
  * - `TTF_PROP_FONT_SIZE_NUMBER`: the point size of the font. Some .fon fonts
@@ -227,6 +228,7 @@ extern SDL_DECLSPEC TTF_Font * SDLCALL TTF_OpenFontWithProperties(SDL_Properties
 
 #define TTF_PROP_FONT_FILENAME_STRING               "SDL_ttf.font.filename"
 #define TTF_PROP_FONT_IOSTREAM_POINTER              "SDL_ttf.font.iostream"
+#define TTF_PROP_FONT_IOSTREAM_OFFSET_NUMBER        "SDL_ttf.font.iostream.offset"
 #define TTF_PROP_FONT_IOSTREAM_AUTOCLOSE_BOOLEAN    "SDL_ttf.font.iostream.autoclose"
 #define TTF_PROP_FONT_SIZE_NUMBER                   "SDL_ttf.font.size"
 #define TTF_PROP_FONT_FACE_NUMBER                   "SDL_ttf.font.face"
diff --git a/src/SDL_ttf.c b/src/SDL_ttf.c
index 1e9e9152..8a4551e4 100644
--- a/src/SDL_ttf.c
+++ b/src/SDL_ttf.c
@@ -257,6 +257,7 @@ struct TTF_Font {
 
     /* We are responsible for closing the font stream */
     SDL_IOStream *src;
+    Sint64 src_offset;
     bool closeio;
     FT_Open_Args args;
 
@@ -1754,17 +1755,16 @@ static unsigned long IOread(
     unsigned long count
 )
 {
-    SDL_IOStream *src;
-
-    src = (SDL_IOStream *)stream->descriptor.pointer;
-    SDL_SeekIO(src, offset, SDL_IO_SEEK_SET);
-    return (unsigned long)SDL_ReadIO(src, buffer, count);
+    TTF_Font *font = (TTF_Font *)stream->descriptor.pointer;
+    SDL_SeekIO(font->src, font->src_offset + offset, SDL_IO_SEEK_SET);
+    return (unsigned long)SDL_ReadIO(font->src, buffer, count);
 }
 
 TTF_Font *TTF_OpenFontWithProperties(SDL_PropertiesID props)
 {
     const char *file = SDL_GetStringProperty(props, TTF_PROP_FONT_FILENAME_STRING, NULL);
     SDL_IOStream *src = SDL_GetPointerProperty(props, TTF_PROP_FONT_IOSTREAM_POINTER, NULL);
+    Sint64 src_offset = SDL_GetNumberProperty(props, TTF_PROP_FONT_IOSTREAM_OFFSET_NUMBER, 0);
     bool closeio = SDL_GetBooleanProperty(props, TTF_PROP_FONT_IOSTREAM_AUTOCLOSE_BOOLEAN, false);
     int ptsize = (int)SDL_GetNumberProperty(props, TTF_PROP_FONT_SIZE_NUMBER, 0);
     long index = (long)SDL_GetNumberProperty(props, TTF_PROP_FONT_FACE_NUMBER, 0);
@@ -1821,6 +1821,7 @@ TTF_Font *TTF_OpenFontWithProperties(SDL_PropertiesID props)
     SDL_memset(font, 0, sizeof (*font));
 
     font->src = src;
+    font->src_offset = src_offset;
     font->closeio = closeio;
 
     stream = (FT_Stream)SDL_malloc(sizeof (*stream));
@@ -1832,9 +1833,9 @@ TTF_Font *TTF_OpenFontWithProperties(SDL_PropertiesID props)
     SDL_memset(stream, 0, sizeof (*stream));
 
     stream->read = IOread;
-    stream->descriptor.pointer = src;
-    stream->pos = (unsigned long)position;
-    stream->size = (unsigned long)(SDL_GetIOSize(src) - position);
+    stream->descriptor.pointer = font;
+    stream->pos = 0;
+    stream->size = (unsigned long)(SDL_GetIOSize(src) - src_offset);
 
     font->args.flags = FT_OPEN_STREAM;
     font->args.stream = stream;