Remove default empty state of sf::FileInputStream

This commit is contained in:
Chris Thrasher 2024-06-09 22:02:54 -05:00
parent 37ac80dbe5
commit 304a7c1d69
16 changed files with 198 additions and 260 deletions

View File

@ -923,18 +923,17 @@ public:
// Use the vertex shader SPIR-V code to create a vertex shader module // Use the vertex shader SPIR-V code to create a vertex shader module
{ {
sf::FileInputStream file; auto file = sf::FileInputStream::open("resources/shader.vert.spv");
if (!file)
if (!file.open("resources/shader.vert.spv"))
{ {
vulkanAvailable = false; vulkanAvailable = false;
return; return;
} }
const auto fileSize = file.getSize().value(); const auto fileSize = file->getSize().value();
std::vector<std::uint32_t> buffer(fileSize / sizeof(std::uint32_t)); std::vector<std::uint32_t> buffer(fileSize / sizeof(std::uint32_t));
if (file.read(buffer.data(), fileSize) != file.getSize()) if (file->read(buffer.data(), fileSize) != file->getSize())
{ {
vulkanAvailable = false; vulkanAvailable = false;
return; return;
@ -952,18 +951,17 @@ public:
// Use the fragment shader SPIR-V code to create a fragment shader module // Use the fragment shader SPIR-V code to create a fragment shader module
{ {
sf::FileInputStream file; auto file = sf::FileInputStream::open("resources/shader.frag.spv");
if (!file)
if (!file.open("resources/shader.frag.spv"))
{ {
vulkanAvailable = false; vulkanAvailable = false;
return; return;
} }
const auto fileSize = file.getSize().value(); const auto fileSize = file->getSize().value();
std::vector<std::uint32_t> buffer(fileSize / sizeof(std::uint32_t)); std::vector<std::uint32_t> buffer(fileSize / sizeof(std::uint32_t));
if (file.read(buffer.data(), fileSize) != file.getSize()) if (file->read(buffer.data(), fileSize) != file->getSize())
{ {
vulkanAvailable = false; vulkanAvailable = false;
return; return;

View File

@ -56,12 +56,6 @@ namespace sf
class SFML_SYSTEM_API FileInputStream : public InputStream class SFML_SYSTEM_API FileInputStream : public InputStream
{ {
public: public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
FileInputStream();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Default destructor /// \brief Default destructor
/// ///
@ -97,10 +91,10 @@ public:
/// ///
/// \param filename Name of the file to open /// \param filename Name of the file to open
/// ///
/// \return True on success, false on error /// \return File input stream on success, `std::nullopt` on error
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
[[nodiscard]] bool open(const std::filesystem::path& filename); [[nodiscard]] static std::optional<FileInputStream> open(const std::filesystem::path& filename);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Read data from the stream /// \brief Read data from the stream
@ -143,12 +137,6 @@ public:
std::optional<std::size_t> getSize() override; std::optional<std::size_t> getSize() override;
private: private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
#ifdef SFML_SYSTEM_ANDROID
std::unique_ptr<priv::ResourceStream> m_androidFile;
#endif
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Deleter for stdio file stream that closes the file stream /// \brief Deleter for stdio file stream that closes the file stream
/// ///
@ -158,6 +146,27 @@ private:
void operator()(std::FILE* file); void operator()(std::FILE* file);
}; };
////////////////////////////////////////////////////////////
/// \brief Construct from file
///
////////////////////////////////////////////////////////////
explicit FileInputStream(std::unique_ptr<std::FILE, FileCloser>&& file);
#ifdef SFML_SYSTEM_ANDROID
////////////////////////////////////////////////////////////
/// \brief Construct from resource stream
///
////////////////////////////////////////////////////////////
explicit FileInputStream(std::unique_ptr<priv::ResourceStream>&& androidFile);
#endif
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
#ifdef SFML_SYSTEM_ANDROID
std::unique_ptr<priv::ResourceStream> m_androidFile;
#endif
std::unique_ptr<std::FILE, FileCloser> m_file; //!< stdio file stream std::unique_ptr<std::FILE, FileCloser> m_file; //!< stdio file stream
}; };
@ -188,9 +197,9 @@ private:
/// \code /// \code
/// void process(InputStream& stream); /// void process(InputStream& stream);
/// ///
/// FileInputStream stream; /// std::optional stream = sf::FileInputStream::open("some_file.dat");
/// if (stream.open("some_file.dat")) /// if (stream)
/// process(stream); /// process(*stream);
/// \endcode /// \endcode
/// ///
/// InputStream, MemoryInputStream /// InputStream, MemoryInputStream

View File

@ -77,11 +77,9 @@ std::optional<InputSoundFile> InputSoundFile::openFromFile(const std::filesystem
return std::nullopt; return std::nullopt;
} }
// Wrap the file into a stream // Open the file
auto file = std::make_unique<FileInputStream>(); auto fileInputStream = FileInputStream::open(filename);
if (!fileInputStream)
// Open it
if (!file->open(filename))
{ {
err() << "Failed to open input sound file from file (couldn't open file input stream)\n" err() << "Failed to open input sound file from file (couldn't open file input stream)\n"
<< formatDebugPathInfo(filename) << std::endl; << formatDebugPathInfo(filename) << std::endl;
@ -89,6 +87,9 @@ std::optional<InputSoundFile> InputSoundFile::openFromFile(const std::filesystem
return std::nullopt; return std::nullopt;
} }
// Wrap the file into a stream
auto file = std::make_unique<FileInputStream>(std::move(*fileInputStream));
// Pass the stream to the reader // Pass the stream to the reader
auto info = reader->open(*file); auto info = reader->open(*file);
if (!info) if (!info)

View File

@ -48,8 +48,8 @@ namespace sf
std::unique_ptr<SoundFileReader> SoundFileFactory::createReaderFromFilename(const std::filesystem::path& filename) std::unique_ptr<SoundFileReader> SoundFileFactory::createReaderFromFilename(const std::filesystem::path& filename)
{ {
// Wrap the input file into a file stream // Wrap the input file into a file stream
FileInputStream stream; auto stream = FileInputStream::open(filename);
if (!stream.open(filename)) if (!stream)
{ {
err() << "Failed to open sound file (couldn't open stream)\n" << formatDebugPathInfo(filename) << std::endl; err() << "Failed to open sound file (couldn't open stream)\n" << formatDebugPathInfo(filename) << std::endl;
return nullptr; return nullptr;
@ -58,13 +58,13 @@ std::unique_ptr<SoundFileReader> SoundFileFactory::createReaderFromFilename(cons
// Test the filename in all the registered factories // Test the filename in all the registered factories
for (const auto& [fpCreate, fpCheck] : getReaderFactoryMap()) for (const auto& [fpCreate, fpCheck] : getReaderFactoryMap())
{ {
if (!stream.seek(0).has_value()) if (!stream->seek(0).has_value())
{ {
err() << "Failed to seek sound stream" << std::endl; err() << "Failed to seek sound stream" << std::endl;
return nullptr; return nullptr;
} }
if (fpCheck(stream)) if (fpCheck(*stream))
return fpCreate(); return fpCreate();
} }

View File

@ -32,6 +32,7 @@
#endif #endif
#include <memory> #include <memory>
#include <cassert>
#include <cstddef> #include <cstddef>
namespace sf namespace sf
@ -43,10 +44,6 @@ void FileInputStream::FileCloser::operator()(std::FILE* file)
} }
////////////////////////////////////////////////////////////
FileInputStream::FileInputStream() = default;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
FileInputStream::~FileInputStream() = default; FileInputStream::~FileInputStream() = default;
@ -60,21 +57,24 @@ FileInputStream& FileInputStream::operator=(FileInputStream&&) noexcept = defaul
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool FileInputStream::open(const std::filesystem::path& filename) std::optional<FileInputStream> FileInputStream::open(const std::filesystem::path& filename)
{ {
#ifdef SFML_SYSTEM_ANDROID #ifdef SFML_SYSTEM_ANDROID
if (priv::getActivityStatesPtr() != nullptr) if (priv::getActivityStatesPtr() != nullptr)
{ {
m_androidFile = std::make_unique<priv::ResourceStream>(filename); auto androidFile = std::make_unique<priv::ResourceStream>(filename);
return m_androidFile->tell().has_value(); if (androidFile->tell().has_value())
return FileInputStream(std::move(androidFile));
return std::nullopt;
} }
#endif #endif
#ifdef SFML_SYSTEM_WINDOWS #ifdef SFML_SYSTEM_WINDOWS
m_file.reset(_wfopen(filename.c_str(), L"rb")); if (auto file = std::unique_ptr<std::FILE, FileCloser>(_wfopen(filename.c_str(), L"rb")))
#else #else
m_file.reset(std::fopen(filename.c_str(), "rb")); if (auto file = std::unique_ptr<std::FILE, FileCloser>(std::fopen(filename.c_str(), "rb")))
#endif #endif
return m_file != nullptr; return FileInputStream(std::move(file));
return std::nullopt;
} }
@ -84,13 +84,11 @@ std::optional<std::size_t> FileInputStream::read(void* data, std::size_t size)
#ifdef SFML_SYSTEM_ANDROID #ifdef SFML_SYSTEM_ANDROID
if (priv::getActivityStatesPtr() != nullptr) if (priv::getActivityStatesPtr() != nullptr)
{ {
if (!m_androidFile) assert(m_androidFile);
return std::nullopt;
return m_androidFile->read(data, size); return m_androidFile->read(data, size);
} }
#endif #endif
if (!m_file) assert(m_file);
return std::nullopt;
return std::fread(data, 1, size, m_file.get()); return std::fread(data, 1, size, m_file.get());
} }
@ -101,13 +99,11 @@ std::optional<std::size_t> FileInputStream::seek(std::size_t position)
#ifdef SFML_SYSTEM_ANDROID #ifdef SFML_SYSTEM_ANDROID
if (priv::getActivityStatesPtr() != nullptr) if (priv::getActivityStatesPtr() != nullptr)
{ {
if (!m_androidFile) assert(m_androidFile);
return std::nullopt;
return m_androidFile->seek(position); return m_androidFile->seek(position);
} }
#endif #endif
if (!m_file) assert(m_file);
return std::nullopt;
if (std::fseek(m_file.get(), static_cast<long>(position), SEEK_SET)) if (std::fseek(m_file.get(), static_cast<long>(position), SEEK_SET))
return std::nullopt; return std::nullopt;
@ -121,13 +117,11 @@ std::optional<std::size_t> FileInputStream::tell()
#ifdef SFML_SYSTEM_ANDROID #ifdef SFML_SYSTEM_ANDROID
if (priv::getActivityStatesPtr() != nullptr) if (priv::getActivityStatesPtr() != nullptr)
{ {
if (!m_androidFile) assert(m_androidFile);
return std::nullopt;
return m_androidFile->tell(); return m_androidFile->tell();
} }
#endif #endif
if (!m_file) assert(m_file);
return std::nullopt;
const auto position = std::ftell(m_file.get()); const auto position = std::ftell(m_file.get());
return position < 0 ? std::nullopt : std::optional<std::size_t>(position); return position < 0 ? std::nullopt : std::optional<std::size_t>(position);
} }
@ -139,13 +133,11 @@ std::optional<std::size_t> FileInputStream::getSize()
#ifdef SFML_SYSTEM_ANDROID #ifdef SFML_SYSTEM_ANDROID
if (priv::getActivityStatesPtr() != nullptr) if (priv::getActivityStatesPtr() != nullptr)
{ {
if (!m_androidFile) assert(m_androidFile);
return std::nullopt;
return m_androidFile->getSize(); return m_androidFile->getSize();
} }
#endif #endif
if (!m_file) assert(m_file);
return std::nullopt;
const auto position = tell().value(); const auto position = tell().value();
std::fseek(m_file.get(), 0, SEEK_END); std::fseek(m_file.get(), 0, SEEK_END);
const std::optional size = tell(); const std::optional size = tell();
@ -156,4 +148,19 @@ std::optional<std::size_t> FileInputStream::getSize()
return size; return size;
} }
////////////////////////////////////////////////////////////
FileInputStream::FileInputStream(std::unique_ptr<std::FILE, FileCloser>&& file) : m_file(std::move(file))
{
}
////////////////////////////////////////////////////////////
#ifdef SFML_SYSTEM_ANDROID
FileInputStream::FileInputStream(std::unique_ptr<priv::ResourceStream>&& androidFile) :
m_androidFile(std::move(androidFile))
{
}
#endif
} // namespace sf } // namespace sf

View File

@ -91,62 +91,52 @@ TEST_CASE("[Audio] sf::InputSoundFile")
SECTION("openFromStream()") SECTION("openFromStream()")
{ {
sf::FileInputStream stream; SECTION("flac")
SECTION("Invalid stream")
{ {
CHECK(!sf::InputSoundFile::openFromStream(stream)); auto stream = sf::FileInputStream::open("Audio/ding.flac").value();
const auto inputSoundFile = sf::InputSoundFile::openFromStream(stream).value();
CHECK(inputSoundFile.getSampleCount() == 87'798);
CHECK(inputSoundFile.getChannelCount() == 1);
CHECK(inputSoundFile.getSampleRate() == 44'100);
CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884));
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
CHECK(inputSoundFile.getSampleOffset() == 0);
} }
SECTION("Valid stream") SECTION("mp3")
{ {
SECTION("flac") auto stream = sf::FileInputStream::open("Audio/ding.mp3").value();
{ const auto inputSoundFile = sf::InputSoundFile::openFromStream(stream).value();
REQUIRE(stream.open("Audio/ding.flac")); CHECK(inputSoundFile.getSampleCount() == 87'798);
const auto inputSoundFile = sf::InputSoundFile::openFromStream(stream).value(); CHECK(inputSoundFile.getChannelCount() == 1);
CHECK(inputSoundFile.getSampleCount() == 87'798); CHECK(inputSoundFile.getSampleRate() == 44'100);
CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884));
CHECK(inputSoundFile.getSampleRate() == 44'100); CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884)); CHECK(inputSoundFile.getSampleOffset() == 0);
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); }
CHECK(inputSoundFile.getSampleOffset() == 0);
}
SECTION("mp3") SECTION("ogg")
{ {
REQUIRE(stream.open("Audio/ding.mp3")); auto stream = sf::FileInputStream::open("Audio/doodle_pop.ogg").value();
const auto inputSoundFile = sf::InputSoundFile::openFromStream(stream).value(); const auto inputSoundFile = sf::InputSoundFile::openFromStream(stream).value();
CHECK(inputSoundFile.getSampleCount() == 87'798); CHECK(inputSoundFile.getSampleCount() == 2'116'992);
CHECK(inputSoundFile.getChannelCount() == 1); CHECK(inputSoundFile.getChannelCount() == 2);
CHECK(inputSoundFile.getSampleRate() == 44'100); CHECK(inputSoundFile.getSampleRate() == 44'100);
CHECK(inputSoundFile.getDuration() == sf::microseconds(1'990'884)); CHECK(inputSoundFile.getDuration() == sf::microseconds(24'002'176));
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
CHECK(inputSoundFile.getSampleOffset() == 0); CHECK(inputSoundFile.getSampleOffset() == 0);
} }
SECTION("ogg") SECTION("wav")
{ {
REQUIRE(stream.open("Audio/doodle_pop.ogg")); auto stream = sf::FileInputStream::open("Audio/killdeer.wav").value();
const auto inputSoundFile = sf::InputSoundFile::openFromStream(stream).value(); const auto inputSoundFile = sf::InputSoundFile::openFromStream(stream).value();
CHECK(inputSoundFile.getSampleCount() == 2'116'992); CHECK(inputSoundFile.getSampleCount() == 112'941);
CHECK(inputSoundFile.getChannelCount() == 2); CHECK(inputSoundFile.getChannelCount() == 1);
CHECK(inputSoundFile.getSampleRate() == 44'100); CHECK(inputSoundFile.getSampleRate() == 22'050);
CHECK(inputSoundFile.getDuration() == sf::microseconds(24'002'176)); CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040));
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero); CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
CHECK(inputSoundFile.getSampleOffset() == 0); CHECK(inputSoundFile.getSampleOffset() == 0);
}
SECTION("wav")
{
REQUIRE(stream.open("Audio/killdeer.wav"));
const auto inputSoundFile = sf::InputSoundFile::openFromStream(stream).value();
CHECK(inputSoundFile.getSampleCount() == 112'941);
CHECK(inputSoundFile.getChannelCount() == 1);
CHECK(inputSoundFile.getSampleRate() == 22'050);
CHECK(inputSoundFile.getDuration() == sf::microseconds(5'122'040));
CHECK(inputSoundFile.getTimeOffset() == sf::Time::Zero);
CHECK(inputSoundFile.getSampleOffset() == 0);
}
} }
} }

View File

@ -82,28 +82,17 @@ TEST_CASE("[Audio] sf::Music", runAudioDeviceTests())
SECTION("openFromStream()") SECTION("openFromStream()")
{ {
sf::FileInputStream stream; auto stream = sf::FileInputStream::open("Audio/doodle_pop.ogg").value();
const auto music = sf::Music::openFromStream(stream).value();
SECTION("Invalid stream") CHECK(music.getDuration() == sf::microseconds(24002176));
{ const auto [offset, length] = music.getLoopPoints();
CHECK(!sf::Music::openFromStream(stream)); CHECK(offset == sf::Time::Zero);
} CHECK(length == sf::microseconds(24002176));
CHECK(music.getChannelCount() == 2);
SECTION("Valid stream") CHECK(music.getSampleRate() == 44100);
{ CHECK(music.getStatus() == sf::Music::Status::Stopped);
REQUIRE(stream.open("Audio/doodle_pop.ogg")); CHECK(music.getPlayingOffset() == sf::Time::Zero);
CHECK(!music.getLoop());
const auto music = sf::Music::openFromStream(stream).value();
CHECK(music.getDuration() == sf::microseconds(24002176));
const auto [offset, length] = music.getLoopPoints();
CHECK(offset == sf::Time::Zero);
CHECK(length == sf::microseconds(24002176));
CHECK(music.getChannelCount() == 2);
CHECK(music.getSampleRate() == 44100);
CHECK(music.getStatus() == sf::Music::Status::Stopped);
CHECK(music.getPlayingOffset() == sf::Time::Zero);
CHECK(!music.getLoop());
}
} }
SECTION("play/pause/stop") SECTION("play/pause/stop")

View File

@ -89,23 +89,13 @@ TEST_CASE("[Audio] sf::SoundBuffer", runAudioDeviceTests())
SECTION("loadFromStream()") SECTION("loadFromStream()")
{ {
sf::FileInputStream stream; auto stream = sf::FileInputStream::open("Audio/ding.flac").value();
const auto soundBuffer = sf::SoundBuffer::loadFromStream(stream).value();
SECTION("Invalid stream") CHECK(soundBuffer.getSamples() != nullptr);
{ CHECK(soundBuffer.getSampleCount() == 87798);
CHECK(!sf::SoundBuffer::loadFromStream(stream)); CHECK(soundBuffer.getSampleRate() == 44100);
} CHECK(soundBuffer.getChannelCount() == 1);
CHECK(soundBuffer.getDuration() == sf::microseconds(1990884));
SECTION("Valid stream")
{
REQUIRE(stream.open("Audio/ding.flac"));
const auto soundBuffer = sf::SoundBuffer::loadFromStream(stream).value();
CHECK(soundBuffer.getSamples() != nullptr);
CHECK(soundBuffer.getSampleCount() == 87798);
CHECK(soundBuffer.getSampleRate() == 44100);
CHECK(soundBuffer.getChannelCount() == 1);
CHECK(soundBuffer.getDuration() == sf::microseconds(1990884));
}
} }
SECTION("saveToFile()") SECTION("saveToFile()")

View File

@ -110,37 +110,30 @@ TEST_CASE("[Audio] sf::SoundFileFactory")
SECTION("createReaderFromStream()") SECTION("createReaderFromStream()")
{ {
sf::FileInputStream stream; std::optional<sf::FileInputStream> stream;
SECTION("Invalid stream") SECTION("flac")
{ {
CHECK(!sf::SoundFileFactory::createReaderFromStream(stream)); stream = sf::FileInputStream::open("Audio/ding.flac");
} }
SECTION("Valid file") SECTION("mp3")
{ {
SECTION("flac") stream = sf::FileInputStream::open("Audio/ding.mp3");
{
REQUIRE(stream.open("Audio/ding.flac"));
}
SECTION("mp3")
{
REQUIRE(stream.open("Audio/ding.mp3"));
}
SECTION("ogg")
{
REQUIRE(stream.open("Audio/doodle_pop.ogg"));
}
SECTION("wav")
{
REQUIRE(stream.open("Audio/killdeer.wav"));
}
CHECK(sf::SoundFileFactory::createReaderFromStream(stream));
} }
SECTION("ogg")
{
stream = sf::FileInputStream::open("Audio/doodle_pop.ogg");
}
SECTION("wav")
{
stream = sf::FileInputStream::open("Audio/killdeer.wav");
}
REQUIRE(stream);
CHECK(sf::SoundFileFactory::createReaderFromStream(*stream));
} }
SECTION("createWriterFromFilename()") SECTION("createWriterFromFilename()")

View File

@ -95,39 +95,29 @@ TEST_CASE("[Graphics] sf::Font", runDisplayTests())
SECTION("loadFromStream()") SECTION("loadFromStream()")
{ {
sf::FileInputStream stream; auto stream = sf::FileInputStream::open("Graphics/tuffy.ttf").value();
const auto font = sf::Font::loadFromStream(stream).value();
SECTION("Invalid stream") CHECK(font.getInfo().family == "Tuffy");
{ const auto& glyph = font.getGlyph(0x45, 16, false);
CHECK(!sf::Font::loadFromStream(stream)); CHECK(glyph.advance == 9);
} CHECK(glyph.lsbDelta == 9);
CHECK(glyph.rsbDelta == 16);
SECTION("Successful load") CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12}));
{ CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12}));
REQUIRE(stream.open("Graphics/tuffy.ttf")); CHECK(font.hasGlyph(0x41));
const auto font = sf::Font::loadFromStream(stream).value(); CHECK(font.hasGlyph(0xC0));
CHECK(font.getInfo().family == "Tuffy"); CHECK(font.getKerning(0x41, 0x42, 12) == -1);
const auto& glyph = font.getGlyph(0x45, 16, false); CHECK(font.getKerning(0x43, 0x44, 24, true) == 0);
CHECK(glyph.advance == 9); CHECK(font.getLineSpacing(24) == 30);
CHECK(glyph.lsbDelta == 9); CHECK(font.getUnderlinePosition(36) == Approx(2.20312f));
CHECK(glyph.rsbDelta == 16); CHECK(font.getUnderlineThickness(48) == Approx(1.17188f));
CHECK(glyph.bounds == sf::FloatRect({0, -12}, {8, 12})); const auto& texture = font.getTexture(10);
CHECK(glyph.textureRect == sf::IntRect({2, 5}, {8, 12})); CHECK(texture.getSize() == sf::Vector2u(128, 128));
CHECK(font.hasGlyph(0x41)); CHECK(texture.isSmooth());
CHECK(font.hasGlyph(0xC0)); CHECK(!texture.isSrgb());
CHECK(font.getKerning(0x41, 0x42, 12) == -1); CHECK(!texture.isRepeated());
CHECK(font.getKerning(0x43, 0x44, 24, true) == 0); CHECK(texture.getNativeHandle() != 0);
CHECK(font.getLineSpacing(24) == 30); CHECK(font.isSmooth());
CHECK(font.getUnderlinePosition(36) == Approx(2.20312f));
CHECK(font.getUnderlineThickness(48) == Approx(1.17188f));
const auto& texture = font.getTexture(10);
CHECK(texture.getSize() == sf::Vector2u(128, 128));
CHECK(texture.isSmooth());
CHECK(!texture.isSrgb());
CHECK(!texture.isRepeated());
CHECK(texture.getNativeHandle() != 0);
CHECK(font.isSmooth());
}
} }
SECTION("Set/get smooth") SECTION("Set/get smooth")

