Use smart pointers to manage memory

This commit is contained in:
Vittorio Romeo 2021-12-21 18:57:38 +01:00
parent 257c78f07a
commit f6de7eca40
44 changed files with 359 additions and 396 deletions

View File

@ -3,7 +3,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include "Effect.hpp" #include "Effect.hpp"
#include <vector> #include <array>
#include <cmath> #include <cmath>
@ -357,12 +357,20 @@ int main()
Effect::setFont(font); Effect::setFont(font);
// Create the effects // Create the effects
std::vector<Effect*> effects; Pixelate pixelateEffect;
effects.push_back(new Pixelate); WaveBlur waveBlurEffect;
effects.push_back(new WaveBlur); StormBlink stormBlinkEffect;
effects.push_back(new StormBlink); Edge edgeEffect;
effects.push_back(new Edge); Geometry geometryEffect;
effects.push_back(new Geometry);
const std::array<Effect*, 5> effects{
&pixelateEffect,
&waveBlurEffect,
&stormBlinkEffect,
&edgeEffect,
&geometryEffect
};
std::size_t current = 0; std::size_t current = 0;
// Initialize them // Initialize them
@ -456,9 +464,5 @@ int main()
window.display(); window.display();
} }
// delete the effects
for (Effect* effect : effects)
delete effect;
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -30,6 +30,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp> #include <SFML/Audio/Export.hpp>
#include <SFML/System/Time.hpp> #include <SFML/System/Time.hpp>
#include <memory>
#include <string> #include <string>
#include <cstddef> #include <cstddef>
@ -218,13 +219,28 @@ public:
void close(); void close();
private: private:
////////////////////////////////////////////////////////////
/// \brief Deleter for input streams that only conditionally deletes
///
////////////////////////////////////////////////////////////
struct StreamDeleter
{
StreamDeleter(bool theOwned);
// To accept ownership transfer from usual std::unique_ptr<T>
template <typename T>
StreamDeleter(const std::default_delete<T>&);
void operator()(InputStream* ptr) const;
bool owned;
};
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SoundFileReader* m_reader; //!< Reader that handles I/O on the file's format std::unique_ptr<SoundFileReader> m_reader; //!< Reader that handles I/O on the file's format
InputStream* m_stream; //!< Input stream used to access the file's data std::unique_ptr<InputStream, StreamDeleter> m_stream; //!< Input stream used to access the file's data
bool m_streamOwned; //!< Is the stream internal or external?
Uint64 m_sampleOffset; //!< Sample Read Position Uint64 m_sampleOffset; //!< Sample Read Position
Uint64 m_sampleCount; //!< Total number of samples in the file Uint64 m_sampleCount; //!< Total number of samples in the file
unsigned int m_channelCount; //!< Number of channels of the sound unsigned int m_channelCount; //!< Number of channels of the sound

View File

@ -29,6 +29,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp> #include <SFML/Audio/Export.hpp>
#include <memory>
#include <string> #include <string>
@ -104,7 +105,7 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SoundFileWriter* m_writer; //!< Writer that handles I/O on the file's format std::unique_ptr<SoundFileWriter> m_writer; //!< Writer that handles I/O on the file's format
}; };
} // namespace sf } // namespace sf

View File

@ -29,6 +29,7 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp> #include <SFML/Audio/Export.hpp>
#include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
@ -86,8 +87,6 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Instantiate the right reader for the given file on disk /// \brief Instantiate the right reader for the given file on disk
/// ///
/// It's up to the caller to release the returned reader
///
/// \param filename Path of the sound file /// \param filename Path of the sound file
/// ///
/// \return A new sound file reader that can read the given file, or null if no reader can handle it /// \return A new sound file reader that can read the given file, or null if no reader can handle it
@ -95,13 +94,11 @@ public:
/// \see createReaderFromMemory, createReaderFromStream /// \see createReaderFromMemory, createReaderFromStream
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static SoundFileReader* createReaderFromFilename(const std::string& filename); static std::unique_ptr<SoundFileReader> createReaderFromFilename(const std::string& filename);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Instantiate the right codec for the given file in memory /// \brief Instantiate the right codec for the given file in memory
/// ///
/// It's up to the caller to release the returned reader
///
/// \param data Pointer to the file data in memory /// \param data Pointer to the file data in memory
/// \param sizeInBytes Total size of the file data, in bytes /// \param sizeInBytes Total size of the file data, in bytes
/// ///
@ -110,13 +107,11 @@ public:
/// \see createReaderFromFilename, createReaderFromStream /// \see createReaderFromFilename, createReaderFromStream
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static SoundFileReader* createReaderFromMemory(const void* data, std::size_t sizeInBytes); static std::unique_ptr<SoundFileReader> createReaderFromMemory(const void* data, std::size_t sizeInBytes);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Instantiate the right codec for the given file in stream /// \brief Instantiate the right codec for the given file in stream
/// ///
/// It's up to the caller to release the returned reader
///
/// \param stream Source stream to read from /// \param stream Source stream to read from
/// ///
/// \return A new sound file codec that can read the given file, or null if no codec can handle it /// \return A new sound file codec that can read the given file, or null if no codec can handle it
@ -124,19 +119,17 @@ public:
/// \see createReaderFromFilename, createReaderFromMemory /// \see createReaderFromFilename, createReaderFromMemory
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static SoundFileReader* createReaderFromStream(InputStream& stream); static std::unique_ptr<SoundFileReader> createReaderFromStream(InputStream& stream);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Instantiate the right writer for the given file on disk /// \brief Instantiate the right writer for the given file on disk
/// ///
/// It's up to the caller to release the returned writer
///
/// \param filename Path of the sound file /// \param filename Path of the sound file
/// ///
/// \return A new sound file writer that can write given file, or null if no writer can handle it /// \return A new sound file writer that can write given file, or null if no writer can handle it
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static SoundFileWriter* createWriterFromFilename(const std::string& filename); static std::unique_ptr<SoundFileWriter> createWriterFromFilename(const std::string& filename);
private: private:
@ -146,14 +139,14 @@ private:
struct ReaderFactory struct ReaderFactory
{ {
bool (*check)(InputStream&); bool (*check)(InputStream&);
SoundFileReader* (*create)(); std::unique_ptr<SoundFileReader> (*create)();
}; };
using ReaderFactoryArray = std::vector<ReaderFactory>; using ReaderFactoryArray = std::vector<ReaderFactory>;
struct WriterFactory struct WriterFactory
{ {
bool (*check)(const std::string&); bool (*check)(const std::string&);
SoundFileWriter* (*create)(); std::unique_ptr<SoundFileWriter> (*create)();
}; };
using WriterFactoryArray = std::vector<WriterFactory>; using WriterFactoryArray = std::vector<WriterFactory>;

View File

@ -31,8 +31,8 @@ namespace sf
{ {
namespace priv namespace priv
{ {
template <typename T> SoundFileReader* createReader() {return new T;} template <typename T> std::unique_ptr<SoundFileReader> createReader() { return std::make_unique<T>(); }
template <typename T> SoundFileWriter* createWriter() {return new T;} template <typename T> std::unique_ptr<SoundFileWriter> createWriter() { return std::make_unique<T>(); }
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -32,11 +32,19 @@
#include <SFML/Graphics/Glyph.hpp> #include <SFML/Graphics/Glyph.hpp>
#include <SFML/Graphics/Texture.hpp> #include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/Rect.hpp> #include <SFML/Graphics/Rect.hpp>
#include <unordered_map> #include <memory>
#include <string> #include <string>
#include <unordered_map>
#include <vector> #include <vector>
#ifdef SFML_SYSTEM_ANDROID
namespace sf::priv
{
class ResourceStream;
}
#endif
namespace sf namespace sf
{ {
class InputStream; class InputStream;
@ -387,22 +395,19 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Types // Types
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
class FontHandles;
using PageTable = std::unordered_map<unsigned int, Page>; //!< Table mapping a character size to its page (texture) using PageTable = std::unordered_map<unsigned int, Page>; //!< Table mapping a character size to its page (texture)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void* m_library; //!< Pointer to the internal library interface (it is typeless to avoid exposing implementation details) std::shared_ptr<FontHandles> m_font; //!< Shared information about the internal font instance
void* m_face; //!< Pointer to the internal font face (it is typeless to avoid exposing implementation details)
void* m_streamRec; //!< Pointer to the stream rec instance (it is typeless to avoid exposing implementation details)
void* m_stroker; //!< Pointer to the stroker (it is typeless to avoid exposing implementation details)
int* m_refCount; //!< Reference counter used by implicit sharing
bool m_isSmooth; //!< Status of the smooth filter bool m_isSmooth; //!< Status of the smooth filter
Info m_info; //!< Information about the font Info m_info; //!< Information about the font
mutable PageTable m_pages; //!< Table containing the glyphs pages by character size mutable PageTable m_pages; //!< Table containing the glyphs pages by character size
mutable std::vector<Uint8> m_pixelBuffer; //!< Pixel buffer holding a glyph's pixels before being written to the texture mutable std::vector<Uint8> m_pixelBuffer; //!< Pixel buffer holding a glyph's pixels before being written to the texture
#ifdef SFML_SYSTEM_ANDROID #ifdef SFML_SYSTEM_ANDROID
void* m_stream; //!< Asset file streamer (if loaded from file) std::unique_ptr<priv::ResourceStream> m_stream; //!< Asset file streamer (if loaded from file)
#endif #endif
}; };

View File

@ -32,6 +32,7 @@
#include <SFML/Graphics/Texture.hpp> #include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/RenderTarget.hpp> #include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Window/ContextSettings.hpp> #include <SFML/Window/ContextSettings.hpp>
#include <memory>
namespace sf namespace sf
@ -228,7 +229,7 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
priv::RenderTextureImpl* m_impl; //!< Platform/hardware specific implementation std::unique_ptr<priv::RenderTextureImpl> m_impl; //!< Platform/hardware specific implementation
Texture m_texture; //!< Target texture to draw on Texture m_texture; //!< Target texture to draw on
}; };

View File

@ -30,6 +30,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Network/Export.hpp> #include <SFML/Network/Export.hpp>
#include <SFML/System/Time.hpp> #include <SFML/System/Time.hpp>
#include <memory>
namespace sf namespace sf
@ -50,6 +51,12 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SocketSelector(); SocketSelector();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~SocketSelector();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Copy constructor /// \brief Copy constructor
/// ///
@ -58,12 +65,6 @@ public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SocketSelector(const SocketSelector& copy); SocketSelector(const SocketSelector& copy);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~SocketSelector();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Add a new socket to the selector /// \brief Add a new socket to the selector
/// ///
@ -158,7 +159,7 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SocketSelectorImpl* m_impl; //!< Opaque pointer to the implementation (which requires OS-specific types) std::unique_ptr<SocketSelectorImpl> m_impl; //!< Opaque pointer to the implementation (which requires OS-specific types)
}; };
} // namespace sf } // namespace sf
@ -203,7 +204,7 @@ private:
/// listener.listen(55001); /// listener.listen(55001);
/// ///
/// // Create a list to store the future clients /// // Create a list to store the future clients
/// std::list<sf::TcpSocket*> clients; /// std::list<std::unique_ptr<sf::TcpSocket>> clients;
/// ///
/// // Create a selector /// // Create a selector
/// sf::SocketSelector selector; /// sf::SocketSelector selector;
@ -221,28 +222,27 @@ private:
/// if (selector.isReady(listener)) /// if (selector.isReady(listener))
/// { /// {
/// // The listener is ready: there is a pending connection /// // The listener is ready: there is a pending connection
/// sf::TcpSocket* client = new sf::TcpSocket; /// auto client = std::make_unique<sf::TcpSocket>();
/// if (listener.accept(*client) == sf::Socket::Done) /// if (listener.accept(*client) == sf::Socket::Done)
/// { /// {
/// // Add the new client to the clients list
/// clients.push_back(client);
///
/// // Add the new client to the selector so that we will /// // Add the new client to the selector so that we will
/// // be notified when he sends something /// // be notified when he sends something
/// selector.add(*client); /// selector.add(*client);
///
/// // Add the new client to the clients list
/// clients.push_back(std::move(client));
/// } /// }
/// else /// else
/// { /// {
/// // Error, we won't get a new connection, delete the socket /// // Error, we won't get a new connection, delete the socket
/// delete client; /// client.reset();
/// } /// }
/// } /// }
/// else /// else
/// { /// {
/// // The listener socket is not ready, test all other sockets (the clients) /// // The listener socket is not ready, test all other sockets (the clients)
/// for (auto it = clients.begin(); it != clients.end(); ++it) /// for (sf::TcpSocket& client : clients)
/// { /// {
/// sf::TcpSocket& client = **it;
/// if (selector.isReady(client)) /// if (selector.isReady(client))
/// { /// {
/// // The client has sent some data, we can receive it /// // The client has sent some data, we can receive it

