SDL_ttf: Use global direction and script if per-font values were not set

From 2c14d7cf46128a3c8c8d0ce8216739eea4a7e8c6 Mon Sep 17 00:00:00 2001
From: Simon McVittie <[EMAIL REDACTED]>
Date: Thu, 26 May 2022 17:31:09 +0100
Subject: [PATCH] Use global direction and script if per-font values were not
 set

This fixes a regression for the py-sdl2 test suite, which exercises
the (now-deprecated) TTF_SetDirection() and TTF_SetScript(), and
expects setting a new global value to have an effect on pre-existing
font objects.

Resolves: https://github.com/libsdl-org/SDL_ttf/issues/221
Signed-off-by: Simon McVittie <smcv@collabora.com>
---
 SDL_ttf.c | 35 ++++++++++++++++++++++++++++-------
 SDL_ttf.h |  5 ++++-
 2 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/SDL_ttf.c b/SDL_ttf.c
index 8a4bb3d..f770bef 100644
--- a/SDL_ttf.c
+++ b/SDL_ttf.c
@@ -290,7 +290,9 @@ struct _TTF_Font {
     int render_subpixel;
 #if TTF_USE_HARFBUZZ
     hb_font_t *hb_font;
+    /* If HB_SCRIPT_INVALID, use global default script */
     hb_script_t hb_script;
+    /* If HB_DIRECTION_INVALID, use global default direction */
     hb_direction_t hb_direction;
 #endif
     int render_sdf;
@@ -1002,10 +1004,15 @@ static void Draw_Line(TTF_Font *font, const SDL_Surface *textbuf, int column, in
     int tmp    = row + line_thickness - textbuf->h;
     int x_offset = column * textbuf->format->BytesPerPixel;
     Uint8 *dst = (Uint8 *)textbuf->pixels + row * textbuf->pitch + x_offset;
-
 #if TTF_USE_HARFBUZZ
+    hb_direction_t hb_direction = font->hb_direction;
+
+    if (hb_direction == HB_DIRECTION_INVALID) {
+        hb_direction = g_hb_direction;
+    }
+
     /* No Underline/Strikethrough style if direction is vertical */
-    if (font->hb_direction == HB_DIRECTION_TTB || font->hb_direction == HB_DIRECTION_BTT) {
+    if (hb_direction == HB_DIRECTION_TTB || hb_direction == HB_DIRECTION_BTT) {
         return;
     }
 #endif
@@ -1873,9 +1880,9 @@ TTF_Font* TTF_OpenFontIndexDPIRW(SDL_RWops *src, int freesrc, int ptsize, long i
      * you will get mismatching advances and raster. */
     hb_ft_font_set_load_flags(font->hb_font, FT_LOAD_DEFAULT | font->ft_load_target);
 
-    /* Default value script / direction */
-    font->hb_script = g_hb_script;
-    font->hb_direction = g_hb_direction;
+    /* By default the script / direction are inherited from global variables */
+    font->hb_script = HB_SCRIPT_INVALID;
+    font->hb_direction = HB_DIRECTION_INVALID;
 #endif
 
     if (TTF_SetFontSizeDPI(font, ptsize, hdpi, vdpi) < 0) {
@@ -3116,6 +3123,8 @@ static int TTF_Size_Internal(TTF_Font *font,
     Uint8 *utf8_alloc = NULL;
     c_glyph *glyph;
 #if TTF_USE_HARFBUZZ
+    hb_direction_t hb_direction;
+    hb_script_t hb_script;
     hb_buffer_t *hb_buffer = NULL;
     unsigned int g;
     unsigned int glyph_count;
@@ -3171,9 +3180,21 @@ static int TTF_Size_Internal(TTF_Font *font,
        goto failure;
     }
 
+
+    hb_direction = font->hb_direction;
+    hb_script = font->hb_script;
+
+    if (hb_script == HB_SCRIPT_INVALID) {
+        hb_script = g_hb_script;
+    }
+
+    if (hb_direction == HB_DIRECTION_INVALID) {
+        hb_direction = g_hb_direction;
+    }
+
     /* Set global configuration */
-    hb_buffer_set_direction(hb_buffer, font->hb_direction);
-    hb_buffer_set_script(hb_buffer, font->hb_script);
+    hb_buffer_set_direction(hb_buffer, hb_direction);
+    hb_buffer_set_script(hb_buffer, hb_script);
 
     /* Layout the text */
     hb_buffer_add_utf8(hb_buffer, text, -1, 0, -1);
diff --git a/SDL_ttf.h b/SDL_ttf.h
index 1a4d80b..044cd08 100644
--- a/SDL_ttf.h
+++ b/SDL_ttf.h
@@ -439,7 +439,10 @@ typedef enum
 extern DECLSPEC int SDLCALL TTF_SetDirection(int direction); /* hb_direction_t */
 extern DECLSPEC int SDLCALL TTF_SetScript(int script); /* hb_script_t */
 
-/* Set direction and script per font.
+/* Set direction and script per font, overriding the global direction
+   and script set with the deprecated TTF_SetDirection() and
+   TTF_SetScript().
+
    'script' is null terminated string of exactly 4 characters.
    These functions return 0, or -1 if SDL_ttf is not compiled with HarfBuzz or invalid parameter
 */