aboutsummaryrefslogtreecommitdiff
path: root/src/crepe/facade
diff options
context:
space:
mode:
Diffstat (limited to 'src/crepe/facade')
-rw-r--r--src/crepe/facade/CMakeLists.txt4
-rw-r--r--src/crepe/facade/Font.cpp23
-rw-r--r--src/crepe/facade/Font.h42
-rw-r--r--src/crepe/facade/FontFacade.cpp51
-rw-r--r--src/crepe/facade/FontFacade.h34
-rw-r--r--src/crepe/facade/SDLContext.cpp59
-rw-r--r--src/crepe/facade/SDLContext.h39
7 files changed, 245 insertions, 7 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 f331517..ada560b 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 <array>
#include <cmath>
#include <cstddef>
@@ -19,6 +20,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"
@@ -58,6 +62,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;
}
@@ -70,6 +78,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();
}
@@ -182,6 +191,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;
@@ -407,3 +462,7 @@ 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 b9c7fbd..01d82a0 100644
--- a/src/crepe/facade/SDLContext.h
+++ b/src/crepe/facade/SDLContext.h
@@ -12,16 +12,19 @@
#include <unordered_map>
#include "../types.h"
+#include "EventData.h"
#include "api/Camera.h"
#include "api/Color.h"
#include "api/KeyCodes.h"
#include "api/Sprite.h"
#include "api/Transform.h"
-#include "EventData.h"
+#include "FontFacade.h"
namespace crepe {
class Texture;
+class Text;
+class Font;
class Mediator;
/**
@@ -69,12 +72,11 @@ public:
const double & scale;
};
-public:
- /**
- * \brief Gets the singleton instance of SDLContext.
- * \return Reference to the SDLContext instance.
- */
- static SDLContext & get_instance();
+ struct RenderText {
+ const Text & text;
+ const Font & font;
+ const Transform & transform;
+ };
public:
SDLContext(const SDLContext &) = delete;
@@ -184,6 +186,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();
@@ -344,6 +353,22 @@ private:
{SDL_SCANCODE_RALT, Keycode::RIGHT_ALT},
{SDL_SCANCODE_RGUI, Keycode::RIGHT_SUPER},
{SDL_SCANCODE_MENU, Keycode::MENU}};
+
+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