View File

@ -31,8 +31,9 @@
#include <SFML/Config.hpp> #include <SFML/Config.hpp>
#include <SFML/System/Export.hpp> #include <SFML/System/Export.hpp>
#include <SFML/System/InputStream.hpp> #include <SFML/System/InputStream.hpp>
#include <cstdio> #include <memory>
#include <string> #include <string>
#include <cstdio>
#ifdef SFML_SYSTEM_ANDROID #ifdef SFML_SYSTEM_ANDROID
namespace sf namespace sf
@ -134,7 +135,7 @@ private:
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#ifdef SFML_SYSTEM_ANDROID #ifdef SFML_SYSTEM_ANDROID
priv::ResourceStream* m_file; std::unique_ptr<priv::ResourceStream> m_file;
#else #else
std::FILE* m_file; //!< stdio file stream std::FILE* m_file; //!< stdio file stream
#endif #endif

View File

@ -31,6 +31,7 @@
#include <SFML/Window/Export.hpp> #include <SFML/Window/Export.hpp>
#include <SFML/Window/GlResource.hpp> #include <SFML/Window/GlResource.hpp>
#include <SFML/Window/ContextSettings.hpp> #include <SFML/Window/ContextSettings.hpp>
#include <memory>
namespace sf namespace sf
@ -161,7 +162,7 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
priv::GlContext* m_context; //!< Internal OpenGL context std::unique_ptr<priv::GlContext> m_context; //!< Internal OpenGL context
}; };
} // namespace sf } // namespace sf

View File

@ -30,6 +30,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/Export.hpp> #include <SFML/Window/Export.hpp>
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <memory>
namespace sf namespace sf
{ {
@ -209,7 +210,7 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
priv::CursorImpl* m_impl; //!< Platform-specific implementation of the cursor std::unique_ptr<priv::CursorImpl> m_impl; //!< Platform-specific implementation of the cursor
}; };
} // namespace sf } // namespace sf

View File

@ -31,6 +31,7 @@
#include <SFML/Window/ContextSettings.hpp> #include <SFML/Window/ContextSettings.hpp>
#include <SFML/Window/GlResource.hpp> #include <SFML/Window/GlResource.hpp>
#include <SFML/Window/WindowBase.hpp> #include <SFML/Window/WindowBase.hpp>
#include <memory>
namespace sf namespace sf
@ -276,7 +277,7 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
priv::GlContext* m_context; //!< Platform-specific implementation of the OpenGL context std::unique_ptr<priv::GlContext> m_context; //!< Platform-specific implementation of the OpenGL context
Clock m_clock; //!< Clock for measuring the elapsed time between frames Clock m_clock; //!< Clock for measuring the elapsed time between frames
Time m_frameTimeLimit; //!< Current framerate limit Time m_frameTimeLimit; //!< Current framerate limit
}; };

View File

@ -36,6 +36,7 @@
#include <SFML/Window/WindowStyle.hpp> #include <SFML/Window/WindowStyle.hpp>
#include <SFML/System/Clock.hpp> #include <SFML/System/Clock.hpp>
#include <SFML/System/Vector2.hpp> #include <SFML/System/Vector2.hpp>
#include <memory>
namespace sf namespace sf
@ -482,7 +483,7 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
priv::WindowImpl* m_impl; //!< Platform-specific implementation of the window std::unique_ptr<priv::WindowImpl> m_impl; //!< Platform-specific implementation of the window
Vector2u m_size; //!< Current size of the window Vector2u m_size; //!< Current size of the window
}; };

View File

@ -27,6 +27,7 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Audio/AlResource.hpp> #include <SFML/Audio/AlResource.hpp>
#include <SFML/Audio/AudioDevice.hpp> #include <SFML/Audio/AudioDevice.hpp>
#include <memory>
#include <mutex> #include <mutex>
@ -39,7 +40,7 @@ namespace
// The audio device is instantiated on demand rather than at global startup, // The audio device is instantiated on demand rather than at global startup,
// which solves a lot of weird crashes and errors. // which solves a lot of weird crashes and errors.
// It is destroyed when it is no longer needed. // It is destroyed when it is no longer needed.
sf::priv::AudioDevice* globalDevice; std::unique_ptr<sf::priv::AudioDevice> globalDevice;
} }
@ -53,7 +54,7 @@ AlResource::AlResource()
// If this is the very first resource, trigger the global device initialization // If this is the very first resource, trigger the global device initialization
if (count == 0) if (count == 0)
globalDevice = new priv::AudioDevice; globalDevice = std::make_unique<priv::AudioDevice>();
// Increment the resources counter // Increment the resources counter
count++; count++;
@ -71,7 +72,7 @@ AlResource::~AlResource()
// If there's no more resource alive, we can destroy the device // If there's no more resource alive, we can destroy the device
if (count == 0) if (count == 0)
delete globalDevice; globalDevice.reset();
} }
} // namespace sf } // namespace sf

View File

