diff --git a/include/CSFML/Graphics/Font.h b/include/CSFML/Graphics/Font.h index 48164f3..e80c53b 100644 --- a/include/CSFML/Graphics/Font.h +++ b/include/CSFML/Graphics/Font.h @@ -101,6 +101,31 @@ CSFML_GRAPHICS_API void sfFont_destroy(const sfFont* font); CSFML_GRAPHICS_API sfGlyph sfFont_getGlyph(const sfFont* font, uint32_t codePoint, unsigned int characterSize, bool bold, float outlineThickness); +//////////////////////////////////////////////////////////// +/// \brief Get a glyph in a font by glyph ID +/// +/// If the font is a bitmap font, not all character sizes +/// might be available. If the glyph is not available at the +/// requested size, an empty glyph is returned. +/// +/// Glyph IDs are font specific and are for example +/// provided by the shaped glyphs of a text. +/// +/// Be aware that using a negative value for the outline +/// thickness will cause distorted rendering. +/// +/// \param font Source font +/// \param id ID of the glyph to get +/// \param characterSize Character size, in pixels +/// \param bold Retrieve the bold version or the regular one? +/// \param outlineThickness Thickness of outline (when != 0 the glyph will not be filled) +/// +/// \return The corresponding glyph +/// +//////////////////////////////////////////////////////////// +CSFML_GRAPHICS_API sfGlyph + sfFont_getGlyphById(const sfFont* font, uint32_t id, unsigned int characterSize, bool bold, float outlineThickness); + //////////////////////////////////////////////////////////// /// \brief Determine if this font has a glyph representing the requested code point /// @@ -157,6 +182,44 @@ CSFML_GRAPHICS_API float sfFont_getBoldKerning(const sfFont* font, uint32_t firs //////////////////////////////////////////////////////////// CSFML_GRAPHICS_API float sfFont_getLineSpacing(const sfFont* font, unsigned int characterSize); +//////////////////////////////////////////////////////////// +/// \brief Get the ascent of a font +/// +/// The ascent is the largest distance between the baseline and +/// the top of all glyphs in the font. +/// +/// Be aware that there is no uniform definition of how the +/// ascent is calculated. It can vary from font to font. +/// +/// \param font Source font +/// \param characterSize Reference character size +/// +/// \return Ascent, in pixels +/// +//////////////////////////////////////////////////////////// +CSFML_GRAPHICS_API float sfFont_getAscent(const sfFont* font, unsigned int characterSize); + +//////////////////////////////////////////////////////////// +/// \brief Get the descent of a font +/// +/// The descent is the largest distance between the baseline and +/// the bottom of all glyphs in the font. +/// +/// Be aware that there is no uniform definition of how the +/// descent is calculated. It can vary from font to font. +/// +/// The descent shares the same coordinate system as the +/// ascent. This means that it will be negative for distances +/// below the baseline. +/// +/// \param font Source font +/// \param characterSize Reference character size +/// +/// \return Descent, in pixels +/// +//////////////////////////////////////////////////////////// +CSFML_GRAPHICS_API float sfFont_getDescent(const sfFont* font, unsigned int characterSize); + //////////////////////////////////////////////////////////// /// \brief Get the position of the underline /// diff --git a/include/CSFML/Graphics/FontInfo.h b/include/CSFML/Graphics/FontInfo.h index 6037e14..3806718 100644 --- a/include/CSFML/Graphics/FontInfo.h +++ b/include/CSFML/Graphics/FontInfo.h @@ -29,10 +29,16 @@ //////////////////////////////////////////////////////////// #include +#include +#include + //////////////////////////////////////////////////////////// /// sfFontInfo holds various information about a font //////////////////////////////////////////////////////////// typedef struct { - const char* family; + uint64_t id; ///< A unique ID that identifies the font + const char* family; ///< The font family + bool hasKerning; ///< Has kerning information + bool hasVerticalMetrics; ///< Has native vertical metrics } sfFontInfo; diff --git a/src/CSFML/Graphics/CMakeLists.txt b/src/CSFML/Graphics/CMakeLists.txt index e3e056e..a1536a4 100644 --- a/src/CSFML/Graphics/CMakeLists.txt +++ b/src/CSFML/Graphics/CMakeLists.txt @@ -12,6 +12,7 @@ set(SRC ${SRCROOT}/Color.cpp ${INCROOT}/Color.h ${SRCROOT}/ConvertColor.hpp + ${SRCROOT}/ConvertGlyph.hpp ${SRCROOT}/ConvertRect.hpp ${SRCROOT}/ConvertRenderStates.hpp ${SRCROOT}/ConvertStencil.hpp diff --git a/src/CSFML/Graphics/ConvertGlyph.hpp b/src/CSFML/Graphics/ConvertGlyph.hpp new file mode 100644 index 0000000..ef52405 --- /dev/null +++ b/src/CSFML/Graphics/ConvertGlyph.hpp @@ -0,0 +1,42 @@ +//////////////////////////////////////////////////////////// +// +// SFML - Simple and Fast Multimedia Library +// Copyright (C) 2007-2026 Laurent Gomila (laurent@sfml-dev.org) +// +// This software is provided 'as-is', without any express or implied warranty. +// In no event will the authors be held liable for any damages arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it freely, +// subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; +// you must not claim that you wrote the original software. +// If you use this software in a product, an acknowledgment +// in the product documentation would be appreciated but is not required. +// +// 2. Altered source versions must be plainly marked as such, +// and must not be misrepresented as being the original software. +// +// 3. This notice may not be removed or altered from any source distribution. +// +//////////////////////////////////////////////////////////// + +#pragma once + +//////////////////////////////////////////////////////////// +// Headers +//////////////////////////////////////////////////////////// +#include +#include + +#include + + +//////////////////////////////////////////////////////////// +// Convert sf::Glyph to sfGlyph +//////////////////////////////////////////////////////////// +[[nodiscard]] inline sfGlyph convertGlyph(const sf::Glyph& glyph) +{ + return {glyph.advance, convertRect(glyph.bounds), convertRect(glyph.textureRect)}; +} diff --git a/src/CSFML/Graphics/Font.cpp b/src/CSFML/Graphics/Font.cpp index 63991b1..a854015 100644 --- a/src/CSFML/Graphics/Font.cpp +++ b/src/CSFML/Graphics/Font.cpp @@ -26,7 +26,7 @@ // Headers //////////////////////////////////////////////////////////// #include -#include +#include #include #include @@ -88,14 +88,15 @@ sfGlyph sfFont_getGlyph(const sfFont* font, uint32_t codePoint, unsigned int cha { assert(font); - sf::Glyph sfmlGlyph = font->getGlyph(codePoint, characterSize, bold, outlineThickness); + return convertGlyph(font->getGlyph(codePoint, characterSize, bold, outlineThickness)); +} - sfGlyph glyph{}; - glyph.advance = sfmlGlyph.advance; - glyph.bounds = convertRect(sfmlGlyph.bounds); - glyph.textureRect = convertRect(sfmlGlyph.textureRect); - return glyph; +//////////////////////////////////////////////////////////// +sfGlyph sfFont_getGlyphById(const sfFont* font, uint32_t id, unsigned int characterSize, bool bold, float outlineThickness) +{ + assert(font); + return convertGlyph(font->getGlyphById(id, characterSize, bold, outlineThickness)); } @@ -131,6 +132,22 @@ float sfFont_getLineSpacing(const sfFont* font, unsigned int characterSize) } +//////////////////////////////////////////////////////////// +float sfFont_getAscent(const sfFont* font, unsigned int characterSize) +{ + assert(font); + return font->getAscent(characterSize); +} + + +//////////////////////////////////////////////////////////// +float sfFont_getDescent(const sfFont* font, unsigned int characterSize) +{ + assert(font); + return font->getDescent(characterSize); +} + + //////////////////////////////////////////////////////////// float sfFont_getUnderlinePosition(const sfFont* font, unsigned int characterSize) { @@ -178,5 +195,6 @@ bool sfFont_isSmooth(const sfFont* font) sfFontInfo sfFont_getInfo(const sfFont* font) { assert(font); - return {font->getInfo().family.c_str()}; + const sf::Font::Info& info = font->getInfo(); + return {info.id, info.family.c_str(), info.hasKerning, info.hasVerticalMetrics}; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index dd6cdaa..24e2890 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -49,6 +49,7 @@ add_executable(test-csfml-graphics Graphics/BlendMode.test.cpp Graphics/Color.test.cpp Graphics/CoordinateType.test.cpp + Graphics/Font.test.cpp Graphics/Image.test.cpp Graphics/PrimitiveType.test.cpp Graphics/Rect.test.cpp diff --git a/test/Graphics/Font.test.cpp b/test/Graphics/Font.test.cpp new file mode 100644 index 0000000..3bf2855 --- /dev/null +++ b/test/Graphics/Font.test.cpp @@ -0,0 +1,27 @@ +#include + +#include + +#include + +TEST_CASE("[Graphics] sfFont") +{ + SECTION("sfFont_createFromFile") + { + CHECK(sfFont_createFromFile("does/not/exist.ttf") == nullptr); + + sfFont* font = sfFont_createFromFile("Graphics/tuffy.ttf"); + REQUIRE(font != nullptr); + + const sfFontInfo info = sfFont_getInfo(font); + CHECK(info.id != 0); + CHECK(std::string(info.family) == "Tuffy"); + CHECK(!info.hasVerticalMetrics); + + CHECK(sfFont_getAscent(font, 10) > 0); + CHECK(sfFont_getDescent(font, 10) < 0); + CHECK(sfFont_getAscent(font, 20) > sfFont_getAscent(font, 10)); + + sfFont_destroy(font); + } +} diff --git a/test/Graphics/tuffy.ttf b/test/Graphics/tuffy.ttf new file mode 100644 index 0000000..8ea6470 Binary files /dev/null and b/test/Graphics/tuffy.ttf differ