Remove default empty state of sf::Font

This commit is contained in:
Chris Thrasher 2024-05-18 11:06:12 -06:00
parent 0ac278b2d6
commit 504b850f03
18 changed files with 81 additions and 185 deletions

View File

@ -27,9 +27,7 @@
/// sf::Sprite sprite(texture);
///
/// // Create a graphical text to display
/// sf::Font font;
/// if (!font.loadFromFile("arial.ttf"))
/// return EXIT_FAILURE;
/// const auto font = sf::Font::loadFromFile("arial.ttf").value();
/// sf::Text text(font, "Hello SFML", 50);
///
/// // Load a music to play

View File

@ -94,9 +94,7 @@ int main(int argc, char* argv[])
image.setPosition(sf::Vector2f(screen.size) / 2.f);
image.setOrigin(sf::Vector2f(texture.getSize()) / 2.f);
sf::Font font;
if (!font.loadFromFile("tuffy.ttf"))
return EXIT_FAILURE;
const auto font = sf::Font::loadFromFile("tuffy.ttf").value();
sf::Text text(font, "Tap anywhere to move the logo.", 64);
text.setFillColor(sf::Color::Black);

View File

@ -41,7 +41,6 @@ struct SFMLmainWindow
{
SFMLmainWindow(sf::WindowHandle win) : renderWindow(win)
{
const std::filesystem::path resPath = [[[NSBundle mainBundle] resourcePath] tostdstring];
if (!logo.loadFromFile(resPath / "logo.png"))
NSLog(@"Couldn't load the logo image");
@ -51,18 +50,16 @@ struct SFMLmainWindow
sprite.scale({0.3f, 0.3f});
sprite.setPosition(sf::Vector2f(renderWindow.getSize()) / 2.f);
if (!font.loadFromFile(resPath / "tuffy.ttf"))
NSLog(@"Couldn't load the font");
text.setFillColor(sf::Color::White);
}
sf::RenderWindow renderWindow;
sf::Font font;
sf::Text text{font};
sf::Texture logo;
sf::Sprite sprite{logo};
sf::Color background{sf::Color::Blue};
std::filesystem::path resPath{[[[NSBundle mainBundle] resourcePath] tostdstring]};
sf::RenderWindow renderWindow;
sf::Font font{sf::Font::loadFromFile(resPath / "tuffy.ttf").value()};
sf::Text text{font};
sf::Texture logo;
sf::Sprite sprite{logo};
sf::Color background{sf::Color::Blue};
};
// Private stuff

View File

@ -91,9 +91,7 @@ int main()
sf::RenderWindow window(sf::VideoMode({windowWidth, windowHeight}), "SFML Island", sf::Style::Titlebar | sf::Style::Close);
window.setVerticalSyncEnabled(true);
sf::Font font;
if (!font.loadFromFile("resources/tuffy.ttf"))
return EXIT_FAILURE;
const auto font = sf::Font::loadFromFile("resources/tuffy.ttf").value();
// Create all of our graphics resources
sf::Text hudText(font);

View File

@ -94,9 +94,7 @@ int main()
window.setVerticalSyncEnabled(true);
// Load the text font
sf::Font font;
if (!font.loadFromFile("resources/tuffy.ttf"))
return EXIT_FAILURE;
const auto font = sf::Font::loadFromFile("resources/tuffy.ttf").value();
// Set up our string conversion parameters
sstr.precision(2);

View File

@ -65,9 +65,7 @@ int main()
const sf::Sprite background(backgroundTexture);
// Create some text to draw on top of our OpenGL object
sf::Font font;
if (!font.loadFromFile(resourcesDir() / "tuffy.ttf"))
return EXIT_FAILURE;
const auto font = sf::Font::loadFromFile(resourcesDir() / "tuffy.ttf").value();
sf::Text text(font, "SFML / OpenGL demo");
sf::Text sRgbInstructions(font, "Press space to toggle sRGB conversion");

View File

@ -346,9 +346,7 @@ int main()
window.setVerticalSyncEnabled(true);
// Load the application font and pass it to the Effect class
sf::Font font;
if (!font.loadFromFile("resources/tuffy.ttf"))
return EXIT_FAILURE;
const auto font = sf::Font::loadFromFile("resources/tuffy.ttf").value();
Effect::setFont(font);
// Create the effects

View File

