diff options
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/crepe/api/AssetManager.h | 62 | ||||
-rw-r--r-- | src/crepe/api/Config.h | 11 | ||||
-rw-r--r-- | src/crepe/api/Text.cpp | 0 | ||||
-rw-r--r-- | src/crepe/api/Text.h | 35 | ||||
-rw-r--r-- | src/crepe/facade/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/crepe/facade/SDLFontContext.cpp | 54 | ||||
-rw-r--r-- | src/crepe/facade/SDLFontContext.h | 18 | ||||
-rw-r--r-- | src/crepe/facade/font.cpp | 21 | ||||
-rw-r--r-- | src/crepe/facade/font.h | 31 | ||||
-rw-r--r-- | src/example/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/example/loadfont.cpp | 13 |
12 files changed, 250 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 97b21f0..2b8873f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,7 @@ find_package(SoLoud REQUIRED) find_package(GTest REQUIRED) find_package(whereami REQUIRED) find_library(BERKELEY_DB db) +find_package(Fontconfig REQUIRED) add_library(crepe SHARED) add_executable(test_main EXCLUDE_FROM_ALL) @@ -27,6 +28,7 @@ target_link_libraries(crepe PUBLIC SDL2_image PUBLIC ${BERKELEY_DB} PUBLIC whereami + PUBLIC ${Fontconfig_LIBRARIES} ) add_subdirectory(crepe) diff --git a/src/crepe/api/AssetManager.h b/src/crepe/api/AssetManager.h new file mode 100644 index 0000000..3b1cc4b --- /dev/null +++ b/src/crepe/api/AssetManager.h @@ -0,0 +1,62 @@ +#pragma once + +#include <any> +#include <memory> +#include <string> +#include <unordered_map> + +namespace crepe { + +/** + * \brief The AssetManager is responsible for storing and managing assets over multiple scenes. + * + * The AssetManager ensures that assets are loaded once and can be accessed across different + * scenes. It caches assets to avoid reloading them every time a scene is loaded. Assets are + * retained in memory until the AssetManager is destroyed, at which point the cached assets are + * cleared. + */ +class AssetManager { + +private: + //! A cache that holds all the assets, accessible by their file path, over multiple scenes. + std::unordered_map<std::string, std::any> asset_cache; + +private: + AssetManager(); + virtual ~AssetManager(); + +public: + AssetManager(const AssetManager &) = delete; + AssetManager(AssetManager &&) = delete; + AssetManager & operator=(const AssetManager &) = delete; + AssetManager & operator=(AssetManager &&) = delete; + + /** + * \brief Retrieves the singleton instance of the AssetManager. + * + * \return A reference to the single instance of the AssetManager. + */ + static AssetManager & get_instance(); + +public: + /** + * \brief Caches an asset by loading it from the given file path. + * + * \param file_path The path to the asset file to load. + * \param reload If true, the asset will be reloaded from the file, even if it is already + * cached. + * \tparam T The type of asset to cache (e.g., texture, sound, etc.). + * + * \return A shared pointer to the cached asset. + * + * This template function caches the asset at the given file path. If the asset is already + * cached and `reload` is false, the existing cached version will be returned. Otherwise, the + * asset will be reloaded and added to the cache. + */ + template <typename T> + std::shared_ptr<T> cache(const std::string & file_path, bool reload = false); +}; + +} // namespace crepe + +#include "AssetManager.hpp" diff --git a/src/crepe/api/Config.h b/src/crepe/api/Config.h index 6472270..def4c49 100644 --- a/src/crepe/api/Config.h +++ b/src/crepe/api/Config.h @@ -76,6 +76,17 @@ struct Config final { */ std::string root_pattern = ".crepe-root"; } asset; + //! Default font options + struct { + /** + * \brief Default font size + * + * using the SDL_ttf library the font size needs to be set when loading the font. + * This config option is the font size at which all fonts will be loaded initially. + * + */ + int font_size = 16; + } font; //! Audio system settings struct { diff --git a/src/crepe/api/Text.cpp b/src/crepe/api/Text.cpp new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/crepe/api/Text.cpp diff --git a/src/crepe/api/Text.h b/src/crepe/api/Text.h new file mode 100644 index 0000000..9dd275b --- /dev/null +++ b/src/crepe/api/Text.h @@ -0,0 +1,35 @@ +#pragma once + +#include <string> + +#include "../Component.h" + +#include "Asset.h" +#include "Color.h" +#include "UIObject.h" + +namespace crepe{ +class Text : public UIObject{ +public: + Text(game_object_id_t id,const vec2 & dimensions, const vec2 & offset, const Asset & font, int font_size); + + //! Label text. + std::string text; + //! Label text color + Color text_color = Color::BLACK; + /** + * \brief fontsize for text rendering + * + * \note this is not the actual font size that is loaded in. + * + * Since SDL_TTF requires the font size when loading in the font it is not possible to switch the font size. + * The default font size that is loaded is set in the Config. + * Instead this value is used to upscale the font texture which can cause blurring or distorted text when upscaling or downscaling too much. + */ + int font_size = 16; + + const Asset source; +private: +}; + +} // namespace crepe diff --git a/src/crepe/facade/CMakeLists.txt b/src/crepe/facade/CMakeLists.txt index 0598e16..f4d71ff 100644 --- a/src/crepe/facade/CMakeLists.txt +++ b/src/crepe/facade/CMakeLists.txt @@ -4,6 +4,7 @@ target_sources(crepe PUBLIC SoundContext.cpp SDLContext.cpp DB.cpp + SDLFontContext.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -12,5 +13,6 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES SoundContext.h SDLContext.h DB.h + SDLFontContext.h ) diff --git a/src/crepe/facade/SDLFontContext.cpp b/src/crepe/facade/SDLFontContext.cpp new file mode 100644 index 0000000..a4be143 --- /dev/null +++ b/src/crepe/facade/SDLFontContext.cpp @@ -0,0 +1,54 @@ +#include <stdexcept> + +#include "SDLFontContext.h" + + +using namespace crepe; +using namespace std; + +SDLFontContext::SDLFontContext(){ + +} + +SDLFontContext::~SDLFontContext(){ + +} +unique_ptr<Asset> SDLFontContext::get_font_asset(const std::string & font_family) { + if (!FcInit()) { + throw std::runtime_error("Failed to initialize Fontconfig."); + } + // Create a pattern to search for the font family + FcPattern* pattern = FcNameParse(reinterpret_cast<const FcChar8*>(font_family.c_str())); + if (!pattern) { + throw std::runtime_error("Failed to create font pattern."); + } + + // Default configuration + FcConfig* config = FcConfigGetCurrent(); + if (!config) { + FcPatternDestroy(pattern); + throw std::runtime_error("Failed to get current Fontconfig configuration."); + } + + // Match the font pattern + FcResult result; + FcPattern* matched_pattern = FcFontMatch(config, pattern, &result); + FcPatternDestroy(pattern); + + if (!matched_pattern) { + throw std::runtime_error("No matching font found."); + } + + // Extract the file path + FcChar8* file_path = nullptr; + if (FcPatternGetString(matched_pattern, FC_FILE, 0, &file_path) != FcResultMatch || !file_path) { + FcPatternDestroy(matched_pattern); + throw std::runtime_error("Failed to get font file path."); + } + + // Convert the file path to a std::string + std::string font_file_path(reinterpret_cast<const char*>(file_path)); + FcPatternDestroy(matched_pattern); + FcFini(); + return std::move(make_unique<Asset>(font_file_path)); +} diff --git a/src/crepe/facade/SDLFontContext.h b/src/crepe/facade/SDLFontContext.h new file mode 100644 index 0000000..cd91383 --- /dev/null +++ b/src/crepe/facade/SDLFontContext.h @@ -0,0 +1,18 @@ +#pragma once + +#include <memory> +#include <SDL2/SDL_ttf.h> +#include <fontconfig/fontconfig.h> + +#include "../api/Asset.h" + +namespace crepe { + class SDLFontContext{ + public: + SDLFontContext(); + ~SDLFontContext(); + std::unique_ptr<Asset> get_font_asset(const std::string & font_family); + private: + }; + +} diff --git a/src/crepe/facade/font.cpp b/src/crepe/facade/font.cpp new file mode 100644 index 0000000..259a6cd --- /dev/null +++ b/src/crepe/facade/font.cpp @@ -0,0 +1,21 @@ +#include "font.h" +#include "../api/Config.h" +using namespace std; +using namespace crepe; + +void Font::load(unique_ptr<Asset> res){ + const char* font_path = res->get_path(); + int font_size = Config::get_instance().font.font_size; + this->font = std::unique_ptr<TTF_Font, decltype(&TTF_CloseFont)>( + TTF_OpenFont(font_path, font_size), &TTF_CloseFont); + + if (!font) { + throw std::runtime_error("Failed to load font: " + std::string(TTF_GetError())); + } +} +Font::Font(const char* src){ + this->load(make_unique<Asset>(src)); +} +Font::Font(std::unique_ptr<Asset> res){ + this->load(std::move(res)); +} diff --git a/src/crepe/facade/font.h b/src/crepe/facade/font.h new file mode 100644 index 0000000..a8d8040 --- /dev/null +++ b/src/crepe/facade/font.h @@ -0,0 +1,31 @@ +#pragma once + +#include <memory> +#include <SDL2/SDL_ttf.h> + +#include "../api/Asset.h" + +namespace crepe { + +/** + * \brief Font resource facade + * + * This class is a wrapper around an SDL_ttf font instance, encapsulating font loading and usage. + */ +class Font : public Resource{ +public: + /** + * \param res A unique pointer to an Asset holding the font resource. + */ + Font(const Asset & src, Mediator & mediator); + + /** + * \brief Destructor to clean up font resources. + */ + ~Font() = default; +private: + //! The SDL_ttf font object with custom deleter. + std::unique_ptr<TTF_Font, decltype(&TTF_CloseFont)> font; +}; + +} // namespace crepe diff --git a/src/example/CMakeLists.txt b/src/example/CMakeLists.txt index 187ed46..0e2d5e2 100644 --- a/src/example/CMakeLists.txt +++ b/src/example/CMakeLists.txt @@ -19,4 +19,5 @@ endfunction() add_example(rendering_particle) add_example(game) add_example(button) +add_example(loadfont) add_example(AITest) diff --git a/src/example/loadfont.cpp b/src/example/loadfont.cpp new file mode 100644 index 0000000..8931ce3 --- /dev/null +++ b/src/example/loadfont.cpp @@ -0,0 +1,13 @@ +#include <iostream> +#include <memory> + +#include <crepe/facade/SDLFontContext.h> + +using namespace crepe; + +int main(){ + SDLFontContext font_facade; + std::unique_ptr<Asset> asset = font_facade.get_font_asset("OpenSymbol"); + std::cout << "path: " << asset->get_path() << std::endl; + return 0; +} |