LCOV - code coverage report
Current view: top level - src/gui - window_context.cpp (source / functions) Coverage Total Hit
Test: merged.info Lines: 3.2 % 157 5
Test Date: 2026-06-07 15:51:50 Functions: 30.0 % 10 3

            Line data    Source code
       1              : #include "gui/window_context.h"
       2              : 
       3              : #include <SDL2/SDL.h>
       4              : #include <imgui.h>
       5              : #include <imgui_impl_opengl3.h>
       6              : #include <imgui_impl_sdl2.h>
       7              : 
       8              : #include <iostream>
       9              : 
      10              : #include "gui/gl_setup.h"
      11              : #include "gui/state/gui_graph_state.h"
      12              : #include "gui/theme/theme.h"
      13              : 
      14              : #ifdef __EMSCRIPTEN__
      15              : #include <emscripten.h>
      16              : #endif
      17              : 
      18              : #pragma GCC diagnostic push
      19              : #if defined(__GNUC__) && !defined(__clang__)
      20              : #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
      21              : #endif
      22              : #define NANOSVG_IMPLEMENTATION
      23              : #include "nanosvg.h"
      24              : #define NANOSVGRAST_IMPLEMENTATION
      25              : #include "nanosvgrast.h"
      26              : #pragma GCC diagnostic pop
      27              : 
      28              : namespace Amplitron {
      29              : 
      30           20 : WindowContext::WindowContext() = default;
      31              : 
      32           20 : WindowContext::~WindowContext() { shutdown(); }
      33              : 
      34            0 : bool WindowContext::initialize(int width, int height, const std::string& title) {
      35            0 :     width_ = width;
      36            0 :     height_ = height;
      37              : 
      38            0 :     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) {
      39            0 :         std::cerr << "SDL_Init failed: " << SDL_GetError() << std::endl;
      40            0 :         return false;
      41              :     }
      42              : 
      43            0 :     SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0);
      44            0 :     SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, GLSetup::GL_CONTEXT_PROFILE);
      45            0 :     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, GLSetup::GL_MAJOR);
      46            0 :     SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, GLSetup::GL_MINOR);
      47            0 :     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
      48            0 :     SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
      49            0 :     SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
      50              : 
      51            0 :     window_ = SDL_CreateWindow(title.c_str(), SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
      52            0 :                                width_, height_,
      53              :                                SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
      54              : 
      55            0 :     if (!window_) {
      56            0 :         std::cerr << "SDL_CreateWindow failed: " << SDL_GetError() << std::endl;
      57            0 :         SDL_Quit();
      58            0 :         return false;
      59              :     }
      60              : 
      61            0 :     gl_context_ = SDL_GL_CreateContext(window_);
      62            0 :     if (!gl_context_) {
      63            0 :         std::cerr << "SDL_GL_CreateContext failed: " << SDL_GetError() << std::endl;
      64            0 :         SDL_DestroyWindow(window_);
      65            0 :         window_ = nullptr;
      66            0 :         SDL_Quit();
      67            0 :         return false;
      68              :     }
      69            0 :     SDL_GL_MakeCurrent(window_, gl_context_);
      70            0 :     SDL_GL_SetSwapInterval(1);  // vsync
      71              : 
      72              :     // Initialize ImGui
      73            0 :     IMGUI_CHECKVERSION();
      74            0 :     ImGui::CreateContext();
      75            0 :     ImGuiIO& io = ImGui::GetIO();
      76            0 :     io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
      77              : 
      78            0 :     ImGui::StyleColorsDark();
      79            0 :     Theme::ApplyStyle();
      80              : 
      81            0 :     if (window_) {
      82            0 :         SDL_GetWindowSize(window_, &width_, &height_);
      83            0 :     }
      84              : 
      85            0 :     load_fonts();
      86            0 :     load_icon();
      87              : 
      88            0 :     ImGui_ImplSDL2_InitForOpenGL(window_, gl_context_);
      89            0 :     ImGui_ImplOpenGL3_Init(GLSetup::GLSL_VERSION);
      90              : 
      91            0 :     initialized_ = true;
      92            0 :     return true;
      93            0 : }
      94              : 
      95            0 : void WindowContext::load_fonts() {
      96            0 :     dpi_scale_ = 1.0f;
      97            0 :     int draw_w = width_, draw_h = height_;
      98            0 :     SDL_GL_GetDrawableSize(window_, &draw_w, &draw_h);
      99            0 :     if (width_ > 0) {
     100            0 :         dpi_scale_ = static_cast<float>(draw_w) / static_cast<float>(width_);
     101            0 :     }
     102              : 
     103              : #ifdef __EMSCRIPTEN__
     104              :     if (dpi_scale_ <= 1.0f) {
     105              :         dpi_scale_ = emscripten_get_device_pixel_ratio();
     106              :         if (dpi_scale_ <= 0.0f) {
     107              :             dpi_scale_ = 1.0f;
     108              :         }
     109              :     }
     110              : #endif
     111              : 
     112            0 :     GuiGraphState::get_instance().dpi_scale = dpi_scale_;
     113            0 :     ImGuiIO& io = ImGui::GetIO();
     114              : 
     115            0 :     const float base_font_size = 14.0f;
     116            0 :     const float scaled_size = base_font_size;
     117              : 
     118            0 :     ImFont* loaded_font = nullptr;
     119            0 :     auto try_font = [&](const std::string& path) {
     120            0 :         if (!loaded_font) {
     121            0 :             loaded_font = io.Fonts->AddFontFromFileTTF(path.c_str(), scaled_size);
     122            0 :         }
     123            0 :     };
     124              : 
     125            0 :     char* base_path = SDL_GetBasePath();
     126            0 :     if (base_path) {
     127            0 :         try_font(std::string(base_path) + "assets/fonts/Roboto-Medium.ttf");
     128            0 :         SDL_free(base_path);
     129            0 :     }
     130            0 :     try_font("assets/fonts/Roboto-Medium.ttf");
     131              : #ifdef __EMSCRIPTEN__
     132              :     try_font("/assets/fonts/Roboto-Medium.ttf");
     133              : #endif
     134            0 :     try_font("../assets/fonts/Roboto-Medium.ttf");
     135            0 :     try_font("external/imgui/misc/fonts/Roboto-Medium.ttf");
     136            0 :     try_font("../external/imgui/misc/fonts/Roboto-Medium.ttf");
     137              : 
     138            0 :     if (!loaded_font) {
     139            0 :         io.Fonts->AddFontDefault();
     140            0 :     } else {
     141            0 :         io.FontGlobalScale = 1.0f;
     142              :     }
     143            0 : }
     144              : 
     145            0 : void WindowContext::load_icon() {
     146            0 :     std::string icon_path;
     147            0 :     char* base = SDL_GetBasePath();
     148            0 :     if (base) {
     149            0 :         icon_path = std::string(base) + "assets/icon.svg";
     150            0 :         SDL_free(base);
     151            0 :     }
     152            0 :     NSVGimage* svg = nullptr;
     153            0 :     if (!icon_path.empty()) {
     154            0 :         svg = nsvgParseFromFile(icon_path.c_str(), "px", 96.0f);
     155            0 :     }
     156            0 :     if (!svg) {
     157            0 :         svg = nsvgParseFromFile("../assets/icon.svg", "px", 96.0f);
     158            0 :     }
     159            0 :     if (!svg) {
     160            0 :         svg = nsvgParseFromFile("assets/icon.svg", "px", 96.0f);
     161            0 :     }
     162              : 
     163            0 :     if (svg) {
     164            0 :         const int icon_size = 64;
     165            0 :         NSVGrasterizer* rast = nsvgCreateRasterizer();
     166            0 :         if (rast) {
     167            0 :             unsigned char* img = new unsigned char[icon_size * icon_size * 4];
     168            0 :             nsvgRasterize(rast, svg, 0, 0, icon_size / svg->width, img, icon_size, icon_size,
     169              :                           icon_size * 4);
     170              : 
     171            0 :             SDL_Surface* icon =
     172            0 :                 SDL_CreateRGBSurfaceFrom(img, icon_size, icon_size, 32, icon_size * 4, 0x000000FF,
     173              :                                          0x0000FF00, 0x00FF0000, 0xFF000000);
     174            0 :             if (icon) {
     175            0 :                 SDL_SetWindowIcon(window_, icon);
     176            0 :                 SDL_FreeSurface(icon);
     177            0 :             }
     178            0 :             delete[] img;
     179            0 :             nsvgDeleteRasterizer(rast);
     180            0 :         }
     181            0 :         nsvgDelete(svg);
     182            0 :     } else {
     183            0 :         std::cerr << "Warning: Could not load assets/icon.svg" << std::endl;
     184              :     }
     185            0 : }
     186              : 
     187           15 : void WindowContext::shutdown() {
     188           15 :     if (!initialized_) return;
     189            0 :     initialized_ = false;
     190              : 
     191            0 :     ImGui_ImplOpenGL3_Shutdown();
     192            0 :     ImGui_ImplSDL2_Shutdown();
     193            0 :     ImGui::DestroyContext();
     194              : 
     195            0 :     if (gl_context_) {
     196            0 :         SDL_GL_DeleteContext(gl_context_);
     197            0 :         gl_context_ = nullptr;
     198            0 :     }
     199            0 :     if (window_) {
     200            0 :         SDL_DestroyWindow(window_);
     201            0 :         window_ = nullptr;
     202            0 :     }
     203            0 :     SDL_Quit();
     204            5 : }
     205              : 
     206            0 : bool WindowContext::poll_events() {
     207            0 :     SDL_Event event;
     208            0 :     while (SDL_PollEvent(&event)) {
     209            0 :         ImGui_ImplSDL2_ProcessEvent(&event);
     210            0 :         if (event.type == SDL_QUIT) return false;
     211            0 :         if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE &&
     212            0 :             event.window.windowID == SDL_GetWindowID(window_))
     213            0 :             return false;
     214              :     }
     215            0 :     if (window_) {
     216            0 :         SDL_GetWindowSize(window_, &width_, &height_);
     217            0 :     }
     218            0 :     return true;
     219            0 : }
     220              : 
     221            0 : void WindowContext::begin_frame() {
     222            0 :     ImGui_ImplOpenGL3_NewFrame();
     223            0 :     ImGui_ImplSDL2_NewFrame();
     224            0 :     ImGui::NewFrame();
     225            0 : }
     226              : 
     227            0 : void WindowContext::end_frame() {
     228            0 :     ImGui::Render();
     229            0 :     int display_w, display_h;
     230            0 :     SDL_GL_GetDrawableSize(window_, &display_w, &display_h);
     231            0 :     glViewport(0, 0, display_w, display_h);
     232            0 :     glClearColor(0.078f, 0.071f, 0.063f, 1.0f);
     233            0 :     glClear(GL_COLOR_BUFFER_BIT);
     234            0 :     ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
     235            0 :     SDL_GL_SwapWindow(window_);
     236            0 : }
     237              : 
     238              : }  // namespace Amplitron
        

Generated by: LCOV version 2.0-1