From dd4527645ee97f3c45eed615b745406db556cdd6 Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Sat, 7 Jun 2025 02:41:14 -0500 Subject: [PATCH] Add SDL2 support --- CMakeLists.txt | 22 ++++++- Config.cmake.in | 8 +++ TessesFrameworkFeatures.h.in | 3 + examples/sdl2.cpp | 28 +++++++++ include/TessesFramework/Common.hpp | 10 ++- include/TessesFramework/SDL2/FontCache.hpp | 28 +++++++++ include/TessesFramework/TessesFramework.hpp | 3 +- src/SDL2/FontCache.cpp | 69 +++++++++++++++++++++ src/TF_Init.cpp | 21 ++++++- 9 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 examples/sdl2.cpp create mode 100644 include/TessesFramework/SDL2/FontCache.hpp create mode 100644 src/SDL2/FontCache.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index e1c0718..50732d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ src/Crypto/MbedHelpers.cpp src/TF_Init.cpp src/wrapper.cpp src/HiddenField.cpp +src/SDL2/FontCache.cpp ) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) @@ -57,6 +58,7 @@ option(TESSESFRAMEWORK_ENABLE_STATIC "Enable Tesses Framework Static Libraries" option(TESSESFRAMEWORK_ENABLE_SHARED "Enable Tesses Framework Shared Libraries" ON) option(TESSESFRAMEWORK_ENABLE_SETDATE "Enable setting date to file" ON) option(TESSESFRAMEWORK_LOGTOFILE "TessesFramework Log to file" OFF) +option(TESSESFRAMEWORK_ENABLE_SDL2 "Enable SDL2" OFF) option(TESSESFRAMEWORK_FETCHCONTENT "TessesFramework fetchcontent" OFF) if(TESSESFRAMEWORK_FETCHCONTENT) set(TESSESFRAMEWORK_CERT_BUNDLE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ca-certificates.crt" CACHE FILEPATH "Path to ca-chain") @@ -67,6 +69,14 @@ endif() file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include) +if(TESSESFRAMEWORK_ENABLE_SDL2) + + +find_package(SDL2 REQUIRED) +find_package(SDL2_ttf REQUIRED) +find_package(SDL2_image REQUIRED) +endif() + if(TESSESFRAMEWORK_ENABLE_MBED) if(TESSESFRAMEWORK_EMBED_CERT_BUNDLE) include(cmake/bin2h.cmake) @@ -89,8 +99,8 @@ endif() FetchContent_Declare( mbedtls GIT_REPOSITORY https://github.com/Mbed-TLS/mbedtls.git + GIT_PROGRESS TRUE ) - FetchContent_MakeAvailable(mbedtls) else() set(MBEDTLS_DIR "" CACHE PATH "Mbed tls directory") @@ -120,6 +130,10 @@ endif() if(TESSESFRAMEWORK_ENABLE_NETWORKING) target_compile_definitions(${TessesFramework_TARGET} PUBLIC TESSESFRAMEWORK_ENABLE_NETWORKING) endif() +if(TESSESFRAMEWORK_ENABLE_SDL2) +target_link_libraries(${TessesFramework_TARGET} PUBLIC SDL2::SDL2 SDL2_image::SDL2_image SDL2_ttf::SDL2_ttf) +target_compile_definitions(${TessesFramework_TARGET} PUBLIC TESSESFRAMEWORK_ENABLE_SDL2) +endif() if(TESSESFRAMEWORK_ENABLE_MBED) target_compile_definitions(${TessesFramework_TARGET} PUBLIC TESSESFRAMEWORK_ENABLE_MBED) if(TESSESFRAMEWORK_EMBED_CERT_BUNDLE) @@ -170,6 +184,7 @@ if(TESSESFRAMEWORK_ENABLE_STATIC) add_library(tessesframework STATIC ${TESSESFRAMEWORK_SOURCE}) TESSESFRAMEWORK_LINKDEPS(tessesframework) + if(TESSESFRAMEWORK_FETCHCONTENT AND TESSESFRAMEWORK_ENABLE_MBED) target_link_libraries(tessesframework PUBLIC mbedtls mbedx509 mbedcrypto everest p256m) @@ -189,6 +204,7 @@ else() endif() add_library(tessesframework_shared SHARED ${TESSESFRAMEWORK_SOURCE}) TESSESFRAMEWORK_LINKDEPS(tessesframework_shared) + if(TESSESFRAMEWORK_FETCHCONTENT AND TESSESFRAMEWORK_ENABLE_MBED) target_link_libraries(tessesframework_shared PUBLIC mbedtls mbedx509 mbedcrypto everest p256m) @@ -235,6 +251,10 @@ DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/TessesFramework) endif() if(TESSESFRAMEWORK_ENABLE_EXAMPLES) + if(TESSESFRAMEWORK_ENABLE_SDL2) + add_executable(sdl2 examples/sdl2.cpp) + target_link_libraries(sdl2 PUBLIC tessesframework) + endif() add_executable(copyfile examples/copyfile.cpp) target_link_libraries(copyfile PUBLIC tessesframework) diff --git a/Config.cmake.in b/Config.cmake.in index dd0c310..df04e7f 100644 --- a/Config.cmake.in +++ b/Config.cmake.in @@ -17,5 +17,13 @@ if(${TESSESFRAMEWORK_ENABLE_LIBWEBCAM}) find_package(libwebcam) endif() +set(TESSESFRAMEWORK_ENABLE_SDL2 @TESSESFRAMEWORK_ENABLE_SDL2@) + +if(${TESSESFRAMEWORK_ENABLE_SDL2}) +find_package(SDL2 REQUIRED) +find_package(SDL2_ttf REQUIRED) +find_package(SDL2_image REQUIRED) +endif() + set(TESSESFRAMEWORK_ENABLE_NETWORKING @TESSESFRAMEWORK_ENABLE_NETWORKING@) set(TESSESFRAMEWORK_ENABLE_THREADING @TESSESFRAMEWORK_ENABLE_THREADING@) diff --git a/TessesFrameworkFeatures.h.in b/TessesFrameworkFeatures.h.in index 4550462..eb67ab6 100644 --- a/TessesFrameworkFeatures.h.in +++ b/TessesFrameworkFeatures.h.in @@ -16,5 +16,8 @@ #if TESSES_FRAMEWORK_FLAG_@TESSESFRAMEWORK_LOGTOFILE@ #define TESSESFRAMEWORK_LOGTOFILE #endif +#if TESSES_FRAMEWORK_FLAG_@TESSESFRAMEWORK_ENABLE_SDL2@ +#define TESSESFRAMEWORK_ENABLE_SDL2 +#endif #undef TESSES_FRAMEWORK_FLAG_OFF #undef TESSES_FRAMEWORK_FLAG_ON diff --git a/examples/sdl2.cpp b/examples/sdl2.cpp new file mode 100644 index 0000000..737972d --- /dev/null +++ b/examples/sdl2.cpp @@ -0,0 +1,28 @@ + +#if defined(TESSESFRAMEWORK_ENABLE_SDL2) +#include +#endif + +int main(int argc,char** argv) +{ + #if defined(TESSESFRAMEWORK_ENABLE_SDL2) + + SDL_Init(SDL_INIT_EVERYTHING); + + SDL_Window* window = SDL_CreateWindow("My SDL Window",0,0,320,240,0); + + SDL_Renderer* renderer=SDL_CreateRenderer(window,-1,SDL_RENDERER_ACCELERATED); + while(true) + { + SDL_Event event; + if(SDL_PollEvent(&event) && event.type == SDL_QUIT) break; + SDL_SetRenderDrawColor(renderer,255,0,0,255); + SDL_RenderClear(renderer); + SDL_RenderPresent(renderer); + } + SDL_DestroyRenderer(renderer); + + SDL_DestroyWindow(window); + #endif + return 0; +} \ No newline at end of file diff --git a/include/TessesFramework/Common.hpp b/include/TessesFramework/Common.hpp index 20a22f4..e19a84a 100644 --- a/include/TessesFramework/Common.hpp +++ b/include/TessesFramework/Common.hpp @@ -8,7 +8,7 @@ #include #include #include - +#include "Threading/Mutex.hpp" class TextException : public std::exception { std::string error_message; @@ -52,18 +52,22 @@ namespace Tesses::Framework template class EventList : public Event { + Threading::Mutex mtx; std::vector>> items; public: void operator+=(std::shared_ptr> event) { + mtx.Lock(); for(std::shared_ptr>& item : this->items) { if(item.get() == event.get()) return; } this->items.push_back(event); + mtx.Unlock(); } void operator-=(std::shared_ptr> event) { + mtx.Lock(); for(auto i = this->items.begin(); i != this->items.end(); i++) { if(i->get() == event.get()) @@ -72,13 +76,16 @@ namespace Tesses::Framework return; } } + mtx.Lock(); } void Invoke(TArgs... args) { + mtx.Lock(); for(auto& item : this->items) { item->Invoke(args...); } + mtx.Unlock(); } }; @@ -89,6 +96,7 @@ namespace Tesses::Framework void TF_RunEventLoop(); void TF_RunEventLoopItteration(); bool TF_IsRunning(); + void TF_SetIsRunning(bool _isRunning); void TF_Quit(); bool TF_GetConsoleEventsEnabled(); void TF_SetConsoleEventsEnabled(bool flag); diff --git a/include/TessesFramework/SDL2/FontCache.hpp b/include/TessesFramework/SDL2/FontCache.hpp new file mode 100644 index 0000000..52e7d53 --- /dev/null +++ b/include/TessesFramework/SDL2/FontCache.hpp @@ -0,0 +1,28 @@ +#pragma once +#if defined(TESSESFRAMEWORK_ENABLE_SDL2) +#include +#include +#include +#include +#include +namespace Tesses::Framework::SDL2 +{ +class FontCache +{ + std::array font_chrs; + int mw,mh,ps; + void Load(SDL_Renderer* renderer,TTF_Font* font,const SDL_Color& color); + public: + FontCache(SDL_Renderer* renderer,TTF_Font* font,const SDL_Color& color); + FontCache(SDL_Renderer* renderer,std::string font,int sz,const SDL_Color& color); + FontCache(SDL_Renderer* renderer,const uint8_t* mem,size_t cnt,int sz,const SDL_Color& color); + FontCache(SDL_Renderer* renderer,const std::vector& v,int sz,const SDL_Color& color); + + SDL_Texture* operator[](char c); + int MaxWidth(); + int MaxHeight(); + int PointSize(); + ~FontCache(); +}; +} +#endif \ No newline at end of file diff --git a/include/TessesFramework/TessesFramework.hpp b/include/TessesFramework/TessesFramework.hpp index 72f9d37..463c1fc 100644 --- a/include/TessesFramework/TessesFramework.hpp +++ b/include/TessesFramework/TessesFramework.hpp @@ -27,4 +27,5 @@ #include "Lazy.hpp" #include "Mail/Smtp.hpp" #include "HiddenField.hpp" -#include "Serialization/Json.hpp" \ No newline at end of file +#include "Serialization/Json.hpp" +#include "SDL2/FontCache.hpp" \ No newline at end of file diff --git a/src/SDL2/FontCache.cpp b/src/SDL2/FontCache.cpp new file mode 100644 index 0000000..69c3d56 --- /dev/null +++ b/src/SDL2/FontCache.cpp @@ -0,0 +1,69 @@ +#if defined(TESSESFRAMEWORK_ENABLE_SDL2) +#include "TessesFramework/SDL2/FontCache.hpp" +namespace Tesses::Framework::SDL2 { +void FontCache::Load(SDL_Renderer* renderer,TTF_Font* font,const SDL_Color& color) +{ + this->mw=0; + this->mh=0; + this->ps=ps; + + for(size_t i = 0; i < this->font_chrs.size();i++) + { + SDL_Surface* surf = TTF_RenderGlyph_Blended(font,(Uint16)(i+32),color); + if(surf->w > this->mw) mw = surf->w; + if(surf->h > this->mh) mh = surf->h; + this->font_chrs[i] = SDL_CreateTextureFromSurface(renderer,surf); + SDL_FreeSurface(surf); + + } +} +FontCache::FontCache(SDL_Renderer* renderer,std::string font,int sz,const SDL_Color& color) +{ + TTF_Font* f = TTF_OpenFont(font.c_str(),sz); + Load(renderer,f,color); + TTF_CloseFont(f); +} +FontCache::FontCache(SDL_Renderer* renderer,const uint8_t* mem,size_t cnt,int sz,const SDL_Color& color) +{ + + TTF_Font* f = TTF_OpenFontRW(SDL_RWFromConstMem(mem,cnt),1,sz); + Load(renderer,f,color); + TTF_CloseFont(f); +} +FontCache::FontCache(SDL_Renderer* renderer,const std::vector& v,int sz,const SDL_Color& color) : FontCache(renderer,v.data(),v.size(),sz,color) +{ + +} +FontCache::FontCache(SDL_Renderer* renderer,TTF_Font* font,const SDL_Color& color) +{ + this->Load(renderer,font,color); +} + +SDL_Texture* FontCache::operator[](char c) +{ + if(c >= 32 && c <= 126) + { + return this->font_chrs[c-32]; + } + return this->font_chrs[95]; +} +FontCache::~FontCache() +{ + for(auto item : this->font_chrs) + SDL_DestroyTexture(item); +} +int FontCache::MaxWidth() +{ + return this->mw; +} +int FontCache::MaxHeight() +{ + return this->mh; +} + +int FontCache::PointSize() +{ + return this->ps; +} +} +#endif \ No newline at end of file diff --git a/src/TF_Init.cpp b/src/TF_Init.cpp index e0df690..25a4bc9 100644 --- a/src/TF_Init.cpp +++ b/src/TF_Init.cpp @@ -33,6 +33,9 @@ static GXRModeObj *rmode = NULL; #if defined(TESSESFRAMEWORK_ENABLE_THREADING) #include "TessesFramework/Threading/Mutex.hpp" #endif +#if defined(TESSESFRAMEWORK_ENABLE_SDL2) +#include +#endif namespace Tesses::Framework { @@ -59,6 +62,11 @@ namespace Tesses::Framework static void _sigInt(int c) { isRunningSig=false; + #if defined(TESSESFRAMEWORK_ENABLE_SDL2) + SDL_Event quitEvent; + quitEvent.type = SDL_QUIT; + SDL_PushEvent(&quitEvent); + #endif } void TF_RunEventLoop() { @@ -108,16 +116,27 @@ namespace Tesses::Framework #endif } - + void TF_SetIsRunning(bool _isRunning) + { + isRunning = _isRunning; + } void TF_Quit() { isRunning=false; #if defined(TESSESFRAMEWORK_ENABLE_THREADING) && (defined(GEKKO) || defined(__SWITCH__)) Tesses::Framework::Threading::JoinAllThreads(); #endif + #if defined(TESSESFRAMEWORK_ENABLE_SDL2) + SDL_Quit(); + #endif } void TF_Init() { + #if defined(TESSESFRAMEWORK_ENABLE_SDL2) + //SDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS,"1"); + SDL_Init(SDL_INIT_EVERYTHING); + #endif + tzset(); #if defined(_WIN32) system(" ");