View File

@ -178,22 +178,12 @@ TEST_CASE("[Graphics] sf::Image")
SECTION("loadFromStream()") SECTION("loadFromStream()")
{ {
sf::FileInputStream stream; auto stream = sf::FileInputStream::open("Graphics/sfml-logo-big.png").value();
const auto image = sf::Image::loadFromStream(stream).value();
SECTION("Invalid stream") CHECK(image.getSize() == sf::Vector2u(1001, 304));
{ CHECK(image.getPixelsPtr() != nullptr);
CHECK(!sf::Image::loadFromStream(stream)); CHECK(image.getPixel({0, 0}) == sf::Color(255, 255, 255, 0));
} CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
SECTION("Successful load")
{
CHECK(stream.open("Graphics/sfml-logo-big.png"));
const auto image = sf::Image::loadFromStream(stream).value();
CHECK(image.getSize() == sf::Vector2u(1001, 304));
CHECK(image.getPixelsPtr() != nullptr);
CHECK(image.getPixel({0, 0}) == sf::Color(255, 255, 255, 0));
CHECK(image.getPixel({200, 150}) == sf::Color(144, 208, 62));
}
} }
SECTION("saveToFile()") SECTION("saveToFile()")

View File

@ -243,16 +243,11 @@ TEST_CASE("[Graphics] sf::Shader", skipShaderFullTests())
SECTION("loadFromStream()") SECTION("loadFromStream()")
{ {
sf::FileInputStream vertexShaderStream; auto vertexShaderStream = sf::FileInputStream::open("Graphics/shader.vert").value();
REQUIRE(vertexShaderStream.open("Graphics/shader.vert")); auto fragmentShaderStream = sf::FileInputStream::open("Graphics/shader.frag").value();
auto geometryShaderStream = sf::FileInputStream::open("Graphics/shader.geom").value();
sf::FileInputStream fragmentShaderStream; auto emptyStream = sf::FileInputStream::open("Graphics/invalid_shader.vert").value();
REQUIRE(fragmentShaderStream.open("Graphics/shader.frag"));
sf::FileInputStream geometryShaderStream;
REQUIRE(geometryShaderStream.open("Graphics/shader.geom"));
sf::FileInputStream emptyStream;
SECTION("One shader") SECTION("One shader")
{ {

View File

@ -95,8 +95,7 @@ TEST_CASE("[Graphics] sf::Texture", runDisplayTests())
SECTION("loadFromStream()") SECTION("loadFromStream()")
{ {
sf::FileInputStream stream; auto stream = sf::FileInputStream::open("Graphics/sfml-logo-big.png").value();
REQUIRE(stream.open("Graphics/sfml-logo-big.png"));
const auto texture = sf::Texture::loadFromStream(stream).value(); const auto texture = sf::Texture::loadFromStream(stream).value();
CHECK(texture.getSize() == sf::Vector2u(1001, 304)); CHECK(texture.getSize() == sf::Vector2u(1001, 304));
CHECK(!texture.isSmooth()); CHECK(!texture.isSmooth());

View File

View File

@ -66,21 +66,13 @@ TEST_CASE("[System] sf::FileInputStream")
SECTION("Type traits") SECTION("Type traits")
{ {
STATIC_CHECK(!std::is_default_constructible_v<sf::FileInputStream>);
STATIC_CHECK(!std::is_copy_constructible_v<sf::FileInputStream>); STATIC_CHECK(!std::is_copy_constructible_v<sf::FileInputStream>);
STATIC_CHECK(!std::is_copy_assignable_v<sf::FileInputStream>); STATIC_CHECK(!std::is_copy_assignable_v<sf::FileInputStream>);
STATIC_CHECK(std::is_nothrow_move_constructible_v<sf::FileInputStream>); STATIC_CHECK(std::is_nothrow_move_constructible_v<sf::FileInputStream>);
STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::FileInputStream>); STATIC_CHECK(std::is_nothrow_move_assignable_v<sf::FileInputStream>);
} }
SECTION("Default constructor")
{
sf::FileInputStream fileInputStream;
CHECK(fileInputStream.read(nullptr, 0) == std::nullopt);
CHECK(fileInputStream.seek(0) == std::nullopt);
CHECK(fileInputStream.tell() == std::nullopt);
CHECK(fileInputStream.getSize() == std::nullopt);
}
const TemporaryFile temporaryFile("Hello world"); const TemporaryFile temporaryFile("Hello world");
char buffer[32]; char buffer[32];
@ -88,10 +80,8 @@ TEST_CASE("[System] sf::FileInputStream")
{ {
SECTION("Move constructor") SECTION("Move constructor")
{ {
sf::FileInputStream movedFileInputStream; auto movedFileInputStream = sf::FileInputStream::open(temporaryFile.getPath()).value();
REQUIRE(movedFileInputStream.open(temporaryFile.getPath())); sf::FileInputStream fileInputStream = std::move(movedFileInputStream);
sf::FileInputStream fileInputStream = std::move(movedFileInputStream);
CHECK(fileInputStream.read(buffer, 6) == 6); CHECK(fileInputStream.read(buffer, 6) == 6);
CHECK(fileInputStream.tell() == 6); CHECK(fileInputStream.tell() == 6);
CHECK(fileInputStream.getSize() == 11); CHECK(fileInputStream.getSize() == 11);
@ -100,11 +90,10 @@ TEST_CASE("[System] sf::FileInputStream")
SECTION("Move assignment") SECTION("Move assignment")
{ {
sf::FileInputStream movedFileInputStream; auto movedFileInputStream = sf::FileInputStream::open(temporaryFile.getPath()).value();
REQUIRE(movedFileInputStream.open(temporaryFile.getPath())); const TemporaryFile temporaryFile2("Hello world the sequel");
auto fileInputStream = sf::FileInputStream::open(temporaryFile2.getPath()).value();
sf::FileInputStream fileInputStream; fileInputStream = std::move(movedFileInputStream);
fileInputStream = std::move(movedFileInputStream);
CHECK(fileInputStream.read(buffer, 6) == 6); CHECK(fileInputStream.read(buffer, 6) == 6);
CHECK(fileInputStream.tell() == 6); CHECK(fileInputStream.tell() == 6);
CHECK(fileInputStream.getSize() == 11); CHECK(fileInputStream.getSize() == 11);
@ -114,8 +103,7 @@ TEST_CASE("[System] sf::FileInputStream")
SECTION("Temporary file stream") SECTION("Temporary file stream")
{ {
sf::FileInputStream fileInputStream; auto fileInputStream = sf::FileInputStream::open(temporaryFile.getPath()).value();
REQUIRE(fileInputStream.open(temporaryFile.getPath()));
CHECK(fileInputStream.read(buffer, 5) == 5); CHECK(fileInputStream.read(buffer, 5) == 5);
CHECK(fileInputStream.tell() == 5); CHECK(fileInputStream.tell() == 5);
CHECK(fileInputStream.getSize() == 11); CHECK(fileInputStream.getSize() == 11);

View File

@ -24,10 +24,9 @@ int main()
[[maybe_unused]] const sf::UdpSocket udpSocket; [[maybe_unused]] const sf::UdpSocket udpSocket;
// System // System
[[maybe_unused]] const sf::Angle angle; [[maybe_unused]] const sf::Angle angle;
[[maybe_unused]] const sf::FileInputStream fileInputStream; [[maybe_unused]] const sf::String string;
[[maybe_unused]] const sf::String string; [[maybe_unused]] const sf::Time time;
[[maybe_unused]] const sf::Time time;
// Window // Window
[[maybe_unused]] const sf::Context context; [[maybe_unused]] const sf::Context context;