@ -1051,9 +1051,7 @@ int main()
window.setVerticalSyncEnabled(true);
// Load the application font and pass it to the Effect class
sf::Font font;
if (!font.loadFromFile(resourcesDir() / "tuffy.ttf"))
return EXIT_FAILURE;
const auto font = sf::Font::loadFromFile(resourcesDir() / "tuffy.ttf").value();
Effect::setFont(font);
// Create the effects

View File

@ -84,9 +84,7 @@ int main()
ball.setOrigin({ballRadius / 2.f, ballRadius / 2.f});
// Load the text font
sf::Font font;
if (!font.loadFromFile(resourcesDir() / "tuffy.ttf"))
return EXIT_FAILURE;
const auto font = sf::Font::loadFromFile(resourcesDir() / "tuffy.ttf").value();
// Initialize the pause message
sf::Text pauseMessage(font);

View File

@ -37,6 +37,7 @@
#include <filesystem>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <vector>
@ -87,12 +88,12 @@ public:
///
/// \param filename Path of the font file to load
///
/// \return True if loading succeeded, false if it failed
/// \return Font if loading succeeded, `std::nullopt` if it failed
///
/// \see loadFromMemory, loadFromStream
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromFile(const std::filesystem::path& filename);
[[nodiscard]] static std::optional<Font> loadFromFile(const std::filesystem::path& filename);
////////////////////////////////////////////////////////////
/// \brief Load the font from a file in memory
@ -108,12 +109,12 @@ public:
/// \param data Pointer to the file data in memory
/// \param sizeInBytes Size of the data to load, in bytes
///
/// \return True if loading succeeded, false if it failed
/// \return Font if loading succeeded, `std::nullopt` if it failed
///
/// \see loadFromFile, loadFromStream
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromMemory(const void* data, std::size_t sizeInBytes);
[[nodiscard]] static std::optional<Font> loadFromMemory(const void* data, std::size_t sizeInBytes);
////////////////////////////////////////////////////////////
/// \brief Load the font from a custom stream
@ -130,12 +131,12 @@ public:
///
/// \param stream Source stream to read from
///
/// \return True if loading succeeded, false if it failed
/// \return Font if loading succeeded, `std::nullopt` if it failed
///
/// \see loadFromFile, loadFromMemory
///
////////////////////////////////////////////////////////////
[[nodiscard]] bool loadFromStream(InputStream& stream);
[[nodiscard]] static std::optional<Font> loadFromStream(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief Get the font information
@ -322,12 +323,6 @@ private:
std::vector<Row> rows; //!< List containing the position of all the existing rows
};
////////////////////////////////////////////////////////////
/// \brief Free all the internal resources
///
////////////////////////////////////////////////////////////
void cleanup();
////////////////////////////////////////////////////////////
/// \brief Find or create the glyphs page corresponding to the given character size
///
@ -378,6 +373,12 @@ private:
struct FontHandles;
using PageTable = std::unordered_map<unsigned int, Page>; //!< Table mapping a character size to its page (texture)
////////////////////////////////////////////////////////////
/// \brief Create a font from font handles and a family name
///
////////////////////////////////////////////////////////////
Font(std::shared_ptr<FontHandles>&& fontHandles, std::string&& familyName);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
@ -430,14 +431,8 @@ private:
///
/// Usage example:
/// \code
/// // Declare a new font
/// sf::Font font;
///
/// // Load it from a file
/// if (!font.loadFromFile("arial.ttf"))
/// {
/// // error...
/// }
/// // Load a new font
/// const auto font = sf::Font::loadFromFile("arial.ttf").value();
///
/// // Create a text which uses our font
/// sf::Text text1(font);

View File

@ -272,11 +272,7 @@ private:
/// // error...
/// }
/// sf::Sprite sprite(texture);
/// sf::Font font;
/// if (!font.loadFromFile("arial.ttf"))
/// {
/// // error...
/// }
/// const auto font = sf::Font::loadFromFile("arial.ttf").value();
/// sf::Text text(font);
/// ...
///

View File

@ -468,12 +468,8 @@ private:
///
/// Usage example:
/// \code
/// // Declare and load a font
/// sf::Font font;
/// if (!font.loadFromFile("arial.ttf"))
/// {
/// // Handle error...
/// }
/// // Load a font
/// const auto font = sf::Font::loadFromFile("arial.ttf").value();
///
/// // Create a text
/// sf::Text text(font, "hello");

