Skip to content

Commit

Permalink
Defer calculating text layout changes until they're needed
Browse files Browse the repository at this point in the history
This allows loading lots of text and making multiple font changes quickly. The application can call TTF_UpdateText() if there's a specific point where changes should be applied, otherwise they'll be applied as needed when the text is renderered.
  • Loading branch information
slouken committed Oct 2, 2024
1 parent f1d6bb5 commit bcbf4da
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 97 deletions.
14 changes: 7 additions & 7 deletions build-scripts/SDL_migration.cocci
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,18 @@
(...)
@@
@@
- TTF_SizeText
+ TTF_GetStringSize
(...)
@@
@@
- TTF_SizeUTF8
+ TTF_SizeText
+ TTF_GetStringSize
(...)
@@
@@
- TTF_MeasureUTF8
+ TTF_MeasureText
+ TTF_MeasureString
(...)
@@
@@
Expand Down Expand Up @@ -160,8 +165,3 @@
- TTF_SetFontScriptName
+ TTF_SetFontScript
(...)
@@
@@
- TTF_SizeText
+ TTF_GetTextSize
(...)
2 changes: 1 addition & 1 deletion examples/testapp.c
Original file line number Diff line number Diff line change
Expand Up @@ -894,7 +894,7 @@ int main(void)
}
}
#endif
if (!TTF_GetTextSize(font, text, 0, &w, &h)) {
if (!TTF_GetStringSize(font, text, 0, &w, &h)) {
SDL_Log("size failed");
}
if (w == 0) {
Expand Down
22 changes: 16 additions & 6 deletions include/SDL3_ttf/SDL_textengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,20 @@ typedef struct TTF_TextLayout TTF_TextLayout;
/* Private data in TTF_Text, available to implementations */
struct TTF_TextData
{
SDL_PropertiesID props; /**< Custom properties associated with this text, read-only. This field is created as-needed using TTF_GetTextProperties() and the properties may be then set and read normally */
int num_ops; /**< The number of drawing operations to render this text, read-only. */
TTF_DrawOperation *ops; /**< The drawing operations used to render this text, read-only. */
TTF_TextLayout *layout; /**< Cached layout information, read-only */
TTF_TextEngine *engine; /**< The engine used to create this text, read-only. */
void *engine_text; /**< The implementation-specific representation of this text */
TTF_Font *font; /**< The font used by this text, read-only. */

bool needs_layout_update; /**< True if the layout needs to be updated */
TTF_TextLayout *layout; /**< Cached layout information, read-only. */
int w; /**< The width of this text, in pixels, read-only. */
int h; /**< The height of this text, in pixels, read-only. */
int num_ops; /**< The number of drawing operations to render this text, read-only. */
TTF_DrawOperation *ops; /**< The drawing operations used to render this text, read-only. */

SDL_PropertiesID props; /**< Custom properties associated with this text, read-only. This field is created as-needed using TTF_GetTextProperties() and the properties may be then set and read normally */

bool needs_engine_update; /**< True if the engine text needs to be updated */
TTF_TextEngine *engine; /**< The engine used to render this text, read-only. */
void *engine_text; /**< The implementation-specific representation of this text */
};

/**
Expand All @@ -132,6 +140,8 @@ struct TTF_TextEngine
*
* All fields of `text` except `internal->engine_text` will already be filled out.
*
* This function should set the `internal->engine_text` field to a non-NULL value.
*
* \param userdata the userdata pointer in this interface.
* \param text the text object being created.
*/
Expand Down
51 changes: 45 additions & 6 deletions include/SDL3_ttf/SDL_ttf.h
Original file line number Diff line number Diff line change
Expand Up @@ -966,7 +966,7 @@ extern SDL_DECLSPEC bool TTF_GetGlyphKerning(TTF_Font *font, Uint32 previous_ch,
*
* \since This function is available since SDL_ttf 3.0.0.
*/
extern SDL_DECLSPEC bool SDLCALL TTF_GetTextSize(TTF_Font *font, const char *text, size_t length, int *w, int *h);
extern SDL_DECLSPEC bool SDLCALL TTF_GetStringSize(TTF_Font *font, const char *text, size_t length, int *w, int *h);

/**
* Calculate the dimensions of a rendered string of UTF-8 text.
Expand Down Expand Up @@ -994,7 +994,7 @@ extern SDL_DECLSPEC bool SDLCALL TTF_GetTextSize(TTF_Font *font, const char *tex
*
* \since This function is available since SDL_ttf 3.0.0.
*/
extern SDL_DECLSPEC bool SDLCALL TTF_GetTextSizeWrapped(TTF_Font *font, const char *text, size_t length, int wrapLength, int *w, int *h);
extern SDL_DECLSPEC bool SDLCALL TTF_GetStringSizeWrapped(TTF_Font *font, const char *text, size_t length, int wrapLength, int *w, int *h);

/**
* Calculate how much of a UTF-8 string will fit in a given width.
Expand All @@ -1020,7 +1020,7 @@ extern SDL_DECLSPEC bool SDLCALL TTF_GetTextSizeWrapped(TTF_Font *font, const ch
*
* \since This function is available since SDL_ttf 3.0.0.
*/
extern SDL_DECLSPEC bool SDLCALL TTF_MeasureText(TTF_Font *font, const char *text, size_t length, int measure_width, int *extent, int *count);
extern SDL_DECLSPEC bool SDLCALL TTF_MeasureString(TTF_Font *font, const char *text, size_t length, int measure_width, int *extent, int *count);

/**
* Render UTF-8 text at high quality to a new 8-bit surface.
Expand Down Expand Up @@ -1323,9 +1323,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. */
int w; /**< The width of this text, in pixels, read-only. */
int h; /**< The height of this text, in pixels, read-only. */
TTF_Font *font; /**< The font used by this text, read-only. You can change the font using TTF_SetTextFont(). */
SDL_FColor color; /**< The color of the text, read-write. You can change this anytime. */

int refcount; /**< Application reference count, used when freeing surface */
Expand Down Expand Up @@ -1530,6 +1527,15 @@ extern SDL_DECLSPEC SDL_PropertiesID SDLCALL TTF_GetTextProperties(TTF_Text *tex
*/
extern SDL_DECLSPEC bool SDLCALL TTF_SetTextEngine(TTF_Text *text, TTF_TextEngine *engine);

/**
* Get the text engine used by a text object.
*
* \param text the TTF_Text to query.
* \returns the TTF_TextEngine used by the text on success or NULL on failure; call
* SDL_GetError() for more information.
*/
extern SDL_DECLSPEC TTF_TextEngine * SDLCALL TTF_GetTextEngine(TTF_Text *text);

/**
* Set the font used by a text object.
*
Expand All @@ -1540,6 +1546,15 @@ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextEngine(TTF_Text *text, TTF_TextEngin
*/
extern SDL_DECLSPEC bool SDLCALL TTF_SetTextFont(TTF_Text *text, TTF_Font *font);

/**
* Get the font used by a text object.
*
* \param text the TTF_Text to query.
* \returns the TTF_Font used by the text on success or NULL on failure; call
* SDL_GetError() for more information.
*/
extern SDL_DECLSPEC TTF_Font * SDLCALL TTF_GetTextFont(TTF_Text *text);

/**
* Set the UTF-8 text used by a text object.
*
Expand Down Expand Up @@ -1610,6 +1625,30 @@ extern SDL_DECLSPEC bool SDLCALL TTF_SetTextWrapping(TTF_Text *text, bool wrap,
*/
extern SDL_DECLSPEC bool SDLCALL TTF_GetTextWrapping(TTF_Text *text, bool *wrap, int *wrapLength);

/**
* Get the size of a text object.
*
* The size of the text may change when the font or font style and size change.
*
* \param text the TTF_Text to query.
* \param w a pointer filled in with the width of the text, in pixels, may be NULL.
* \param h a pointer filled in with the height of the text, in pixels, may be NULL.
* \returns true on success or false on failure; call
* SDL_GetError() for more information.
*/
extern SDL_DECLSPEC bool SDLCALL TTF_GetTextSize(TTF_Text *text, int *w, int *h);

/**
* Update the layout of a text object.
*
* This is automatically done when the layout is requested or the text is rendered, but you can call this if you need more control over the timing of when the layout and text engine representation are updated.
*
* \param text the TTF_Text to update.
* \returns true on success or false on failure; call
* SDL_GetError() for more information.
*/
extern SDL_DECLSPEC bool SDLCALL TTF_UpdateText(TTF_Text *text);

/**
* Destroy a text object created by a text engine.
*
Expand Down
7 changes: 6 additions & 1 deletion src/SDL_renderer_textengine.c
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ static TTF_RendererTextEngineData *CreateEngineData(SDL_Renderer *renderer)

static bool SDLCALL CreateText(void *userdata, TTF_Text *text)
{
TTF_Font *font = text->font;
TTF_Font *font = text->internal->font;
Uint32 font_generation = TTF_GetFontGeneration(font);
int num_ops = text->internal->num_ops;
TTF_DrawOperation *ops;
Expand Down Expand Up @@ -857,6 +857,11 @@ bool TTF_DrawRendererText(TTF_Text *text, float x, float y)
return SDL_InvalidParamError("text");
}

// Make sure the text is up to date
if (!TTF_UpdateText(text)) {
return false;
}

renderer = ((TTF_RendererTextEngineData *)text->internal->engine->userdata)->renderer;
data = (TTF_RendererTextEngineTextData *)text->internal->engine_text;
AtlasDrawSequence *sequence = data->draw_sequence;
Expand Down
7 changes: 6 additions & 1 deletion src/SDL_surface_textengine.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ static TTF_SurfaceTextEngineData *CreateEngineData(void)

static bool SDLCALL CreateText(void *userdata, TTF_Text *text)
{
TTF_Font *font = text->font;
TTF_Font *font = text->internal->font;
Uint32 font_generation = TTF_GetFontGeneration(font);
int num_ops = text->internal->num_ops;
const TTF_DrawOperation *ops = text->internal->ops;
Expand Down Expand Up @@ -335,6 +335,11 @@ bool TTF_DrawSurfaceText(TTF_Text *text, int x, int y, SDL_Surface *surface)
return SDL_InvalidParamError("surface");
}

// Make sure the text is up to date
if (!TTF_UpdateText(text)) {
return false;
}

data = (TTF_SurfaceTextEngineTextData *)text->internal->engine_text;

if (text->color.r != data->fcolor.r ||
Expand Down
Loading

0 comments on commit bcbf4da

Please sign in to comment.