From 42741426ee38a4add52eda258523b54af5de3373 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 19 Oct 2024 19:48:58 -0700 Subject: [PATCH 1/2] Added TTF_SetTextWrapWhitespaceVisible() and TTF_TextWrapWhitespaceVisible() When you're editing text, you want whitespace to be visible. When you're rendering it, you normally want it to be eliminated around line breaks. This is the default, to match previous rendering behavior. Fixes https://github.com/libsdl-org/SDL_ttf/issues/414 --- examples/editbox.c | 5 +++- include/SDL3_ttf/SDL_ttf.h | 30 ++++++++++++++++++++ src/SDL_ttf.c | 58 +++++++++++++++++++++++++++++++++----- src/SDL_ttf.sym | 2 ++ 4 files changed, 87 insertions(+), 8 deletions(-) diff --git a/examples/editbox.c b/examples/editbox.c index b2028178..8cd239e9 100644 --- a/examples/editbox.c +++ b/examples/editbox.c @@ -218,7 +218,7 @@ static void SaveCandidates(EditBox *edit, const SDL_Event *event) } *dst = '\0'; - edit->candidates = TTF_CreateText_Wrapped(TTF_GetTextEngine(edit->text), edit->font, candidate_text, 0, 0); + edit->candidates = TTF_CreateText(TTF_GetTextEngine(edit->text), edit->font, candidate_text, 0); SDL_free(candidate_text); if (edit->candidates) { SDL_copyp(&edit->candidates->color, &edit->text->color); @@ -342,6 +342,9 @@ EditBox *EditBox_Create(SDL_Window *window, SDL_Renderer *renderer, TTF_TextEngi edit->highlight1 = -1; edit->highlight2 = -1; + /* Show the whitespace when wrapping, so it can be edited */ + TTF_SetTextWrapWhitespaceVisible(edit->text, true); + #ifdef TEST_SURFACE_ENGINE /* Grab the window surface if we want to test the surface text engine. * This isn't strictly necessary, we can still use the renderer if it's diff --git a/include/SDL3_ttf/SDL_ttf.h b/include/SDL3_ttf/SDL_ttf.h index 1ccadbcc..f78f22fb 100644 --- a/include/SDL3_ttf/SDL_ttf.h +++ b/include/SDL3_ttf/SDL_ttf.h @@ -1737,6 +1737,36 @@ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapping(TTF_Text *text, int wrapLen */ extern SDL_DECLSPEC bool SDLCALL TTF_GetTextWrapping(TTF_Text *text, int *wrapLength); +/** + * 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 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. + * + * \threadsafety This function should be called on the thread that created the + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapWhitespaceVisible(TTF_Text *text, bool visible); + +/** + * Return whether whitespace is shown when wrapping a text object. + * + * \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. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_TextWrapWhitespaceVisible(TTF_Text *text); + /** * Get the size of a text object. * diff --git a/src/SDL_ttf.c b/src/SDL_ttf.c index 4add63b2..ec342eec 100644 --- a/src/SDL_ttf.c +++ b/src/SDL_ttf.c @@ -3346,7 +3346,7 @@ static bool CharacterIsNewLine(Uint32 c) return false; } -static bool GetWrappedLines(TTF_Font *font, const char *text, size_t length, int xoffset, int wrapLength, TTF_Line **lines, int *num_lines, int *w, int *h) +static bool GetWrappedLines(TTF_Font *font, const char *text, size_t length, int xoffset, int wrapLength, bool trim_whitespace, TTF_Line **lines, int *num_lines, int *w, int *h) { int width, height; int i, numLines = 0, rowHeight; @@ -3400,6 +3400,19 @@ static bool GetWrappedLines(TTF_Font *font, const char *text, size_t length, int strLines = new_lines; } + if (trim_whitespace && spot > text && spot[-1] != '\n') { + const char *next_spot = spot; + size_t next_left = left; + for (;;) { + Uint32 c = SDL_StepUTF8(&next_spot, &next_left); + if (c == 0 || (c != ' ' && c != '\t')) { + break; + } + spot = next_spot; + left = next_left; + } + } + if (numLines > 0) { strLines[numLines - 1].length = spot - strLines[numLines - 1].text; } @@ -3417,6 +3430,9 @@ static bool GetWrappedLines(TTF_Font *font, const char *text, size_t length, int } if (wrapLength != 0) { + // The first line can be empty if we have a text position that's + // at the edge of the wrap length, but subsequent lines should have + // at least one character per line. if (max_count == 0 && numLines > 1) { max_count = 1; } @@ -3425,7 +3441,7 @@ static bool GetWrappedLines(TTF_Font *font, const char *text, size_t length, int if (max_count > 0) { while (left > 0) { int is_delim; - Uint32 c = SDL_StepUTF8((const char **)&spot, &left); + Uint32 c = SDL_StepUTF8(&spot, &left); if (c == UNICODE_BOM_NATIVE || c == UNICODE_BOM_SWAPPED) { continue; @@ -3464,18 +3480,24 @@ static bool GetWrappedLines(TTF_Font *font, const char *text, size_t length, int } while (left > 0); - // Trim whitespace from the wrapped lines and newlines from unwrapped lines for (i = 0; i < numLines; ++i) { TTF_Line *line = &strLines[i]; if (line->length == 0) { continue; } + + // The line doesn't include any delimiter that caused it to be wrapped. if (CharacterIsNewLine(line->text[line->length - 1])) { --line->length; if (line->text[line->length - 1] == '\r') { --line->length; } - } else if (i < (numLines - 1)) { + } else if (i < (numLines - 1) && + CharacterIsDelimiter(line->text[line->length - 1])) { + --line->length; + } + + if (trim_whitespace) { while (line->length > 0 && CharacterIsDelimiter(line->text[line->length - 1])) { --line->length; @@ -3536,7 +3558,7 @@ static bool GetWrappedLines(TTF_Font *font, const char *text, size_t length, int bool TTF_GetStringSizeWrapped(TTF_Font *font, const char *text, size_t length, int wrapLength, int *w, int *h) { - return GetWrappedLines(font, text, length, 0, wrapLength, NULL, NULL, w, h); + return GetWrappedLines(font, text, length, 0, wrapLength, true, NULL, NULL, w, h); } static SDL_Surface* TTF_Render_Wrapped_Internal(TTF_Font *font, const char *text, size_t length, SDL_Color fg, SDL_Color bg, int wrapLength, const render_mode_t render_mode) @@ -3547,7 +3569,7 @@ static SDL_Surface* TTF_Render_Wrapped_Internal(TTF_Font *font, const char *text int i, numLines = 0; TTF_Line *strLines = NULL; - if (!GetWrappedLines(font, text, length, 0, wrapLength, &strLines, &numLines, &width, &height)) { + if (!GetWrappedLines(font, text, length, 0, wrapLength, true, &strLines, &numLines, &width, &height)) { return NULL; } @@ -3652,6 +3674,7 @@ SDL_Surface* TTF_RenderText_LCD_Wrapped(TTF_Font *font, const char *text, size_t struct TTF_TextLayout { int wrap_length; + bool wrap_whitespace_visible; int *lines; }; @@ -3811,6 +3834,7 @@ static bool LayoutText(TTF_Text *text) { TTF_Font *font = text->internal->font; int wrapLength = text->internal->layout->wrap_length; + bool trim_whitespace = !text->internal->layout->wrap_whitespace_visible; size_t length = SDL_strlen(text->text); int i, width = 0, height = 0, numLines = 0; TTF_Line *strLines = NULL; @@ -3821,7 +3845,7 @@ static bool LayoutText(TTF_Text *text) int *lines = NULL; bool result = false; - if (!GetWrappedLines(font, text->text, length, text->internal->x, wrapLength, &strLines, &numLines, &width, &height)) { + if (!GetWrappedLines(font, text->text, length, text->internal->x, wrapLength, trim_whitespace, &strLines, &numLines, &width, &height)) { return true; } height += text->internal->y; @@ -4221,6 +4245,26 @@ bool TTF_GetTextWrapping(TTF_Text *text, int *wrapLength) return true; } +bool TTF_SetTextWrapWhitespaceVisible(TTF_Text *text, bool visible) +{ + TTF_CHECK_POINTER("text", text, false); + + if (visible == text->internal->layout->wrap_whitespace_visible) { + return true; + } + + text->internal->layout->wrap_whitespace_visible = visible; + text->internal->needs_layout_update = true; + return true; +} + +bool TTF_GetTextWrapSpaceTrimming(TTF_Text *text) +{ + TTF_CHECK_POINTER("text", text, false); + + return text->internal->layout->wrap_whitespace_visible; +} + bool TTF_GetTextSize(TTF_Text *text, int *w, int *h) { if (w) { diff --git a/src/SDL_ttf.sym b/src/SDL_ttf.sym index 351142b8..c5bb0e1b 100644 --- a/src/SDL_ttf.sym +++ b/src/SDL_ttf.sym @@ -84,7 +84,9 @@ SDL3_ttf_0.0.0 { TTF_SetTextFont; TTF_SetTextPosition; TTF_SetTextString; + TTF_SetTextWrapWhitespaceVisible; TTF_SetTextWrapping; + TTF_TextWrapWhitespaceVisible; TTF_UpdateText; TTF_Version; TTF_WasInit; From 59a8d3cdbe4fffb4c648d265eaef6112908f632c Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 19 Oct 2024 20:32:57 -0700 Subject: [PATCH 2/2] Added TTF_SetTextColor() and TTF_GetTextColor() People expected there to be an API function to set the text color. Voila! --- examples/editbox.c | 4 +- examples/showfont.c | 5 +- include/SDL3_ttf/SDL_textengine.h | 1 + include/SDL3_ttf/SDL_ttf.h | 125 +++++++++++++++++++++++++++++- src/SDL_renderer_textengine.c | 2 +- src/SDL_surface_textengine.c | 10 +-- src/SDL_ttf.c | 100 +++++++++++++++++++++++- src/SDL_ttf.sym | 4 + 8 files changed, 235 insertions(+), 16 deletions(-) diff --git a/examples/editbox.c b/examples/editbox.c index 8cd239e9..f5f701a9 100644 --- a/examples/editbox.c +++ b/examples/editbox.c @@ -221,7 +221,9 @@ static void SaveCandidates(EditBox *edit, const SDL_Event *event) edit->candidates = TTF_CreateText(TTF_GetTextEngine(edit->text), edit->font, candidate_text, 0); SDL_free(candidate_text); if (edit->candidates) { - SDL_copyp(&edit->candidates->color, &edit->text->color); + float r, g, b, a; + TTF_GetTextColorFloat(edit->text, &r, &g, &b, &a); + TTF_SetTextColorFloat(edit->candidates, r, g, b, a); } else { ClearCandidates(edit); } diff --git a/examples/showfont.c b/examples/showfont.c index fda33db4..9ff9c6d0 100644 --- a/examples/showfont.c +++ b/examples/showfont.c @@ -550,10 +550,7 @@ int main(int argc, char *argv[]) editRect.w -= 8.0f; scene.edit = EditBox_Create(scene.window, scene.renderer, engine, font, &editRect); if (scene.edit) { - scene.edit->text->color.r = forecol->r / 255.0f; - scene.edit->text->color.g = forecol->g / 255.0f; - scene.edit->text->color.b = forecol->b / 255.0f; - scene.edit->text->color.a = forecol->a / 255.0f; + TTF_SetTextColor(scene.edit->text, forecol->r, forecol->g, forecol->b, forecol->a); EditBox_Insert(scene.edit, message); } diff --git a/include/SDL3_ttf/SDL_textengine.h b/include/SDL3_ttf/SDL_textengine.h index 99222e95..0bf12399 100644 --- a/include/SDL3_ttf/SDL_textengine.h +++ b/include/SDL3_ttf/SDL_textengine.h @@ -106,6 +106,7 @@ typedef struct TTF_TextLayout TTF_TextLayout; struct TTF_TextData { TTF_Font *font; /**< The font used by this text, read-only. */ + SDL_FColor color; /**< The color of the text, read-only. */ bool needs_layout_update; /**< True if the layout needs to be updated */ TTF_TextLayout *layout; /**< Cached layout information, read-only. */ diff --git a/include/SDL3_ttf/SDL_ttf.h b/include/SDL3_ttf/SDL_ttf.h index f78f22fb..3dcce873 100644 --- a/include/SDL3_ttf/SDL_ttf.h +++ b/include/SDL3_ttf/SDL_ttf.h @@ -1341,7 +1341,6 @@ typedef struct TTF_TextData TTF_TextData; typedef struct TTF_Text { char *text; /**< A copy of the text used to create this text object, useful for layout and debugging. This will be freed automatically when the object is destroyed. */ - SDL_FColor color; /**< The color of the text, read-write. You can change this anytime. */ int num_lines; /**< The number of lines in the text, 0 if it's empty */ int refcount; /**< Application reference count, used when freeing surface */ @@ -1549,6 +1548,8 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL TTF_GetTextProperties(TTF_Text *tex * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextEngine */ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextEngine(TTF_Text *text, TTF_TextEngine *engine); @@ -1563,6 +1564,8 @@ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextEngine(TTF_Text *text, TTF_TextEngin * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetTextEngine */ extern SDL_DECLSPEC TTF_TextEngine * SDLCALL TTF_GetTextEngine(TTF_Text *text); @@ -1580,6 +1583,8 @@ extern SDL_DECLSPEC TTF_TextEngine * SDLCALL TTF_GetTextEngine(TTF_Text *text); * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextFont */ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextFont(TTF_Text *text, TTF_Font *font); @@ -1594,9 +1599,99 @@ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextFont(TTF_Text *text, TTF_Font *font) * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetTextFont */ extern SDL_DECLSPEC TTF_Font * SDLCALL TTF_GetTextFont(TTF_Text *text); +/** + * Set the color of a text object. + * + * The default text color is white (255, 255, 255, 255). + * + * \param text the TTF_Text to modify. + * \param r the red color value in the range of 0-255. + * \param g the green color value in the range of 0-255. + * \param b the blue color value in the range of 0-255. + * \param a the alpha value in the range of 0-255. + * \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_GetTextColor + * \sa TTF_SetTextColorFloat + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetTextColor(TTF_Text *text, Uint8 r, Uint8 g, Uint8 b, Uint8 a); + +/** + * Set the color of a text object. + * + * The default text color is white (1.0f, 1.0f, 1.0f, 1.0f). + * + * \param text the TTF_Text to modify. + * \param r the red color value, normally in the range of 0-1. + * \param g the green color value, normally in the range of 0-1. + * \param b the blue color value, normally in the range of 0-1. + * \param a the alpha value in the range of 0-1. + * \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_GetTextColorFloat + * \sa TTF_SetTextColor + */ +extern SDL_DECLSPEC bool SDLCALL TTF_SetTextColorFloat(TTF_Text *text, float r, float g, float b, float a); + +/** + * Get the color of a text object. + * + * \param text the TTF_Text to query. + * \param r a pointer filled in with the red color value in the range of 0-255, may be NULL. + * \param g a pointer filled in with the green color value in the range of 0-255, may be NULL. + * \param b a pointer filled in with the blue color value in the range of 0-255, may be NULL. + * \param a a pointer filled in with the alpha value in the range of 0-255, 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 + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextColorFloat + * \sa TTF_SetTextColor + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetTextColor(TTF_Text *text, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a); + +/** + * Get the color of a text object. + * + * \param text the TTF_Text to query. + * \param r a pointer filled in with the red color value, normally in the range of 0-1, may be NULL. + * \param g a pointer filled in with the green color value, normally in the range of 0-1, may be NULL. + * \param b a pointer filled in with the blue color value, normally in the range of 0-1, may be NULL. + * \param a a pointer filled in with the alpha value in the range of 0-1, 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 + * text. + * + * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextColor + * \sa TTF_SetTextColorFloat + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetTextColorFloat(TTF_Text *text, float *r, float *g, float *b, float *a); + /** * Set the position of a text object. * @@ -1611,6 +1706,8 @@ extern SDL_DECLSPEC TTF_Font * SDLCALL TTF_GetTextFont(TTF_Text *text); * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextPosition */ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextPosition(TTF_Text *text, int x, int y); @@ -1627,6 +1724,8 @@ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextPosition(TTF_Text *text, int x, int * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetTextPosition */ extern SDL_DECLSPEC bool SDLCALL TTF_GetTextPosition(TTF_Text *text, int *x, int *y); @@ -1644,6 +1743,10 @@ extern SDL_DECLSPEC bool SDLCALL TTF_GetTextPosition(TTF_Text *text, int *x, int * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_AppendTextString + * \sa TTF_DeleteTextString + * \sa TTF_InsertTextString */ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextString(TTF_Text *text, const char *string, size_t length); @@ -1665,6 +1768,10 @@ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextString(TTF_Text *text, const char *s * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_AppendTextString + * \sa TTF_DeleteTextString + * \sa TTF_SetTextString */ extern SDL_DECLSPEC bool SDLCALL TTF_InsertTextString(TTF_Text *text, int offset, const char *string, size_t length); @@ -1682,6 +1789,10 @@ extern SDL_DECLSPEC bool SDLCALL TTF_InsertTextString(TTF_Text *text, int offset * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_DeleteTextString + * \sa TTF_InsertTextString + * \sa TTF_SetTextString */ extern SDL_DECLSPEC bool SDLCALL TTF_AppendTextString(TTF_Text *text, const char *string, size_t length); @@ -1702,6 +1813,10 @@ extern SDL_DECLSPEC bool SDLCALL TTF_AppendTextString(TTF_Text *text, const char * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_AppendTextString + * \sa TTF_InsertTextString + * \sa TTF_SetTextString */ extern SDL_DECLSPEC bool SDLCALL TTF_DeleteTextString(TTF_Text *text, int offset, int length); @@ -1718,6 +1833,8 @@ extern SDL_DECLSPEC bool SDLCALL TTF_DeleteTextString(TTF_Text *text, int offset * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_GetTextWrapping */ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapping(TTF_Text *text, int wrapLength); @@ -1734,6 +1851,8 @@ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapping(TTF_Text *text, int wrapLen * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetTextWrapping */ extern SDL_DECLSPEC bool SDLCALL TTF_GetTextWrapping(TTF_Text *text, int *wrapLength); @@ -1751,6 +1870,8 @@ extern SDL_DECLSPEC bool SDLCALL TTF_GetTextWrapping(TTF_Text *text, int *wrapLe * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_TextWrapWhitespaceVisible */ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapWhitespaceVisible(TTF_Text *text, bool visible); @@ -1764,6 +1885,8 @@ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapWhitespaceVisible(TTF_Text *text * text. * * \since This function is available since SDL_ttf 3.0.0. + * + * \sa TTF_SetTextWrapWhitespaceVisible */ extern SDL_DECLSPEC bool SDLCALL TTF_TextWrapWhitespaceVisible(TTF_Text *text); diff --git a/src/SDL_renderer_textengine.c b/src/SDL_renderer_textengine.c index 386597dc..d8e53663 100644 --- a/src/SDL_renderer_textengine.c +++ b/src/SDL_renderer_textengine.c @@ -887,7 +887,7 @@ bool TTF_DrawRendererText(TTF_Text *text, float x, float y) SDL_RenderGeometryRaw(renderer, sequence->texture, sequence->positions, 2 * sizeof(float), - &text->color, 0, + &text->internal->color, 0, sequence->texcoords, 2 * sizeof(float), sequence->num_rects * 4, sequence->indices, sequence->num_rects * 6, sizeof(*sequence->indices)); diff --git a/src/SDL_surface_textengine.c b/src/SDL_surface_textengine.c index f8a70754..8730a276 100644 --- a/src/SDL_surface_textengine.c +++ b/src/SDL_surface_textengine.c @@ -344,11 +344,11 @@ bool TTF_DrawSurfaceText(TTF_Text *text, int x, int y, SDL_Surface *surface) return true; } - if (text->color.r != data->fcolor.r || - text->color.g != data->fcolor.g || - text->color.b != data->fcolor.b || - text->color.a != data->fcolor.a) { - UpdateColor(data, &text->color); + if (text->internal->color.r != data->fcolor.r || + text->internal->color.g != data->fcolor.g || + text->internal->color.b != data->fcolor.b || + text->internal->color.a != data->fcolor.a) { + UpdateColor(data, &text->internal->color); } for (int i = 0; i < data->num_ops; ++i) { diff --git a/src/SDL_ttf.c b/src/SDL_ttf.c index ec342eec..37b04bb3 100644 --- a/src/SDL_ttf.c +++ b/src/SDL_ttf.c @@ -3702,10 +3702,10 @@ static TTF_Text *CreateText(TTF_TextEngine *engine, TTF_Font *font, const char * result->internal = &mem->internal; result->internal->layout = &mem->layout; result->internal->font = font; - result->color.r = 1.0f; - result->color.g = 1.0f; - result->color.b = 1.0f; - result->color.a = 1.0f; + result->internal->color.r = 1.0f; + result->internal->color.g = 1.0f; + result->internal->color.b = 1.0f; + result->internal->color.a = 1.0f; result->internal->needs_layout_update = true; result->internal->engine = engine; result->internal->layout->wrap_length = wrapLength; @@ -4064,6 +4064,98 @@ TTF_Font *TTF_GetTextFont(TTF_Text *text) return text->internal->font; } +bool TTF_SetTextColor(TTF_Text *text, Uint8 r, Uint8 g, Uint8 b, Uint8 a) +{ + const float fR = (float)r / 255.0f; + const float fG = (float)g / 255.0f; + const float fB = (float)b / 255.0f; + const float fA = (float)a / 255.0f; + + return TTF_SetTextColorFloat(text, fR, fG, fB, fA); +} + +bool TTF_SetTextColorFloat(TTF_Text *text, float r, float g, float b, float a) +{ + TTF_CHECK_POINTER("text", text, false); + + text->internal->color.r = r; + text->internal->color.g = g; + text->internal->color.b = b; + text->internal->color.a = a; + return true; +} + +bool TTF_GetTextColor(TTF_Text *text, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) +{ + float fR = 1.0f, fG = 1.0f, fB = 1.0f, fA = 1.0f; + + if (!TTF_GetTextColorFloat(text, &fR, &fG, &fB, &fA)) { + if (r) { + *r = 255; + } + if (g) { + *g = 255; + } + if (b) { + *b = 255; + } + if (b) { + *b = 255; + } + return false; + } + + if (r) { + *r = (Uint8)SDL_roundf(SDL_clamp(fR, 0.0f, 1.0f) * 255.0f); + } + if (g) { + *g = (Uint8)SDL_roundf(SDL_clamp(fG, 0.0f, 1.0f) * 255.0f); + } + if (b) { + *b = (Uint8)SDL_roundf(SDL_clamp(fB, 0.0f, 1.0f) * 255.0f); + } + if (a) { + *a = (Uint8)SDL_roundf(SDL_clamp(fA, 0.0f, 1.0f) * 255.0f); + } + return true; +} + +bool TTF_GetTextColorFloat(TTF_Text *text, float *r, float *g, float *b, float *a) +{ + SDL_FColor color; + + if (r) { + *r = 1.0f; + } + if (g) { + *g = 1.0f; + } + if (b) { + *b = 1.0f; + } + if (a) { + *a = 1.0f; + } + + TTF_CHECK_POINTER("text", text, false); + + color = text->internal->color; + + if (r) { + *r = color.r; + } + if (g) { + *g = color.g; + } + if (b) { + *b = color.b; + } + if (a) { + *a = color.a; + } + return true; +} + bool TTF_SetTextPosition(TTF_Text *text, int x, int y) { TTF_CHECK_POINTER("text", text, false); diff --git a/src/SDL_ttf.sym b/src/SDL_ttf.sym index c5bb0e1b..4aab9e0f 100644 --- a/src/SDL_ttf.sym +++ b/src/SDL_ttf.sym @@ -43,6 +43,8 @@ SDL3_ttf_0.0.0 { TTF_GetPreviousTextSubString; TTF_GetStringSize; TTF_GetStringSizeWrapped; + TTF_GetTextColor; + TTF_GetTextColorFloat; TTF_GetTextEngine; TTF_GetTextFont; TTF_GetTextPosition; @@ -80,6 +82,8 @@ SDL3_ttf_0.0.0 { TTF_SetFontSizeDPI; TTF_SetFontStyle; TTF_SetFontWrapAlignment; + TTF_SetTextColor; + TTF_SetTextColorFloat; TTF_SetTextEngine; TTF_SetTextFont; TTF_SetTextPosition;