diff options
Diffstat (limited to 'src/crepe/facade')
-rw-r--r-- | src/crepe/facade/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/crepe/facade/Font.cpp | 23 | ||||
-rw-r--r-- | src/crepe/facade/Font.h | 42 | ||||
-rw-r--r-- | src/crepe/facade/FontFacade.cpp | 51 | ||||
-rw-r--r-- | src/crepe/facade/FontFacade.h | 34 | ||||
-rw-r--r-- | src/crepe/facade/SDLContext.cpp | 60 | ||||
-rw-r--r-- | src/crepe/facade/SDLContext.h | 34 |
7 files changed, 247 insertions, 1 deletions
diff --git a/src/crepe/facade/CMakeLists.txt b/src/crepe/facade/CMakeLists.txt index 0598e16..243ae46 100644 --- a/src/crepe/facade/CMakeLists.txt +++ b/src/crepe/facade/CMakeLists.txt @@ -4,6 +4,8 @@ target_sources(crepe PUBLIC SoundContext.cpp SDLContext.cpp DB.cpp + FontFacade.cpp + Font.cpp ) target_sources(crepe PUBLIC FILE_SET HEADERS FILES @@ -12,5 +14,7 @@ target_sources(crepe PUBLIC FILE_SET HEADERS FILES SoundContext.h SDLContext.h DB.h + FontFacade.h + Font.h ) diff --git a/src/crepe/facade/Font.cpp b/src/crepe/facade/Font.cpp new file mode 100644 index 0000000..4694f7c --- /dev/null +++ b/src/crepe/facade/Font.cpp @@ -0,0 +1,23 @@ +#include <SDL2/SDL_ttf.h> + +#include "../api/Asset.h" +#include "../api/Config.h" +#include <string> + +#include "Font.h" + +using namespace std; +using namespace crepe; + +Font::Font(const Asset & src, Mediator & mediator) : Resource(src, mediator) { + Config & config = Config::get_instance(); + const std::string FONT_PATH = src.get_path(); + + TTF_Font * loaded_font = TTF_OpenFont(FONT_PATH.c_str(), config.font.size); + if (loaded_font == NULL) { + throw runtime_error(format("Font: {} (path: {})", TTF_GetError(), FONT_PATH)); + } + this->font = {loaded_font, [](TTF_Font * close_font) { TTF_CloseFont(close_font); }}; +} + +TTF_Font * Font::get_font() const { return this->font.get(); } diff --git a/src/crepe/facade/Font.h b/src/crepe/facade/Font.h new file mode 100644 index 0000000..b08366d --- /dev/null +++ b/src/crepe/facade/Font.h @@ -0,0 +1,42 @@ +#pragma once + +#include <SDL2/SDL_ttf.h> +#include <functional> +#include <memory> + +#include "../Resource.h" + +namespace crepe { + +class Asset; +/** + * \brief Resource for managing font creation and destruction + * + * This class is a wrapper around an SDL_ttf font instance, encapsulating font loading and usage. + * It loads a font from an Asset and manages its lifecycle. The font is automatically unloaded + * when this object is destroyed. + */ +class Font : public Resource { + +public: + /** + * \param src The Asset containing the font file path and metadata to load the font. + * \param mediator The Mediator object used for managing the SDL context or related systems. + */ + Font(const Asset & src, Mediator & mediator); + /** + * \brief Gets the underlying TTF_Font resource. + * + * This function returns the raw pointer to the SDL_ttf TTF_Font object that represents + * the loaded font. This can be used with SDL_ttf functions to render text. + * + * \return The raw TTF_Font object wrapped in a unique pointer. + */ + TTF_Font * get_font() const; + +private: + //! The SDL_ttf font object with custom deleter. + std::unique_ptr<TTF_Font, std::function<void(TTF_Font *)>> font = nullptr; +}; + +} // namespace crepe diff --git a/src/crepe/facade/FontFacade.cpp b/src/crepe/facade/FontFacade.cpp new file mode 100644 index 0000000..cec3507 --- /dev/null +++ b/src/crepe/facade/FontFacade.cpp @@ -0,0 +1,51 @@ +#include <fontconfig/fontconfig.h> +#include <iostream> +#include <stdexcept> + +#include "FontFacade.h" + +using namespace crepe; +using namespace std; + +FontFacade::FontFacade() { + if (!FcInit()) { + throw runtime_error("Failed to initialize Fontconfig."); + } +} +FontFacade::~FontFacade() { FcFini(); } +Asset FontFacade::get_font_asset(const string & font_family) { + + // Create a pattern to search for the font family + FcPattern * pattern = FcNameParse(reinterpret_cast<const FcChar8 *>(font_family.c_str())); + if (!pattern) { + throw runtime_error("Failed to create font pattern."); + } + + // Default configuration + FcConfig * config = FcConfigGetCurrent(); + if (config == NULL) { + // FcPatternDestroy(pattern); + throw 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 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 == NULL) { + // FcPatternDestroy(matched_pattern); + throw runtime_error("Failed to get font file path."); + } + + // Convert the file path to a string + string font_file_path = reinterpret_cast<const char *>(file_path); + FcPatternDestroy(matched_pattern); + return Asset(font_file_path); +} diff --git a/src/crepe/facade/FontFacade.h b/src/crepe/facade/FontFacade.h new file mode 100644 index 0000000..9761070 --- /dev/null +++ b/src/crepe/facade/FontFacade.h @@ -0,0 +1,34 @@ +#pragma once + +#include <memory> + +#include "../api/Asset.h" + +namespace crepe { + +/** + * + * \brief Font facade class for converting font family names to absolute file paths + * + */ +class FontFacade { +public: + FontFacade(); + ~FontFacade(); + FontFacade(const FontFacade & other) = delete; + FontFacade & operator=(const FontFacade & other) = delete; + FontFacade(FontFacade && other) noexcept = delete; + FontFacade & operator=(FontFacade && other) noexcept = delete; + /** + * + * \brief Facade function to convert a font_family into an asset. + * + * This function uses the FontConfig library to convert a font family name (Arial, Inter, Helvetica) and converts it to the font source path. + * This function returns a default font path if the font_family name doesnt exist or cant be found + * \param font_family Name of the font family name. + * \return Asset with filepath to the corresponding font. + */ + Asset get_font_asset(const std::string & font_family); +}; + +} // namespace crepe diff --git a/src/crepe/facade/SDLContext.cpp b/src/crepe/facade/SDLContext.cpp index 20bb030..c3c1b59 100644 --- a/src/crepe/facade/SDLContext.cpp +++ b/src/crepe/facade/SDLContext.cpp @@ -6,6 +6,7 @@ #include <SDL2/SDL_rect.h> #include <SDL2/SDL_render.h> #include <SDL2/SDL_surface.h> +#include <SDL2/SDL_ttf.h> #include <SDL2/SDL_video.h> #include <array> #include <cmath> @@ -20,6 +21,9 @@ #include "../api/Config.h" #include "../api/Sprite.h" #include "../util/Log.h" +#include "api/Text.h" +#include "api/Transform.h" +#include "facade/Font.h" #include "manager/Mediator.h" #include "SDLContext.h" @@ -59,6 +63,10 @@ SDLContext::SDLContext(Mediator & mediator) { throw runtime_error("SDLContext: SDL_image could not initialize!"); } + if (TTF_Init() == -1) { + throw runtime_error(format("SDL_ttf initialization failed: {}", TTF_GetError())); + } + mediator.sdl_context = *this; } @@ -71,6 +79,7 @@ SDLContext::~SDLContext() { // TODO: how are we going to ensure that these are called from the same // thread that SDL_Init() was called on? This has caused problems for me // before. + TTF_Quit(); IMG_Quit(); SDL_Quit(); } @@ -278,6 +287,52 @@ void SDLContext::draw(const RenderContext & ctx) { angle, NULL, render_flip); } +void SDLContext::draw_text(const RenderText & data) { + + const Text & text = data.text; + const Font & font = data.font; + const Transform & transform = data.transform; + std::unique_ptr<SDL_Surface, std::function<void(SDL_Surface *)>> font_surface; + std::unique_ptr<SDL_Texture, std::function<void(SDL_Texture *)>> font_texture; + + SDL_Color color{ + .r = text.data.text_color.r, + .g = text.data.text_color.g, + .b = text.data.text_color.b, + .a = text.data.text_color.a, + }; + SDL_Surface * tmp_font_surface + = TTF_RenderText_Solid(font.get_font(), text.text.c_str(), color); + if (!tmp_font_surface) { + throw runtime_error(format("draw_text: font surface error: {}", SDL_GetError())); + } + font_surface = {tmp_font_surface, [](SDL_Surface * surface) { SDL_FreeSurface(surface); }}; + + SDL_Texture * tmp_font_texture + = SDL_CreateTextureFromSurface(this->game_renderer.get(), font_surface.get()); + if (!tmp_font_texture) { + throw runtime_error(format("draw_text: font texture error: {}", SDL_GetError())); + } + font_texture + = {tmp_font_texture, [](SDL_Texture * texture) { SDL_DestroyTexture(texture); }}; + + vec2 size = text.dimensions * cam_aux_data.render_scale; + vec2 screen_pos = (transform.position + text.offset - cam_aux_data.cam_pos + + (cam_aux_data.zoomed_viewport) / 2) + * cam_aux_data.render_scale + - size / 2 + cam_aux_data.bar_size; + + SDL_FRect dstrect{ + .x = screen_pos.x, + .y = screen_pos.y, + .w = size.x, + .h = size.y, + }; + + SDL_RenderCopyExF(this->game_renderer.get(), font_texture.get(), NULL, &dstrect, 0, NULL, + SDL_FLIP_NONE); +} + void SDLContext::update_camera_view(const Camera & cam, const vec2 & new_pos) { const Camera::Data & cam_data = cam.data; @@ -429,7 +484,12 @@ std::vector<SDLContext::EventData> SDLContext::get_events() { } return event_list; } + void SDLContext::set_color_texture(const Texture & texture, const Color & color) { SDL_SetTextureColorMod(texture.get_img(), color.r, color.g, color.b); SDL_SetTextureAlphaMod(texture.get_img(), color.a); } + +Asset SDLContext::get_font_from_name(const std::string & font_family) { + return this->font_facade.get_font_asset(font_family); +} diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index bcadf87..aeace07 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -15,12 +15,15 @@ #include "api/KeyCodes.h" #include "api/Sprite.h" #include "api/Transform.h" - #include "types.h" +#include "FontFacade.h" + namespace crepe { class Texture; +class Text; +class Font; class Mediator; /** @@ -68,6 +71,12 @@ public: const double & scale; }; + struct RenderText { + const Text & text; + const Font & font; + const Transform & transform; + }; + public: //! EventType enum for passing eventType enum EventType { @@ -184,6 +193,13 @@ public: */ void draw(const RenderContext & ctx); + /** + * \brief draws a text to the screen + * + * \param data Reference to the rendering data needed to draw + */ + void draw_text(const RenderText & data); + //! Clears the screen, preparing for a new frame. void clear_screen(); @@ -240,6 +256,22 @@ private: * - this is defined in this class because get_events() needs this information aswell */ CameraAuxiliaryData cam_aux_data; + +private: + //! instance of the font_facade + FontFacade font_facade{}; + +public: + /** + * \brief Function to Get asset from font_family + * + * This function uses the FontFacade function to convert a font_family to an asset. + * + * \param font_family name of the font style that needs to be used (will return an asset with default font path of the font_family doesnt exist) + * + * \return asset with the font style absolute path + */ + Asset get_font_from_name(const std::string & font_family); }; } // namespace crepe |