@ -38,12 +38,35 @@
namespace sf namespace sf
{ {
////////////////////////////////////////////////////////////
InputSoundFile::StreamDeleter::StreamDeleter(bool theOwned) : owned{theOwned}
{
}
////////////////////////////////////////////////////////////
template <typename T>
InputSoundFile::StreamDeleter::StreamDeleter(const std::default_delete<T>&)
: owned{true}
{
}
////////////////////////////////////////////////////////////
void InputSoundFile::StreamDeleter::operator()(InputStream* ptr) const
{
if (owned)
std::default_delete<InputStream>{}(ptr);
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
InputSoundFile::InputSoundFile() : InputSoundFile::InputSoundFile() :
m_reader (nullptr), m_reader (),
m_stream (nullptr), m_stream (nullptr, false),
m_streamOwned (false), m_sampleOffset(0),
m_sampleOffset (0),
m_sampleCount (0), m_sampleCount (0),
m_channelCount(0), m_channelCount(0),
m_sampleRate (0) m_sampleRate (0)
@ -66,29 +89,25 @@ bool InputSoundFile::openFromFile(const std::string& filename)
close(); close();
// Find a suitable reader for the file type // Find a suitable reader for the file type
m_reader = SoundFileFactory::createReaderFromFilename(filename); auto reader = SoundFileFactory::createReaderFromFilename(filename);
if (!m_reader) if (!reader)
return false; return false;
// Wrap the file into a stream // Wrap the file into a stream
auto* file = new FileInputStream; auto file = std::make_unique<FileInputStream>();
m_stream = file;
m_streamOwned = true;
// Open it // Open it
if (!file->open(filename)) if (!file->open(filename))
{
close();
return false; return false;
}
// Pass the stream to the reader // Pass the stream to the reader
SoundFileReader::Info info; SoundFileReader::Info info;
if (!m_reader->open(*file, info)) if (!reader->open(*file, info))
{
close();
return false; return false;
}
// Take ownership of successfully opened reader and stream
m_reader = std::move(reader);
m_stream = std::move(file);
// Retrieve the attributes of the open sound file // Retrieve the attributes of the open sound file
m_sampleCount = info.sampleCount; m_sampleCount = info.sampleCount;
@ -106,25 +125,24 @@ bool InputSoundFile::openFromMemory(const void* data, std::size_t sizeInBytes)
close(); close();
// Find a suitable reader for the file type // Find a suitable reader for the file type
m_reader = SoundFileFactory::createReaderFromMemory(data, sizeInBytes); auto reader = SoundFileFactory::createReaderFromMemory(data, sizeInBytes);
if (!m_reader) if (!reader)
return false; return false;
// Wrap the memory file into a stream // Wrap the memory file into a stream
auto* memory = new MemoryInputStream; auto memory = std::make_unique<MemoryInputStream>();
m_stream = memory;
m_streamOwned = true;
// Open it // Open it
memory->open(data, sizeInBytes); memory->open(data, sizeInBytes);
// Pass the stream to the reader // Pass the stream to the reader
SoundFileReader::Info info; SoundFileReader::Info info;
if (!m_reader->open(*memory, info)) if (!reader->open(*memory, info))
{
close();
return false; return false;
}
// Take ownership of successfully opened reader and stream
m_reader = std::move(reader);
m_stream = std::move(memory);
// Retrieve the attributes of the open sound file // Retrieve the attributes of the open sound file
m_sampleCount = info.sampleCount; m_sampleCount = info.sampleCount;
@ -142,14 +160,10 @@ bool InputSoundFile::openFromStream(InputStream& stream)
close(); close();
// Find a suitable reader for the file type // Find a suitable reader for the file type
m_reader = SoundFileFactory::createReaderFromStream(stream); auto reader = SoundFileFactory::createReaderFromStream(stream);
if (!m_reader) if (!reader)
return false; return false;
// store the stream
m_stream = &stream;
m_streamOwned = false;
// Don't forget to reset the stream to its beginning before re-opening it // Don't forget to reset the stream to its beginning before re-opening it
if (stream.seek(0) != 0) if (stream.seek(0) != 0)
{ {
@ -159,11 +173,12 @@ bool InputSoundFile::openFromStream(InputStream& stream)
// Pass the stream to the reader // Pass the stream to the reader
SoundFileReader::Info info; SoundFileReader::Info info;
if (!m_reader->open(stream, info)) if (!reader->open(stream, info))
{
close();
return false; return false;
}
// Take ownership of reader and store a reference to the stream without taking ownership
m_reader = std::move(reader);
m_stream = {&stream, false};
// Retrieve the attributes of the open sound file // Retrieve the attributes of the open sound file
m_sampleCount = info.sampleCount; m_sampleCount = info.sampleCount;
@ -259,19 +274,13 @@ Uint64 InputSoundFile::read(Int16* samples, Uint64 maxCount)
void InputSoundFile::close() void InputSoundFile::close()
{ {
// Destroy the reader // Destroy the reader
delete m_reader; m_reader.reset();
m_reader = nullptr;
// Destroy the stream if we own it // Destroy the stream if we own it
if (m_streamOwned) m_stream.reset();
{
delete m_stream;
m_streamOwned = false;
}
m_stream = nullptr;
m_sampleOffset = 0;
// Reset the sound file attributes // Reset the sound file attributes
m_sampleOffset = 0;
m_sampleCount = 0; m_sampleCount = 0;
m_channelCount = 0; m_channelCount = 0;
m_sampleRate = 0; m_sampleRate = 0;

View File

@ -81,8 +81,7 @@ void OutputSoundFile::write(const Int16* samples, Uint64 count)
void OutputSoundFile::close() void OutputSoundFile::close()
{ {
// Destroy the reader // Destroy the reader
delete m_writer; m_writer.reset();
m_writer = nullptr;
} }
} // namespace sf } // namespace sf

View File

@ -65,7 +65,7 @@ SoundFileFactory::WriterFactoryArray SoundFileFactory::s_writers;
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SoundFileReader* SoundFileFactory::createReaderFromFilename(const std::string& filename) std::unique_ptr<SoundFileReader> SoundFileFactory::createReaderFromFilename(const std::string& filename)
{ {
// Register the built-in readers/writers on first call // Register the built-in readers/writers on first call
ensureDefaultReadersWritersRegistered(); ensureDefaultReadersWritersRegistered();
@ -97,7 +97,7 @@ SoundFileReader* SoundFileFactory::createReaderFromFilename(const std::string& f
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SoundFileReader* SoundFileFactory::createReaderFromMemory(const void* data, std::size_t sizeInBytes) std::unique_ptr<SoundFileReader> SoundFileFactory::createReaderFromMemory(const void* data, std::size_t sizeInBytes)
{ {
// Register the built-in readers/writers on first call // Register the built-in readers/writers on first call
ensureDefaultReadersWritersRegistered(); ensureDefaultReadersWritersRegistered();
@ -126,7 +126,7 @@ SoundFileReader* SoundFileFactory::createReaderFromMemory(const void* data, std:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SoundFileReader* SoundFileFactory::createReaderFromStream(InputStream& stream) std::unique_ptr<SoundFileReader> SoundFileFactory::createReaderFromStream(InputStream& stream)
{ {
// Register the built-in readers/writers on first call // Register the built-in readers/writers on first call
ensureDefaultReadersWritersRegistered(); ensureDefaultReadersWritersRegistered();
@ -151,7 +151,7 @@ SoundFileReader* SoundFileFactory::createReaderFromStream(InputStream& stream)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SoundFileWriter* SoundFileFactory::createWriterFromFilename(const std::string& filename) std::unique_ptr<SoundFileWriter> SoundFileFactory::createWriterFromFilename(const std::string& filename)
{ {
// Register the built-in readers/writers on first call // Register the built-in readers/writers on first call
ensureDefaultReadersWritersRegistered(); ensureDefaultReadersWritersRegistered();

View File

@ -38,6 +38,7 @@
#include FT_OUTLINE_H #include FT_OUTLINE_H
#include FT_BITMAP_H #include FT_BITMAP_H
#include FT_STROKER_H #include FT_STROKER_H
#include <type_traits>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <cmath> #include <cmath>
@ -83,43 +84,45 @@ namespace
namespace sf namespace sf
{ {
////////////////////////////////////////////////////////////
class Font::FontHandles
{
private:
// Default constructible deleter functor
struct Deleter
{
void operator()(FT_Library theLibrary) { FT_Done_FreeType(theLibrary); }
void operator()(FT_Face theFace) { FT_Done_Face(theFace); }
void operator()(FT_Stroker theStroker) { FT_Stroker_Done(theStroker); }
};
public:
std::unique_ptr<std::remove_pointer_t<FT_Library>, Deleter> library; //< Pointer to the internal library interface
std::unique_ptr<FT_StreamRec> streamRec; //< Pointer to the stream rec instance
std::unique_ptr<std::remove_pointer_t<FT_Face>, Deleter> face; //< Pointer to the internal font face
std::unique_ptr<std::remove_pointer_t<FT_Stroker>, Deleter> stroker; //< Pointer to the stroker
};
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Font::Font() : Font::Font() :
m_library (nullptr), m_font (),
m_face (nullptr),
m_streamRec(nullptr),
m_stroker (nullptr),
m_refCount (nullptr),
m_isSmooth (true), m_isSmooth (true),
m_info () m_info ()
{ {
#ifdef SFML_SYSTEM_ANDROID
m_stream = nullptr;
#endif
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Font::Font(const Font& copy) : Font::Font(const Font& copy) :
m_library (copy.m_library), m_font (copy.m_font),
m_face (copy.m_face),
m_streamRec (copy.m_streamRec),
m_stroker (copy.m_stroker),
m_refCount (copy.m_refCount),
m_isSmooth (copy.m_isSmooth), m_isSmooth (copy.m_isSmooth),
m_info (copy.m_info), m_info (copy.m_info),
m_pages (copy.m_pages), m_pages (copy.m_pages),
m_pixelBuffer(copy.m_pixelBuffer) m_pixelBuffer(copy.m_pixelBuffer)
{ {
#ifdef SFML_SYSTEM_ANDROID
m_stream = nullptr;
#endif
// Note: as FreeType doesn't provide functions for copying/cloning,
// we must share all the FreeType pointers
if (m_refCount)
(*m_refCount)++;
} }
@ -127,13 +130,6 @@ m_pixelBuffer(copy.m_pixelBuffer)
Font::~Font() Font::~Font()
{ {
cleanup(); cleanup();
#ifdef SFML_SYSTEM_ANDROID
if (m_stream)
delete static_cast<priv::ResourceStream*>(m_stream);
#endif
} }
@ -144,7 +140,8 @@ bool Font::loadFromFile(const std::string& filename)
// Cleanup the previous resources // Cleanup the previous resources
cleanup(); cleanup();
m_refCount = new int(1);
auto font = std::make_unique<FontHandles>();
// Initialize FreeType // Initialize FreeType
// Note: we initialize FreeType for every font instance in order to avoid having a single // Note: we initialize FreeType for every font instance in order to avoid having a single
@ -155,37 +152,35 @@ bool Font::loadFromFile(const std::string& filename)
err() << "Failed to load font \"" << filename << "\" (failed to initialize FreeType)" << std::endl; err() << "Failed to load font \"" << filename << "\" (failed to initialize FreeType)" << std::endl;
return false; return false;
} }
m_library = library; font->library.reset(library);
// Load the new font face from the specified file // Load the new font face from the specified file
FT_Face face; FT_Face face;
if (FT_New_Face(static_cast<FT_Library>(m_library), filename.c_str(), 0, &face) != 0) if (FT_New_Face(library, filename.c_str(), 0, &face) != 0)
{ {
err() << "Failed to load font \"" << filename << "\" (failed to create the font face)" << std::endl; err() << "Failed to load font \"" << filename << "\" (failed to create the font face)" << std::endl;
return false; return false;
} }
font->face.reset(face);
// Load the stroker that will be used to outline the font // Load the stroker that will be used to outline the font
FT_Stroker stroker; FT_Stroker stroker;
if (FT_Stroker_New(static_cast<FT_Library>(m_library), &stroker) != 0) if (FT_Stroker_New(library, &stroker) != 0)
{ {
err() << "Failed to load font \"" << filename << "\" (failed to create the stroker)" << std::endl; err() << "Failed to load font \"" << filename << "\" (failed to create the stroker)" << std::endl;
FT_Done_Face(face);
return false; return false;
} }
font->stroker.reset(stroker);
// Select the unicode character map // Select the unicode character map
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0) if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0)
{ {
err() << "Failed to load font \"" << filename << "\" (failed to set the Unicode character set)" << std::endl; err() << "Failed to load font \"" << filename << "\" (failed to set the Unicode character set)" << std::endl;
FT_Stroker_Done(stroker);
FT_Done_Face(face);
return false; return false;
} }
// Store the loaded font in our ugly void* :) // Store the loaded font handles
m_stroker = stroker; m_font = std::move(font);
m_face = face;
// Store the font information // Store the font information
m_info.family = face->family_name ? face->family_name : std::string(); m_info.family = face->family_name ? face->family_name : std::string();
@ -194,11 +189,8 @@ bool Font::loadFromFile(const std::string& filename)
#else #else
if (m_stream) m_stream = std::make_unique<priv::ResourceStream>(filename);
delete static_cast<priv::ResourceStream*>(m_stream); return loadFromStream(*m_stream);
m_stream = new priv::ResourceStream(filename);
return loadFromStream(*static_cast<priv::ResourceStream*>(m_stream));
#endif #endif
} }
@ -209,7 +201,8 @@ bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
{ {
// Cleanup the previous resources // Cleanup the previous resources
cleanup(); cleanup();
m_refCount = new int(1);
auto font = std::make_unique<FontHandles>();
// Initialize FreeType // Initialize FreeType
// Note: we initialize FreeType for every font instance in order to avoid having a single // Note: we initialize FreeType for every font instance in order to avoid having a single
@ -220,37 +213,35 @@ bool Font::loadFromMemory(const void* data, std::size_t sizeInBytes)
err() << "Failed to load font from memory (failed to initialize FreeType)" << std::endl; err() << "Failed to load font from memory (failed to initialize FreeType)" << std::endl;
return false; return false;
} }
m_library = library; font->library.reset(library);
// Load the new font face from the specified file // Load the new font face from the specified file
FT_Face face; FT_Face face;
if (FT_New_Memory_Face(static_cast<FT_Library>(m_library), reinterpret_cast<const FT_Byte*>(data), static_cast<FT_Long>(sizeInBytes), 0, &face) != 0) if (FT_New_Memory_Face(library, reinterpret_cast<const FT_Byte*>(data), static_cast<FT_Long>(sizeInBytes), 0, &face) != 0)
{ {
err() << "Failed to load font from memory (failed to create the font face)" << std::endl; err() << "Failed to load font from memory (failed to create the font face)" << std::endl;
return false; return false;
} }
font->face.reset(face);
// Load the stroker that will be used to outline the font // Load the stroker that will be used to outline the font
FT_Stroker stroker; FT_Stroker stroker;
if (FT_Stroker_New(static_cast<FT_Library>(m_library), &stroker) != 0) if (FT_Stroker_New(library, &stroker) != 0)
{ {
err() << "Failed to load font from memory (failed to create the stroker)" << std::endl; err() << "Failed to load font from memory (failed to create the stroker)" << std::endl;
FT_Done_Face(face);
return false; return false;
} }
font->stroker.reset(stroker);
// Select the Unicode character map // Select the Unicode character map
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0) 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; err() << "Failed to load font from memory (failed to set the Unicode character set)" << std::endl;
FT_Stroker_Done(stroker);
FT_Done_Face(face);
return false; return false;
} }
// Store the loaded font in our ugly void* :) // Store the loaded font handles
m_stroker = stroker; m_font = std::move(font);
m_face = face;
// Store the font information // Store the font information
m_info.family = face->family_name ? face->family_name : std::string(); m_info.family = face->family_name ? face->family_name : std::string();
@ -264,7 +255,8 @@ bool Font::loadFromStream(InputStream& stream)
{ {
// Cleanup the previous resources // Cleanup the previous resources
cleanup(); cleanup();
m_refCount = new int(1);
auto font = std::make_unique<FontHandles>();
// Initialize FreeType // Initialize FreeType
// Note: we initialize FreeType for every font instance in order to avoid having a single // Note: we initialize FreeType for every font instance in order to avoid having a single
@ -275,7 +267,7 @@ bool Font::loadFromStream(InputStream& stream)
err() << "Failed to load font from stream (failed to initialize FreeType)" << std::endl; err() << "Failed to load font from stream (failed to initialize FreeType)" << std::endl;
return false; return false;
} }
m_library = library; font->library.reset(library);
// Make sure that the stream's reading position is at the beginning // Make sure that the stream's reading position is at the beginning
if (stream.seek(0) == -1) if (stream.seek(0) == -1)
@ -285,54 +277,48 @@ bool Font::loadFromStream(InputStream& stream)
} }
// Prepare a wrapper for our stream, that we'll pass to FreeType callbacks // Prepare a wrapper for our stream, that we'll pass to FreeType callbacks
auto* rec = new FT_StreamRec; font->streamRec = std::make_unique<FT_StreamRec>();
std::memset(rec, 0, sizeof(*rec)); std::memset(font->streamRec.get(), 0, sizeof(*font->streamRec));
rec->base = nullptr; font->streamRec->base = nullptr;
rec->size = static_cast<unsigned long>(stream.getSize()); font->streamRec->size = static_cast<unsigned long>(stream.getSize());
rec->pos = 0; font->streamRec->pos = 0;
rec->descriptor.pointer = &stream; font->streamRec->descriptor.pointer = &stream;
rec->read = &read; font->streamRec->read = &read;
rec->close = &close; font->streamRec->close = &close;
// Setup the FreeType callbacks that will read our stream // Setup the FreeType callbacks that will read our stream
FT_Open_Args args; FT_Open_Args args;
args.flags = FT_OPEN_STREAM; args.flags = FT_OPEN_STREAM;
args.stream = rec; args.stream = font->streamRec.get();
args.driver = nullptr; args.driver = nullptr;
// Load the new font face from the specified stream // Load the new font face from the specified stream
FT_Face face; FT_Face face;
if (FT_Open_Face(static_cast<FT_Library>(m_library), &args, 0, &face) != 0) if (FT_Open_Face(library, &args, 0, &face) != 0)
{ {
err() << "Failed to load font from stream (failed to create the font face)" << std::endl; err() << "Failed to load font from stream (failed to create the font face)" << std::endl;
delete rec;
return false; return false;
} }
font->face.reset(face);
// Load the stroker that will be used to outline the font // Load the stroker that will be used to outline the font
FT_Stroker stroker; FT_Stroker stroker;
if (FT_Stroker_New(static_cast<FT_Library>(m_library), &stroker) != 0) if (FT_Stroker_New(library, &stroker) != 0)
{ {
err() << "Failed to load font from stream (failed to create the stroker)" << std::endl; err() << "Failed to load font from stream (failed to create the stroker)" << std::endl;
FT_Done_Face(face);
delete rec;
return false; return false;
} }
font->stroker.reset(stroker);
// Select the Unicode character map // Select the Unicode character map
if (FT_Select_Charmap(face, FT_ENCODING_UNICODE) != 0) 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; err() << "Failed to load font from stream (failed to set the Unicode character set)" << std::endl;
FT_Done_Face(face);
FT_Stroker_Done(stroker);
delete rec;
return false; return false;
} }
// Store the loaded font in our ugly void* :) // Store the loaded font handles
m_stroker = stroker; m_font = std::move(font);
m_face = face;
m_streamRec = rec;
// Store the font information // Store the font information
m_info.family = face->family_name ? face->family_name : std::string(); m_info.family = face->family_name ? face->family_name : std::string();
@ -355,7 +341,7 @@ const Glyph& Font::getGlyph(Uint32 codePoint, unsigned int characterSize, bool b
GlyphTable& glyphs = m_pages[characterSize].glyphs; GlyphTable& glyphs = m_pages[characterSize].glyphs;
// Build the key by combining the glyph index (based on code point), bold flag, and outline thickness // Build the key by combining the glyph index (based on code point), bold flag, and outline thickness
Uint64 key = combine(outlineThickness, bold, FT_Get_Char_Index(static_cast<FT_Face>(m_face), codePoint)); Uint64 key = combine(outlineThickness, bold, FT_Get_Char_Index(m_font->face.get(), codePoint));
// Search the glyph into the cache // Search the glyph into the cache
if (auto it = glyphs.find(key); it != glyphs.end()) if (auto it = glyphs.find(key); it != glyphs.end())
@ -375,7 +361,7 @@ const Glyph& Font::getGlyph(Uint32 codePoint, unsigned int characterSize, bool b
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
bool Font::hasGlyph(Uint32 codePoint) const bool Font::hasGlyph(Uint32 codePoint) const
{ {
return FT_Get_Char_Index(static_cast<FT_Face>(m_face), codePoint) != 0; return FT_Get_Char_Index(m_font->face.get(), codePoint) != 0;
} }
@ -386,7 +372,7 @@ float Font::getKerning(Uint32 first, Uint32 second, unsigned int characterSize,
if (first == 0 || second == 0) if (first == 0 || second == 0)
return 0.f; return 0.f;
auto face = static_cast<FT_Face>(m_face); auto face = m_font->face.get();
if (face && setCurrentSize(characterSize)) if (face && setCurrentSize(characterSize))
{ {
@ -423,7 +409,7 @@ float Font::getKerning(Uint32 first, Uint32 second, unsigned int characterSize,
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
float Font::getLineSpacing(unsigned int characterSize) const float Font::getLineSpacing(unsigned int characterSize) const
{ {
auto face = static_cast<FT_Face>(m_face); auto face = m_font->face.get();
if (face && setCurrentSize(characterSize)) if (face && setCurrentSize(characterSize))
{ {
@ -439,7 +425,7 @@ float Font::getLineSpacing(unsigned int characterSize) const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
float Font::getUnderlinePosition(unsigned int characterSize) const float Font::getUnderlinePosition(unsigned int characterSize) const
{ {
auto face = static_cast<FT_Face>(m_face); auto face = m_font->face.get();
if (face && setCurrentSize(characterSize)) if (face && setCurrentSize(characterSize))
{ {
@ -459,7 +445,7 @@ float Font::getUnderlinePosition(unsigned int characterSize) const
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
float Font::getUnderlineThickness(unsigned int characterSize) const float Font::getUnderlineThickness(unsigned int characterSize) const
{ {
auto face = static_cast<FT_Face>(m_face); auto face = m_font->face.get();
if (face && setCurrentSize(characterSize)) if (face && setCurrentSize(characterSize))
{ {
@ -508,11 +494,7 @@ Font& Font::operator =(const Font& right)
{ {
Font temp(right); Font temp(right);
std::swap(m_library, temp.m_library); std::swap(m_font, temp.m_font);
std::swap(m_face, temp.m_face);
std::swap(m_streamRec, temp.m_streamRec);
std::swap(m_stroker, temp.m_stroker);
std::swap(m_refCount, temp.m_refCount);
std::swap(m_isSmooth, temp.m_isSmooth); std::swap(m_isSmooth, temp.m_isSmooth);
std::swap(m_info, temp.m_info); std::swap(m_info, temp.m_info);
std::swap(m_pages, temp.m_pages); std::swap(m_pages, temp.m_pages);
@ -529,42 +511,10 @@ Font& Font::operator =(const Font& right)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void Font::cleanup() void Font::cleanup()
{ {
// Check if we must destroy the FreeType pointers // Drop ownership of shared FreeType pointers
if (m_refCount) m_font.reset();
{
// Decrease the reference counter
(*m_refCount)--;
// Free the resources only if we are the last owner
if (*m_refCount == 0)
{
// Delete the reference counter
delete m_refCount;
// Destroy the stroker
if (m_stroker)
FT_Stroker_Done(static_cast<FT_Stroker>(m_stroker));
// Destroy the font face
if (m_face)
FT_Done_Face(static_cast<FT_Face>(m_face));
// Destroy the stream rec instance, if any (must be done after FT_Done_Face!)
if (m_streamRec)
delete static_cast<FT_StreamRec*>(m_streamRec);
// Close the library
if (m_library)
FT_Done_FreeType(static_cast<FT_Library>(m_library));
}
}
// Reset members // Reset members
m_library = nullptr;
m_face = nullptr;
m_stroker = nullptr;
m_streamRec = nullptr;
m_refCount = nullptr;
m_pages.clear(); m_pages.clear();
std::vector<Uint8>().swap(m_pixelBuffer); std::vector<Uint8>().swap(m_pixelBuffer);
} }
@ -576,8 +526,8 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
// The glyph to return // The glyph to return
Glyph glyph; Glyph glyph;
// First, transform our ugly void* to a FT_Face // First, get our FT_Face
auto face = static_cast<FT_Face>(m_face); auto face = m_font->face.get();
if (!face) if (!face)
return glyph; return glyph;
@ -610,7 +560,7 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
if (outlineThickness != 0) if (outlineThickness != 0)
{ {
auto stroker = static_cast<FT_Stroker>(m_stroker); auto stroker = m_font->stroker.get();
FT_Stroker_Set(stroker, static_cast<FT_Fixed>(outlineThickness * static_cast<float>(1 << 6)), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0); FT_Stroker_Set(stroker, static_cast<FT_Fixed>(outlineThickness * static_cast<float>(1 << 6)), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
FT_Glyph_Stroke(&glyphDesc, stroker, true); FT_Glyph_Stroke(&glyphDesc, stroker, true);
@ -628,7 +578,7 @@ Glyph Font::loadGlyph(Uint32 codePoint, unsigned int characterSize, bool bold, f
if (!outline) if (!outline)
{ {
if (bold) if (bold)
FT_Bitmap_Embolden(static_cast<FT_Library>(m_library), &bitmap, weight, weight); FT_Bitmap_Embolden(m_font->library.get(), &bitmap, weight, weight);
if (outlineThickness != 0) if (outlineThickness != 0)
err() << "Failed to outline glyph (no fallback available)" << std::endl; err() << "Failed to outline glyph (no fallback available)" << std::endl;
@ -814,7 +764,7 @@ bool Font::setCurrentSize(unsigned int characterSize) const
// FT_Set_Pixel_Sizes is an expensive function, so we must call it // FT_Set_Pixel_Sizes is an expensive function, so we must call it
// only when necessary to avoid killing performances // only when necessary to avoid killing performances
auto face = static_cast<FT_Face>(m_face); auto face = m_font->face.get();
FT_UShort currentSize = face->size->metrics.x_ppem; FT_UShort currentSize = face->size->metrics.x_ppem;
if (currentSize != characterSize) if (currentSize != characterSize)

View File

@ -29,23 +29,17 @@
#include <SFML/Graphics/RenderTextureImplFBO.hpp> #include <SFML/Graphics/RenderTextureImplFBO.hpp>
#include <SFML/Graphics/RenderTextureImplDefault.hpp> #include <SFML/Graphics/RenderTextureImplDefault.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#include <memory>
namespace sf namespace sf
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderTexture::RenderTexture() : RenderTexture::RenderTexture() = default;
m_impl(nullptr)
{
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderTexture::~RenderTexture() RenderTexture::~RenderTexture() = default;
{
delete m_impl;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -65,11 +59,10 @@ bool RenderTexture::create(unsigned int width, unsigned int height, const Contex
setSmooth(false); setSmooth(false);
// Create the implementation // Create the implementation
delete m_impl;
if (priv::RenderTextureImplFBO::isAvailable()) if (priv::RenderTextureImplFBO::isAvailable())
{ {
// Use frame-buffer object (FBO) // Use frame-buffer object (FBO)
m_impl = new priv::RenderTextureImplFBO; m_impl = std::make_unique<priv::RenderTextureImplFBO>();
// Mark the texture as being a framebuffer object attachment // Mark the texture as being a framebuffer object attachment
m_texture.m_fboAttachment = true; m_texture.m_fboAttachment = true;
@ -77,7 +70,7 @@ bool RenderTexture::create(unsigned int width, unsigned int height, const Contex
else else
{ {
// Use default implementation // Use default implementation
m_impl = new priv::RenderTextureImplDefault; m_impl = std::make_unique<priv::RenderTextureImplDefault>();
} }
// Initialize the render texture // Initialize the render texture

View File

@ -29,6 +29,7 @@
#include <SFML/Graphics/GLCheck.hpp> #include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Graphics/TextureSaver.hpp> #include <SFML/Graphics/TextureSaver.hpp>
#include <SFML/Window/Context.hpp> #include <SFML/Window/Context.hpp>
#include <memory>
namespace sf namespace sf
@ -37,7 +38,7 @@ namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderTextureImplDefault::RenderTextureImplDefault() : RenderTextureImplDefault::RenderTextureImplDefault() :
m_context(nullptr), m_context(),
m_width (0), m_width (0),
m_height (0) m_height (0)
{ {
@ -46,11 +47,7 @@ m_height (0)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
RenderTextureImplDefault::~RenderTextureImplDefault() RenderTextureImplDefault::~RenderTextureImplDefault() = default;
{
// Destroy the context
delete m_context;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -71,7 +68,7 @@ bool RenderTextureImplDefault::create(unsigned int width, unsigned int height, u
m_height = height; m_height = height;
// Create the in-memory OpenGL context // Create the in-memory OpenGL context
m_context = new Context(settings, width, height); m_context = std::make_unique<Context>(settings, width, height);
return true; return true;
} }

View File

@ -30,11 +30,14 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderTextureImpl.hpp> #include <SFML/Graphics/RenderTextureImpl.hpp>
#include <SFML/Window/GlResource.hpp> #include <SFML/Window/GlResource.hpp>
#include <SFML/Window/Context.hpp> #include <memory>
namespace sf namespace sf
{ {
class Context;
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -113,7 +116,7 @@ private:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Context* m_context; //!< P-Buffer based context std::unique_ptr<Context> m_context; //!< P-Buffer based context
unsigned int m_width; //!< Width of the P-Buffer unsigned int m_width; //!< Width of the P-Buffer
unsigned int m_height; //!< Height of the P-Buffer unsigned int m_height; //!< Height of the P-Buffer
}; };

View File

@ -28,12 +28,13 @@
#include <SFML/Graphics/RenderTextureImplFBO.hpp> #include <SFML/Graphics/RenderTextureImplFBO.hpp>
#include <SFML/Graphics/Texture.hpp> #include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/GLCheck.hpp> #include <SFML/Graphics/GLCheck.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#include <utility> #include <mutex>
#include <set>
#include <unordered_map> #include <unordered_map>
#include <unordered_set> #include <unordered_set>
#include <set> #include <utility>
#include <mutex>
namespace namespace
@ -118,7 +119,7 @@ m_depthStencilBuffer(0),
m_colorBuffer (0), m_colorBuffer (0),
m_width (0), m_width (0),
m_height (0), m_height (0),
m_context (nullptr), m_context (),
m_textureId (0), m_textureId (0),
m_multisample (false), m_multisample (false),
m_stencil (false), m_stencil (false),
@ -169,9 +170,6 @@ RenderTextureImplFBO::~RenderTextureImplFBO()
// Clean up FBOs // Clean up FBOs
destroyStaleFBOs(); destroyStaleFBOs();
// Delete the backup context if we had to create one
delete m_context;
} }
@ -521,7 +519,7 @@ bool RenderTextureImplFBO::activate(bool active)
if (!contextId) if (!contextId)
{ {
if (!m_context) if (!m_context)
m_context = new Context; m_context = std::make_unique<Context>();
if (!m_context->setActive(true)) if (!m_context->setActive(true))
{ {

View File

@ -29,13 +29,16 @@
// Headers // Headers
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderTextureImpl.hpp> #include <SFML/Graphics/RenderTextureImpl.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/Window/GlResource.hpp> #include <SFML/Window/GlResource.hpp>
#include <unordered_map> #include <unordered_map>
#include <memory>
namespace sf namespace sf
{ {
class Context;
namespace priv namespace priv
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -142,7 +145,7 @@ private:
unsigned int m_colorBuffer; //!< Optional multisample color buffer attached to the frame buffer unsigned int m_colorBuffer; //!< Optional multisample color buffer attached to the frame buffer
unsigned int m_width; //!< Width of the attachments unsigned int m_width; //!< Width of the attachments
unsigned int m_height; //!< Height of the attachments unsigned int m_height; //!< Height of the attachments
Context* m_context; //!< Backup OpenGL context, used when none already exist std::unique_ptr<Context> m_context; //!< Backup OpenGL context, used when none already exist
unsigned int m_textureId; //!< The ID of the texture to attach to the FBO unsigned int m_textureId; //!< The ID of the texture to attach to the FBO
bool m_multisample; //!< Whether we have to create a multisample frame buffer as well bool m_multisample; //!< Whether we have to create a multisample frame buffer as well
bool m_stencil; //!< Whether we have stencil attachment bool m_stencil; //!< Whether we have stencil attachment

View File

@ -498,8 +498,7 @@ static void onLowMemory(ANativeActivity* activity)
JNIEXPORT void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize) JNIEXPORT void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize)
{ {
// Create an activity states (will keep us in the know, about events we care) // Create an activity states (will keep us in the know, about events we care)
sf::priv::ActivityStates* states = nullptr; auto* states = new sf::priv::ActivityStates;
states = new sf::priv::ActivityStates;
// Initialize the states value // Initialize the states value
states->activity = nullptr; states->activity = nullptr;

View File

@ -30,6 +30,7 @@
#include <SFML/Network/SocketImpl.hpp> #include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#include <algorithm> #include <algorithm>
#include <memory>
#include <utility> #include <utility>
#ifdef _MSC_VER #ifdef _MSC_VER
@ -51,7 +52,7 @@ struct SocketSelector::SocketSelectorImpl
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SocketSelector::SocketSelector() : SocketSelector::SocketSelector() :
m_impl(new SocketSelectorImpl) m_impl(std::make_unique<SocketSelectorImpl>())
{ {
clear(); clear();
} }
@ -59,17 +60,14 @@ m_impl(new SocketSelectorImpl)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SocketSelector::SocketSelector(const SocketSelector& copy) : SocketSelector::SocketSelector(const SocketSelector& copy) :
m_impl(new SocketSelectorImpl(*copy.m_impl)) m_impl(std::make_unique<SocketSelectorImpl>(*copy.m_impl))
{ {
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SocketSelector::~SocketSelector() SocketSelector::~SocketSelector() = default;
{
delete m_impl;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -29,7 +29,8 @@
#ifdef SFML_SYSTEM_ANDROID #ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Android/ResourceStream.hpp> #include <SFML/System/Android/ResourceStream.hpp>
#endif #endif
#include <memory>
#include <cstddef>
namespace sf namespace sf
{ {
@ -44,10 +45,7 @@ FileInputStream::FileInputStream()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
FileInputStream::~FileInputStream() FileInputStream::~FileInputStream()
{ {
#ifdef SFML_SYSTEM_ANDROID #ifndef SFML_SYSTEM_ANDROID
if (m_file)
delete m_file;
#else
if (m_file) if (m_file)
std::fclose(m_file); std::fclose(m_file);
#endif #endif
@ -58,9 +56,7 @@ FileInputStream::~FileInputStream()
bool FileInputStream::open(const std::string& filename) bool FileInputStream::open(const std::string& filename)
{ {
#ifdef SFML_SYSTEM_ANDROID #ifdef SFML_SYSTEM_ANDROID
if (m_file) m_file = std::make_unique<priv::ResourceStream>(filename);
delete m_file;
m_file = new priv::ResourceStream(filename);
return m_file->tell() != -1; return m_file->tell() != -1;
#else #else
if (m_file) if (m_file)

View File

@ -60,8 +60,6 @@ Context::~Context()
{ {
err() << "Failed to set context as inactive during destruction" << std::endl; err() << "Failed to set context as inactive during destruction" << std::endl;
} }
delete m_context;
} }
@ -90,7 +88,7 @@ const Context* Context::getActiveContext()
using ContextImpl::currentContext; using ContextImpl::currentContext;
// We have to check that the last activated sf::Context is still active (a RenderTarget activation may have deactivated it) // We have to check that the last activated sf::Context is still active (a RenderTarget activation may have deactivated it)
if (currentContext && currentContext->m_context == priv::GlContext::getActiveContext()) if (currentContext && currentContext->m_context.get() == priv::GlContext::getActiveContext())
return currentContext; return currentContext;
else else
return nullptr; return nullptr;

View File

@ -27,23 +27,22 @@
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
#include <SFML/Window/Cursor.hpp> #include <SFML/Window/Cursor.hpp>
#include <SFML/Window/CursorImpl.hpp> #include <SFML/Window/CursorImpl.hpp>
#include <SFML/System/Vector2.hpp>
#include <memory>
namespace sf namespace sf
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Cursor::Cursor() : Cursor::Cursor() :
m_impl(new priv::CursorImpl()) m_impl(std::make_unique<priv::CursorImpl>())
{ {
// That's it
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Cursor::~Cursor() Cursor::~Cursor() = default;
{
delete m_impl;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -131,7 +131,7 @@ m_config (nullptr)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
EglContext::EglContext(EglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) : EglContext::EglContext(EglContext* shared, const ContextSettings& settings, const WindowImpl& owner, unsigned int bitsPerPixel) :
m_display (EGL_NO_DISPLAY), m_display (EGL_NO_DISPLAY),
m_context (EGL_NO_CONTEXT), m_context (EGL_NO_CONTEXT),
m_surface (EGL_NO_SURFACE), m_surface (EGL_NO_SURFACE),
@ -162,7 +162,7 @@ m_config (nullptr)
#if !defined(SFML_SYSTEM_ANDROID) #if !defined(SFML_SYSTEM_ANDROID)
// Create EGL surface (except on Android because the window is created // Create EGL surface (except on Android because the window is created
// asynchronously, its activity manager will call it for us) // asynchronously, its activity manager will call it for us)
createSurface(owner->getSystemHandle()); createSurface(owner.getSystemHandle());
#else #else
(void) owner; (void) owner;
#endif #endif

View File

@ -63,7 +63,7 @@ public:
/// \param bitsPerPixel Pixel depth, in bits per pixel /// \param bitsPerPixel Pixel depth, in bits per pixel
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
EglContext(EglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel); EglContext(EglContext* shared, const ContextSettings& settings, const WindowImpl& owner, unsigned int bitsPerPixel);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new context that embeds its own rendering target /// \brief Create a new context that embeds its own rendering target

View File

@ -31,16 +31,17 @@
#include <SFML/System/Err.hpp> #include <SFML/System/Err.hpp>
#include <glad/gl.h> #include <glad/gl.h>
#include <algorithm> #include <algorithm>
#include <vector> #include <memory>
#include <mutex>
#include <optional>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <utility> #include <utility>
#include <vector>
#include <cassert>
#include <cctype>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <cctype>
#include <cassert>
#include <mutex>
#include <optional>
#if defined(SFML_SYSTEM_WINDOWS) #if defined(SFML_SYSTEM_WINDOWS)
@ -166,7 +167,7 @@ namespace
thread_local sf::priv::GlContext* currentContext(nullptr); thread_local sf::priv::GlContext* currentContext(nullptr);
// The hidden, inactive context that will be shared with all other contexts // The hidden, inactive context that will be shared with all other contexts
ContextType* sharedContext = nullptr; std::unique_ptr<ContextType> sharedContext;
// Unique identifier, used for identifying contexts when managing unshareable OpenGL resources // Unique identifier, used for identifying contexts when managing unshareable OpenGL resources
sf::Uint64 id = 1; // start at 1, zero is "no context" sf::Uint64 id = 1; // start at 1, zero is "no context"
@ -194,7 +195,7 @@ namespace
{ {
if (resourceCount == 0) if (resourceCount == 0)
{ {
context = new sf::Context; context = std::make_unique<sf::Context>();
} }
else if (!currentContext) else if (!currentContext)
{ {
@ -214,7 +215,7 @@ namespace
sharedContext->setActive(false); sharedContext->setActive(false);
sharedContextLock.reset(); sharedContextLock.reset();
delete context; context.reset();
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
@ -233,14 +234,14 @@ namespace
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
unsigned int referenceCount; unsigned int referenceCount;
sf::Context* context; std::unique_ptr<sf::Context> context;
std::optional<std::scoped_lock<std::recursive_mutex>> sharedContextLock; std::optional<std::scoped_lock<std::recursive_mutex>> sharedContextLock;
bool useSharedContext; bool useSharedContext;
}; };
// This per-thread variable tracks if and how a transient // This per-thread variable tracks if and how a transient
// context is currently being used on the current thread // context is currently being used on the current thread
thread_local TransientContext* transientContext(nullptr); thread_local std::unique_ptr<TransientContext> transientContext;
// Supported OpenGL extensions // Supported OpenGL extensions
std::vector<std::string> extensions; std::vector<std::string> extensions;
@ -347,7 +348,7 @@ void GlContext::initResource()
} }
// Create the shared context // Create the shared context
sharedContext = new ContextType(nullptr); sharedContext = std::make_unique<ContextType>(nullptr);
sharedContext->initialize(ContextSettings()); sharedContext->initialize(ContextSettings());
// Load our extensions vector // Load our extensions vector
@ -382,8 +383,7 @@ void GlContext::cleanupResource()
return; return;
// Destroy the shared context // Destroy the shared context
delete sharedContext; sharedContext.reset();
sharedContext = nullptr;
} }
} }
@ -408,7 +408,7 @@ void GlContext::acquireTransientContext()
// If this is the first TransientContextLock on this thread // If this is the first TransientContextLock on this thread
// construct the state object // construct the state object
if (!transientContext) if (!transientContext)
transientContext = new TransientContext; transientContext = std::make_unique<TransientContext>();
// Increase the reference count // Increase the reference count
transientContext->referenceCount++; transientContext->referenceCount++;
@ -434,14 +434,13 @@ void GlContext::releaseTransientContext()
// destroy the state object // destroy the state object
if (transientContext->referenceCount == 0) if (transientContext->referenceCount == 0)
{ {
delete transientContext; transientContext.reset();
transientContext = nullptr;
} }
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlContext* GlContext::create() std::unique_ptr<GlContext> GlContext::create()
{ {
using GlContextImpl::mutex; using GlContextImpl::mutex;
using GlContextImpl::sharedContext; using GlContextImpl::sharedContext;
@ -451,7 +450,7 @@ GlContext* GlContext::create()
std::scoped_lock lock(mutex); std::scoped_lock lock(mutex);
GlContext* context = nullptr; std::unique_ptr<GlContext> context;
// We don't use acquireTransientContext here since we have // We don't use acquireTransientContext here since we have
// to ensure we have exclusive access to the shared context // to ensure we have exclusive access to the shared context
@ -460,7 +459,7 @@ GlContext* GlContext::create()
sharedContext->setActive(true); sharedContext->setActive(true);
// Create the context // Create the context
context = new ContextType(sharedContext); context = std::make_unique<ContextType>(sharedContext.get());
sharedContext->setActive(false); sharedContext->setActive(false);
} }
@ -472,7 +471,7 @@ GlContext* GlContext::create()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) std::unique_ptr<GlContext> GlContext::create(const ContextSettings& settings, const WindowImpl& owner, unsigned int bitsPerPixel)
{ {
using GlContextImpl::mutex; using GlContextImpl::mutex;
using GlContextImpl::resourceCount; using GlContextImpl::resourceCount;
@ -495,15 +494,14 @@ GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl*
// Re-create our shared context as a core context // Re-create our shared context as a core context
ContextSettings sharedSettings(0, 0, 0, settings.majorVersion, settings.minorVersion, settings.attributeFlags); ContextSettings sharedSettings(0, 0, 0, settings.majorVersion, settings.minorVersion, settings.attributeFlags);
delete sharedContext; sharedContext = std::make_unique<ContextType>(nullptr, sharedSettings, 1, 1);
sharedContext = new ContextType(nullptr, sharedSettings, 1, 1);
sharedContext->initialize(sharedSettings); sharedContext->initialize(sharedSettings);
// Reload our extensions vector // Reload our extensions vector
loadExtensions(); loadExtensions();
} }
GlContext* context = nullptr; std::unique_ptr<GlContext> context;
// We don't use acquireTransientContext here since we have // We don't use acquireTransientContext here since we have
// to ensure we have exclusive access to the shared context // to ensure we have exclusive access to the shared context
@ -512,7 +510,7 @@ GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl*
sharedContext->setActive(true); sharedContext->setActive(true);
// Create the context // Create the context
context = new ContextType(sharedContext, settings, owner, bitsPerPixel); context = std::make_unique<ContextType>(sharedContext.get(), settings, owner, bitsPerPixel);
sharedContext->setActive(false); sharedContext->setActive(false);
} }
@ -525,7 +523,7 @@ GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl*
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlContext* GlContext::create(const ContextSettings& settings, unsigned int width, unsigned int height) std::unique_ptr<GlContext> GlContext::create(const ContextSettings& settings, unsigned int width, unsigned int height)
{ {
using GlContextImpl::mutex; using GlContextImpl::mutex;
using GlContextImpl::resourceCount; using GlContextImpl::resourceCount;
@ -548,15 +546,14 @@ GlContext* GlContext::create(const ContextSettings& settings, unsigned int width
// Re-create our shared context as a core context // Re-create our shared context as a core context
ContextSettings sharedSettings(0, 0, 0, settings.majorVersion, settings.minorVersion, settings.attributeFlags); ContextSettings sharedSettings(0, 0, 0, settings.majorVersion, settings.minorVersion, settings.attributeFlags);
delete sharedContext; sharedContext = std::make_unique<ContextType>(nullptr, sharedSettings, 1, 1);
sharedContext = new ContextType(nullptr, sharedSettings, 1, 1);
sharedContext->initialize(sharedSettings); sharedContext->initialize(sharedSettings);
// Reload our extensions vector // Reload our extensions vector
loadExtensions(); loadExtensions();
} }
GlContext* context = nullptr; std::unique_ptr<GlContext> context;
// We don't use acquireTransientContext here since we have // We don't use acquireTransientContext here since we have
// to ensure we have exclusive access to the shared context // to ensure we have exclusive access to the shared context
@ -565,7 +562,7 @@ GlContext* GlContext::create(const ContextSettings& settings, unsigned int width
sharedContext->setActive(true); sharedContext->setActive(true);
// Create the context // Create the context
context = new ContextType(sharedContext, settings, width, height); context = std::make_unique<ContextType>(sharedContext.get(), settings, width, height);
sharedContext->setActive(false); sharedContext->setActive(false);
} }

View File

@ -32,6 +32,7 @@
#include <SFML/Window/Context.hpp> #include <SFML/Window/Context.hpp>
#include <SFML/Window/ContextSettings.hpp> #include <SFML/Window/ContextSettings.hpp>
#include <SFML/Window/GlResource.hpp> #include <SFML/Window/GlResource.hpp>
#include <memory>
namespace sf namespace sf
@ -100,10 +101,10 @@ public:
/// This function automatically chooses the specialized class /// This function automatically chooses the specialized class
/// to use according to the OS. /// to use according to the OS.
/// ///
/// \return Pointer to the created context (don't forget to delete it) /// \return Pointer to the created context
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static GlContext* create(); static std::unique_ptr<GlContext> create();
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new context attached to a window /// \brief Create a new context attached to a window
@ -118,7 +119,7 @@ public:
/// \return Pointer to the created context /// \return Pointer to the created context
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static GlContext* create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel); static std::unique_ptr<GlContext> create(const ContextSettings& settings, const WindowImpl& owner, unsigned int bitsPerPixel);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new context that embeds its own rendering target /// \brief Create a new context that embeds its own rendering target
@ -133,7 +134,7 @@ public:
/// \return Pointer to the created context /// \return Pointer to the created context
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static GlContext* create(const ContextSettings& settings, unsigned int width, unsigned int height); static std::unique_ptr<GlContext> create(const ContextSettings& settings, unsigned int width, unsigned int height);
public: public:
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -83,7 +83,7 @@ public:
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SFContext(SFContext* shared, const ContextSettings& settings, SFContext(SFContext* shared, const ContextSettings& settings,
const WindowImpl* owner, unsigned int bitsPerPixel); const WindowImpl& owner, unsigned int bitsPerPixel);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new context that embeds its own rendering target /// \brief Create a new context that embeds its own rendering target

View File

@ -63,7 +63,7 @@ m_window(0)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
SFContext::SFContext(SFContext* shared, const ContextSettings& settings, SFContext::SFContext(SFContext* shared, const ContextSettings& settings,
const WindowImpl* owner, unsigned int bitsPerPixel) : const WindowImpl& owner, unsigned int bitsPerPixel) :
m_context(0), m_context(0),
m_view(0), m_view(0),
m_window(0) m_window(0)
@ -73,8 +73,8 @@ m_window(0)
createContext(shared, bitsPerPixel, settings); createContext(shared, bitsPerPixel, settings);
// Apply context. // Apply context.
const WindowImplCocoa* ownerCocoa = static_cast<const WindowImplCocoa*>(owner); const auto& ownerCocoa = static_cast<const WindowImplCocoa&>(owner);
ownerCocoa->applyContext(m_context); ownerCocoa.applyContext(m_context);
} }

View File

@ -131,7 +131,7 @@ m_ownsWindow(false)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlxContext::GlxContext(GlxContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int /*bitsPerPixel*/) : GlxContext::GlxContext(GlxContext* shared, const ContextSettings& settings, const WindowImpl& owner, unsigned int /*bitsPerPixel*/) :
m_display (nullptr), m_display (nullptr),
m_window (0), m_window (0),
m_context (nullptr), m_context (nullptr),
@ -148,7 +148,7 @@ m_ownsWindow(false)
ensureExtensionsInit(m_display, DefaultScreen(m_display)); ensureExtensionsInit(m_display, DefaultScreen(m_display));
// Create the rendering surface from the owner window // Create the rendering surface from the owner window
createSurface(owner->getSystemHandle()); createSurface(owner.getSystemHandle());
// Create the context // Create the context
createContext(shared); createContext(shared);

View File

@ -62,7 +62,7 @@ public:
/// \param bitsPerPixel Pixel depth, in bits per pixel /// \param bitsPerPixel Pixel depth, in bits per pixel
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
GlxContext(GlxContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel); GlxContext(GlxContext* shared, const ContextSettings& settings, const WindowImpl& owner, unsigned int bitsPerPixel);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new context that embeds its own rendering target /// \brief Create a new context that embeds its own rendering target

View File

@ -108,7 +108,7 @@ WglContext(shared, ContextSettings(), 1u, 1u)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WglContext::WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel) : WglContext::WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl& owner, unsigned int bitsPerPixel) :
m_window (nullptr), m_window (nullptr),
m_pbuffer (nullptr), m_pbuffer (nullptr),
m_deviceContext(nullptr), m_deviceContext(nullptr),
@ -121,7 +121,7 @@ m_ownsWindow (false)
m_settings = settings; m_settings = settings;
// Create the rendering surface from the owner window // Create the rendering surface from the owner window
createSurface(owner->getSystemHandle(), bitsPerPixel); createSurface(owner.getSystemHandle(), bitsPerPixel);
// Create the context // Create the context
createContext(shared); createContext(shared);

View File

@ -61,7 +61,7 @@ public:
/// \param bitsPerPixel Pixel depth, in bits per pixel /// \param bitsPerPixel Pixel depth, in bits per pixel
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel); WglContext(WglContext* shared, const ContextSettings& settings, const WindowImpl& owner, unsigned int bitsPerPixel);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new context that embeds its own rendering target /// \brief Create a new context that embeds its own rendering target

View File

@ -36,7 +36,7 @@ namespace sf
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Window::Window() : Window::Window() :
m_context (nullptr), m_context (),
m_frameTimeLimit(Time::Zero) m_frameTimeLimit(Time::Zero)
{ {
@ -45,7 +45,7 @@ m_frameTimeLimit(Time::Zero)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Window::Window(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings) : Window::Window(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings) :
m_context (nullptr), m_context (),
m_frameTimeLimit(Time::Zero) m_frameTimeLimit(Time::Zero)
{ {
Window::create(mode, title, style, settings); Window::create(mode, title, style, settings);
@ -54,7 +54,7 @@ m_frameTimeLimit(Time::Zero)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
Window::Window(WindowHandle handle, const ContextSettings& settings) : Window::Window(WindowHandle handle, const ContextSettings& settings) :
m_context (nullptr), m_context (),
m_frameTimeLimit(Time::Zero) m_frameTimeLimit(Time::Zero)
{ {
Window::create(handle, settings); Window::create(handle, settings);
@ -119,7 +119,7 @@ void Window::create(VideoMode mode, const String& title, Uint32 style, const Con
m_impl = priv::WindowImpl::create(mode, title, style, settings); m_impl = priv::WindowImpl::create(mode, title, style, settings);
// Recreate the context // Recreate the context
m_context = priv::GlContext::create(settings, m_impl, mode.bitsPerPixel); m_context = priv::GlContext::create(settings, *m_impl, mode.bitsPerPixel);
// Perform common initializations // Perform common initializations
initialize(); initialize();
@ -143,7 +143,7 @@ void Window::create(WindowHandle handle, const ContextSettings& settings)
WindowBase::create(handle); WindowBase::create(handle);
// Recreate the context // Recreate the context
m_context = priv::GlContext::create(settings, m_impl, VideoMode::getDesktopMode().bitsPerPixel); m_context = priv::GlContext::create(settings, *m_impl, VideoMode::getDesktopMode().bitsPerPixel);
// Perform common initializations // Perform common initializations
initialize(); initialize();
@ -154,8 +154,7 @@ void Window::create(WindowHandle handle, const ContextSettings& settings)
void Window::close() void Window::close()
{ {
// Delete the context // Delete the context
delete m_context; m_context.reset();
m_context = nullptr;
// Close the base window // Close the base window
WindowBase::close(); WindowBase::close();

View File

@ -45,8 +45,8 @@ namespace sf
{ {
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowBase::WindowBase() : WindowBase::WindowBase() :
m_impl (nullptr), m_impl(),
m_size (0, 0) m_size(0, 0)
{ {
} }
@ -54,8 +54,8 @@ m_size (0, 0)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowBase::WindowBase(VideoMode mode, const String& title, Uint32 style) : WindowBase::WindowBase(VideoMode mode, const String& title, Uint32 style) :
m_impl (nullptr), m_impl(),
m_size (0, 0) m_size(0, 0)
{ {
WindowBase::create(mode, title, style); WindowBase::create(mode, title, style);
} }
@ -63,8 +63,8 @@ m_size (0, 0)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowBase::WindowBase(WindowHandle handle) : WindowBase::WindowBase(WindowHandle handle) :
m_impl (nullptr), m_impl(),
m_size (0, 0) m_size(0, 0)
{ {
WindowBase::create(handle); WindowBase::create(handle);
} }
@ -143,8 +143,7 @@ void WindowBase::create(WindowHandle handle)
void WindowBase::close() void WindowBase::close()
{ {
// Delete the window implementation // Delete the window implementation
delete m_impl; m_impl.reset();
m_impl = nullptr;
// Update the fullscreen window // Update the fullscreen window
if (this == getFullscreenWindow()) if (this == getFullscreenWindow())

View File

@ -32,6 +32,7 @@
#include <SFML/Window/SensorManager.hpp> #include <SFML/Window/SensorManager.hpp>
#include <SFML/System/Sleep.hpp> #include <SFML/System/Sleep.hpp>
#include <algorithm> #include <algorithm>
#include <memory>
#include <cmath> #include <cmath>
#if defined(SFML_SYSTEM_WINDOWS) #if defined(SFML_SYSTEM_WINDOWS)
@ -85,22 +86,22 @@ struct WindowImpl::JoystickStatesImpl
}; };
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImpl* WindowImpl::create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings) std::unique_ptr<WindowImpl> WindowImpl::create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings)
{ {
return new WindowImplType(mode, title, style, settings); return std::make_unique<WindowImplType>(mode, title, style, settings);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImpl* WindowImpl::create(WindowHandle handle) std::unique_ptr<WindowImpl> WindowImpl::create(WindowHandle handle)
{ {
return new WindowImplType(handle); return std::make_unique<WindowImplType>(handle);
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImpl::WindowImpl() : WindowImpl::WindowImpl() :
m_joystickStatesImpl(new JoystickStatesImpl), m_joystickStatesImpl(std::make_unique<JoystickStatesImpl>()),
m_joystickThreshold(0.1f) m_joystickThreshold(0.1f)
{ {
// Get the initial joystick states // Get the initial joystick states
@ -118,10 +119,7 @@ m_joystickThreshold(0.1f)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
WindowImpl::~WindowImpl() WindowImpl::~WindowImpl() = default;
{
delete m_joystickStatesImpl;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////

View File

@ -38,6 +38,7 @@
#include <SFML/Window/VideoMode.hpp> #include <SFML/Window/VideoMode.hpp>
#include <SFML/Window/Vulkan.hpp> #include <SFML/Window/Vulkan.hpp>
#include <SFML/Window/WindowHandle.hpp> #include <SFML/Window/WindowHandle.hpp>
#include <memory>
#include <queue> #include <queue>
#include <set> #include <set>
@ -64,20 +65,20 @@ public:
/// \param style Window style /// \param style Window style
/// \param settings Additional settings for the underlying OpenGL context /// \param settings Additional settings for the underlying OpenGL context
/// ///
/// \return Pointer to the created window (don't forget to delete it) /// \return Pointer to the created window
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static WindowImpl* create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings); static std::unique_ptr<WindowImpl> create(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new window depending on to the current OS /// \brief Create a new window depending on to the current OS
/// ///
/// \param handle Platform-specific handle of the control /// \param handle Platform-specific handle of the control
/// ///
/// \return Pointer to the created window (don't forget to delete it) /// \return Pointer to the created window
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
static WindowImpl* create(WindowHandle handle); static std::unique_ptr<WindowImpl> create(WindowHandle handle);
public: public:
@ -294,7 +295,7 @@ private:
// Member data // Member data
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
std::queue<Event> m_events; //!< Queue of available events std::queue<Event> m_events; //!< Queue of available events
JoystickStatesImpl* m_joystickStatesImpl; //!< Previous state of the joysticks (PImpl) std::unique_ptr<JoystickStatesImpl> m_joystickStatesImpl; //!< Previous state of the joysticks (PImpl)
Vector3f m_sensorValue[Sensor::Count]; //!< Previous value of the sensors Vector3f m_sensorValue[Sensor::Count]; //!< Previous value of the sensors
float m_joystickThreshold; //!< Joystick threshold (minimum motion for "move" event to be generated) float m_joystickThreshold; //!< Joystick threshold (minimum motion for "move" event to be generated)
float m_previousAxes[Joystick::Count][Joystick::AxisCount]; //!< Position of each axis last time a move event triggered, in range [-100, 100] float m_previousAxes[Joystick::Count][Joystick::AxisCount]; //!< Position of each axis last time a move event triggered, in range [-100, 100]

View File

@ -70,7 +70,7 @@ public:
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
EaglContext(EaglContext* shared, const ContextSettings& settings, EaglContext(EaglContext* shared, const ContextSettings& settings,
const WindowImpl* owner, unsigned int bitsPerPixel); const WindowImpl& owner, unsigned int bitsPerPixel);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
/// \brief Create a new context that embeds its own rendering target /// \brief Create a new context that embeds its own rendering target
@ -149,13 +149,13 @@ private:
/// \brief Create the context /// \brief Create the context
/// ///
/// \param shared Context to share the new one with (can be a null pointer) /// \param shared Context to share the new one with (can be a null pointer)
/// \param window Window to attach the context to (can be a null pointer) /// \param window Window to attach the context to
/// \param bitsPerPixel Pixel depth, in bits per pixel /// \param bitsPerPixel Pixel depth, in bits per pixel
/// \param settings Creation parameters /// \param settings Creation parameters
/// ///
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void createContext(EaglContext* shared, void createContext(EaglContext* shared,
const WindowImplUIKit* window, const WindowImplUIKit& window,
unsigned int bitsPerPixel, unsigned int bitsPerPixel,
const ContextSettings& settings); const ContextSettings& settings);

View File

@ -105,7 +105,7 @@ m_clock ()
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
EaglContext::EaglContext(EaglContext* shared, const ContextSettings& settings, EaglContext::EaglContext(EaglContext* shared, const ContextSettings& settings,
const WindowImpl* owner, unsigned int bitsPerPixel) : const WindowImpl& owner, unsigned int bitsPerPixel) :
m_context (nil), m_context (nil),
m_framebuffer (0), m_framebuffer (0),
m_colorbuffer (0), m_colorbuffer (0),
@ -115,7 +115,7 @@ m_clock ()
{ {
ensureInit(); ensureInit();
const WindowImplUIKit* window = static_cast<const WindowImplUIKit*>(owner); const auto& window = static_cast<const WindowImplUIKit&>(owner);
createContext(shared, window, bitsPerPixel, settings); createContext(shared, window, bitsPerPixel, settings);
} }
@ -286,7 +286,7 @@ void EaglContext::setVerticalSyncEnabled(bool enabled)
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
void EaglContext::createContext(EaglContext* shared, void EaglContext::createContext(EaglContext* shared,
const WindowImplUIKit* window, const WindowImplUIKit& window,
unsigned int /* bitsPerPixel */, unsigned int /* bitsPerPixel */,
const ContextSettings& settings) const ContextSettings& settings)
{ {
@ -318,10 +318,10 @@ void EaglContext::createContext(EaglContext* shared,
glGenFramebuffersOESFunc(1, &m_framebuffer); glGenFramebuffersOESFunc(1, &m_framebuffer);
// Create the render buffers // Create the render buffers
recreateRenderBuffers(window->getGlView()); recreateRenderBuffers(window.getGlView());
// Attach the context to the GL view for future updates // Attach the context to the GL view for future updates
window->getGlView().context = this; window.getGlView().context = this;
// Deactivate it // Deactivate it
makeCurrent(false); makeCurrent(false);