diff --git a/include/SDL3_ttf/SDL_ttf.h b/include/SDL3_ttf/SDL_ttf.h index c785c8cf..e20acf84 100644 --- a/include/SDL3_ttf/SDL_ttf.h +++ b/include/SDL3_ttf/SDL_ttf.h @@ -844,6 +844,33 @@ extern SDL_DECLSPEC void SDLCALL TTF_SetFontKerning(TTF_Font *font, bool enabled */ extern SDL_DECLSPEC bool SDLCALL TTF_GetFontKerning(const TTF_Font *font); +/** + * Query the font's bounding box. + * + * The bounding box defines bounds large enough to contain any glyph from + * the font. It is expressed in pixel offsets from glyph's origin (0,0), + * with Y axis pointing upwards. Thus maxy offset may be seen as the + * "maximum ascender" and miny offset - as the "minimum descender". + * + * \param font the font to query. + * \param minx a pointer filled in with the minimum x coordinate of *any* glyph + * in this font from it's origin. This value may be negative. + * \param maxx a pointer filled in with the maximum x coordinate of *any* glyph + * in this font from it's origin. + * \param miny a pointer filled in with the minimum y coordinate of *any* glyph + * in this font from it's origin. This value may be negative. + * \param maxy a pointer filled in with the maximum y coordinate of *any* glyph + * in this font from it's origin. + * \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 + * font. + * + * \since This function is available since SDL_ttf 3.4.0. + */ +extern SDL_DECLSPEC bool SDLCALL TTF_GetFontBBox(const TTF_Font *font, int *minx, int *maxx, int *miny, int *maxy); + /** * Query whether a font is fixed-width. * diff --git a/src/SDL_ttf.c b/src/SDL_ttf.c index a34e8478..0abd7378 100644 --- a/src/SDL_ttf.c +++ b/src/SDL_ttf.c @@ -5915,6 +5915,34 @@ bool TTF_GetFontKerning(const TTF_Font *font) return font->enable_kerning; } +bool TTF_GetFontBBox(const TTF_Font *font, int *minx, int *maxx, int *miny, int *maxy) +{ + TTF_CHECK_FONT(font, false); + + /* Bitmap fonts do not contain bbox information */ + if (!FT_IS_SCALABLE(font->face)) { + return false; + } + + const FT_Face face = font->face; + /* Recalculate FT_Face's bbox from font units to pixels */ + FT_Fixed xscale = face->size->metrics.x_scale; + FT_Fixed yscale = face->size->metrics.y_scale; + if (minx) { + *minx = FT_CEIL(FT_MulFix(face->bbox.xMin, xscale)); + } + if (maxx) { + *maxx = FT_CEIL(FT_MulFix(face->bbox.xMax, xscale)); + } + if (miny) { + *miny = FT_CEIL(FT_MulFix(face->bbox.yMin, yscale)); + } + if (maxy) { + *maxy = FT_CEIL(FT_MulFix(face->bbox.yMax, yscale)); + } + return true; +} + int TTF_GetNumFontFaces(const TTF_Font *font) { TTF_CHECK_FONT(font, 0); diff --git a/src/SDL_ttf.sym b/src/SDL_ttf.sym index 34143f6b..ce0ec5aa 100644 --- a/src/SDL_ttf.sym +++ b/src/SDL_ttf.sym @@ -119,5 +119,6 @@ SDL3_ttf_0.0.0 { TTF_WasInit; TTF_SetFontCharSpacing; TTF_GetFontCharSpacing; + TTF_GetFontBBox; local: *; };