View File

@ -124,13 +124,17 @@ struct Font::FontHandles
////////////////////////////////////////////////////////////
bool Font::loadFromFile(const std::filesystem::path& filename)
Font::Font(std::shared_ptr<FontHandles>&& fontHandles, std::string&& familyName) : m_fontHandles(std::move(fontHandles))
{
m_info.family = std::move(familyName);
}
////////////////////////////////////////////////////////////
std::optional<Font> Font::loadFromFile(const std::filesystem::path& filename)
{
#ifndef SFML_SYSTEM_ANDROID
// Cleanup the previous resources
cleanup();
auto fontHandles = std::make_shared<FontHandles>();
// Initialize FreeType
@ -139,7 +143,7 @@ bool Font::loadFromFile(const std::filesystem::path& filename)
if (FT_Init_FreeType(&fontHandles->library) != 0)
{
err() << "Failed to load font (failed to initialize FreeType)\n" << formatDebugPathInfo(filename) << std::endl;
return false;
return std::nullopt;
}
// Load the new font face from the specified file
@ -147,7 +151,7 @@ bool Font::loadFromFile(const std::filesystem::path& filename)
if (FT_New_Face(fontHandles->library, filename.string().c_str(), 0, &face) != 0)
{
err() << "Failed to load font (failed to create the font face)\n" << formatDebugPathInfo(filename) << std::endl;
return false;
return std::nullopt;
}
fontHandles->face = face;
@ -155,7 +159,7 @@ bool Font::loadFromFile(const std::filesystem::path& filename)
if (FT_Stroker_New(fontHandles->library, &fontHandles->stroker) != 0)
{
err() << "Failed to load font (failed to create the stroker)\n" << formatDebugPathInfo(filename) << std::endl;
return false;
return std::nullopt;
}
// Select the unicode character map
@ -163,32 +167,26 @@ bool Font::loadFromFile(const std::filesystem::path& filename)
{
err() << "Failed to load font (failed to set the Unicode character set)\n"
<< formatDebugPathInfo(filename) << std::endl;
return false;
return std::nullopt;
}
// Store the loaded font handles
m_fontHandles = std::move(fontHandles);
// Store the font information
m_info.family = face->family_name ? face->family_name : std::string();
return true;
return Font(std::move(fontHandles), std::string(face->family_name ? face->family_name : ""));
#else
m_stream = std::make_shared<priv::ResourceStream>(filename);
return loadFromStream(*m_stream);
auto stream = std::make_shared<priv::ResourceStream>(filename);
auto font = loadFromStream(*stream);
if (font)
font->m_stream = std::move(stream);
return font;
#endif
}
////////////////////////////////////////////////////////////
bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
std::optional<Font> Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
{
// Cleanup the previous resources
cleanup();
auto fontHandles = std::make_shared<FontHandles>();
// Initialize FreeType
@ -197,7 +195,7 @@ bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
if (FT_Init_FreeType(&fontHandles->library) != 0)
{
err() << "Failed to load font from memory (failed to initialize FreeType)" << std::endl;
return false;
return std::nullopt;
}
// Load the new font face from the specified file
@ -209,7 +207,7 @@ bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
&face) != 0)
{
err() << "Failed to load font from memory (failed to create the font face)" << std::endl;
return false;
return std::nullopt;
}
fontHandles->face = face;
@ -217,32 +215,23 @@ bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
if (FT_Stroker_New(fontHandles->library, &fontHandles->stroker) != 0)
{
err() << "Failed to load font from memory (failed to create the stroker)" << std::endl;
return false;
return std::nullopt;
}
// Select the Unicode character map
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
{
err() << "Failed to load font from memory (failed to set the Unicode character set)" << std::endl;
return false;
return std::nullopt;
}
// Store the loaded font handles
m_fontHandles = std::move(fontHandles);
// Store the font information
m_info.family = face->family_name ? face->family_name : std::string();
return true;
return Font(std::move(fontHandles), std::string(face->family_name ? face->family_name : ""));
}
////////////////////////////////////////////////////////////
bool Font::loadFromStream(InputStream& stream)
std::optional<Font> Font::loadFromStream(InputStream& stream)
{
// Cleanup the previous resources
cleanup();
auto fontHandles = std::make_shared<FontHandles>();
// Initialize FreeType
@ -251,14 +240,14 @@ bool Font::loadFromStream(InputStream& stream)
if (FT_Init_FreeType(&fontHandles->library) != 0)
{
err() << "Failed to load font from stream (failed to initialize FreeType)" << std::endl;
return false;
return std::nullopt;
}
// Make sure that the stream's reading position is at the beginning
if (stream.seek(0) == -1)
{
err() << "Failed to seek font stream" << std::endl;
return false;
return std::nullopt;
}
// Prepare a wrapper for our stream, that we'll pass to FreeType callbacks
@ -280,7 +269,7 @@ bool Font::loadFromStream(InputStream& stream)
if (FT_Open_Face(fontHandles->library, &args, 0, &face) != 0)
{
err() << "Failed to load font from stream (failed to create the font face)" << std::endl;
return false;
return std::nullopt;
}
fontHandles->face = face;
@ -288,23 +277,17 @@ bool Font::loadFromStream(InputStream& stream)
if (FT_Stroker_New(fontHandles->library, &fontHandles->stroker) != 0)
{
err() << "Failed to load font from stream (failed to create the stroker)" << std::endl;
return false;
return std::nullopt;
}
// Select the Unicode character map
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
{
err() << "Failed to load font from stream (failed to set the Unicode character set)" << std::endl;
return false;
return std::nullopt;
}
// Store the loaded font handles
m_fontHandles = std::move(fontHandles);
// Store the font information
m_info.family = face->family_name ? face->family_name : std::string();
return true;
return Font(std::move(fontHandles), std::string(face->family_name ? face->family_name : ""));
}
@ -474,18 +457,6 @@ bool Font::isSmooth() const
}
////////////////////////////////////////////////////////////
void Font::cleanup()
{
// Drop ownership of shared FreeType pointers
m_fontHandles.reset();
// Reset members
m_pages.clear();
std::vector<std::uint8_t>().swap(m_pixelBuffer);
}
////////////////////////////////////////////////////////////
Font::Page& Font::loadPage(unsigned int characterSize) const
{

View File

@ -15,35 +15,23 @@ TEST_CASE("[Graphics] sf::Font", runDisplayTests())
{
SECTION("Type traits")
{
STATIC_CHECK(!std::is_default_constructible_v<sf::Font>);
STATIC_CHECK(std::is_copy_constructible_v<sf::Font>);
STATIC_CHECK(std::is_copy_assignable_v<sf::Font>);
STATIC_CHECK(std::is_move_constructible_v<sf::Font>);
STATIC_CHECK(std::is_move_assignable_v<sf::Font>);
}
SECTION("Construction")
{
const sf::Font font;
CHECK(font.getInfo().family.empty());
CHECK(!font.hasGlyph(0));
CHECK(font.getLineSpacing(0) == 0);
CHECK(font.getUnderlinePosition(0) == 0);
CHECK(font.getUnderlineThickness(0) == 0);
CHECK(font.isSmooth());
}
SECTION("loadFromFile()")
{
sf::Font font;
SECTION("Invalid filename")
{
CHECK(!font.loadFromFile("does/not/exist.ttf"));
CHECK(!sf::Font::loadFromFile("does/not/exist.ttf"));
}
SECTION("Successful load")
{
REQUIRE(font.loadFromFile("Graphics/tuffy.ttf"));
const auto font = sf::Font::loadFromFile("Graphics/tuffy.ttf").value();
CHECK(font.getInfo().family == "Tuffy");
const auto& glyph = font.getGlyph(0x45, 16, false);
CHECK(glyph.advance == 9);
@ -70,19 +58,17 @@ TEST_CASE("[Graphics] sf::Font", runDisplayTests())
SECTION("loadFromMemory()")
{
sf::Font font;
SECTION("Invalid data and size")
{
CHECK(!font.loadFromMemory(nullptr, 1));
CHECK(!sf::Font::loadFromMemory(nullptr, 1));
const std::byte testByte{0xCD};
CHECK(!font.loadFromMemory(&testByte, 0));
CHECK(!sf::Font::loadFromMemory(&testByte, 0));
}
SECTION("Successful load")
{
const auto memory = loadIntoMemory("Graphics/tuffy.ttf");
REQUIRE(font.loadFromMemory(memory.data(), memory.size()));
const auto font = sf::Font::loadFromMemory(memory.data(), memory.size()).value();
CHECK(font.getInfo().family == "Tuffy");
const auto& glyph = font.getGlyph(0x45, 16, false);
CHECK(glyph.advance == 9);
@ -109,18 +95,17 @@ TEST_CASE("[Graphics] sf::Font", runDisplayTests())
SECTION("loadFromStream()")
{
sf::Font font;
sf::FileInputStream stream;
SECTION("Invalid stream")
{
CHECK(!font.loadFromStream(stream));
CHECK(!sf::Font::loadFromStream(stream));
}
SECTION("Successful load")
{
REQUIRE(stream.open("Graphics/tuffy.ttf"));
REQUIRE(font.loadFromStream(stream));
const auto font = sf::Font::loadFromStream(stream).value();
CHECK(font.getInfo().family == "Tuffy");
const auto& glyph = font.getGlyph(0x45, 16, false);
CHECK(glyph.advance == 9);
@ -147,8 +132,7 @@ TEST_CASE("[Graphics] sf::Font", runDisplayTests())
SECTION("Set/get smooth")
{
sf::Font font;
REQUIRE(font.loadFromFile("Graphics/tuffy.ttf"));
auto font = sf::Font::loadFromFile("Graphics/tuffy.ttf").value();
font.setSmooth(false);
CHECK(!font.isSmooth());
}

View File

@ -20,29 +20,10 @@ TEST_CASE("[Graphics] sf::Text", runDisplayTests())
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::Text>);
}
sf::Font font;
REQUIRE(font.loadFromFile("Graphics/tuffy.ttf"));
const auto font = sf::Font::loadFromFile("Graphics/tuffy.ttf").value();
SECTION("Construction")
{
SECTION("Font constructor with empty font")
{
const sf::Font emptyFont;
const sf::Text text(emptyFont);
CHECK(text.getString() == "");
CHECK(&text.getFont() == &emptyFont);
CHECK(text.getCharacterSize() == 30);
CHECK(text.getLetterSpacing() == 1.f);
CHECK(text.getLineSpacing() == 1.f);
CHECK(text.getStyle() == sf::Text::Regular);
CHECK(text.getFillColor() == sf::Color::White);
CHECK(text.getOutlineColor() == sf::Color::Black);
CHECK(text.getOutlineThickness() == 0);
CHECK(text.findCharacterPos(0) == sf::Vector2f());
CHECK(text.getLocalBounds() == sf::FloatRect());
CHECK(text.getGlobalBounds() == sf::FloatRect());
}
SECTION("Font constructor")
{
const sf::Text text(font);
@ -104,8 +85,8 @@ TEST_CASE("[Graphics] sf::Text", runDisplayTests())
SECTION("Set/get font")
{
sf::Text text(font);
const sf::Font otherFont;
sf::Text text(font);
const auto otherFont = sf::Font::loadFromFile("Graphics/tuffy.ttf").value();
text.setFont(otherFont);
CHECK(&text.getFont() == &otherFont);
}

View File

@ -14,7 +14,7 @@ int main()
// Graphics
[[maybe_unused]] const sf::Color color;
[[maybe_unused]] const sf::Font font;
[[maybe_unused]] const sf::IntRect rect;
[[maybe_unused]] const sf::RenderWindow renderWindow;
[[maybe_unused]] const sf::RectangleShape rectangleShape;
[[maybe_unused]] const sf::Vertex vertex;

View File

@ -42,12 +42,8 @@ int main()
sf::Sprite sprite(texture);
// Create a graphical text to display
sf::Font font;
if (!font.loadFromFile(resourcePath() / "tuffy.ttf"))
{
return EXIT_FAILURE;
}
sf::Text text(font, "Hello SFML", 50);
const auto font = sf::Font::loadFromFile(resourcePath() / "tuffy.ttf").value();
sf::Text text(font, "Hello SFML", 50);
text.setFillColor(sf::Color::Black);
// Load a music to play

View File

@ -40,12 +40,8 @@ int main()
sf::Sprite sprite(texture);
// Create a graphical text to display
sf::Font font;
if (!font.loadFromFile("tuffy.ttf"))
{
return EXIT_FAILURE;
}
sf::Text text(font, "Hello SFML", 50);
const auto font = sf::Font::loadFromFile("tuffy.ttf").value();
sf::Text text(font, "Hello SFML", 50);
text.setFillColor(sf::Color::Black);
// Load a music to play