From f2e672f84d8cd45971c415c67d69237d09a8033a Mon Sep 17 00:00:00 2001 From: admin Date: Sat, 24 May 2025 19:17:27 +0200 Subject: changed to sdl3 and added linux/cross-compilation --- src/glamac/glamac.c | 43 +++++----- src/glamac/glamac_events.c | 84 +++++++++----------- src/glamac/glamac_render.c | 194 +++++++++++++++++++++++++++++++-------------- src/glamac/glamac_view.c | 19 ++--- 4 files changed, 197 insertions(+), 143 deletions(-) (limited to 'src') diff --git a/src/glamac/glamac.c b/src/glamac/glamac.c index d176403..b834dbc 100644 --- a/src/glamac/glamac.c +++ b/src/glamac/glamac.c @@ -1,17 +1,8 @@ /** * glamac.c - main source file for the GlaMaC. - * - * Copyright (C) 2025 https://optics-design.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * See the COPYING file for the full license text. */ -#include -#include +#include +#include #include #include "glamacdef.h" // Type definitions #include "glass_data.h" // Glass catalog @@ -31,23 +22,22 @@ int main(int argc, char* argv[]) { SDL_Renderer* renderer = NULL; FontSet fonts = {0}; - // Initialize SDL2 - if (SDL_Init(SDL_INIT_VIDEO) < 0) { - printf("SDL2 could not initialize! SDL_Error: %s\n", SDL_GetError()); + // Initialize SDL3 + if (!SDL_Init(SDL_INIT_VIDEO)) { + printf("SDL3 could not initialize! SDL_Error: %s\n", SDL_GetError()); return 1; } - // Initialize SDL_ttf - if (TTF_Init() < 0) { - printf("SDL_ttf could not initialize! TTF_Error: %s\n", TTF_GetError()); + // Initialize SDL3_ttf + if (!TTF_Init()) { + printf("SDL3_ttf could not initialize! SDL_Error: %s\n", SDL_GetError()); SDL_Quit(); return 1; } - // Create window with SDL2 - window = SDL_CreateWindow("GlaMaC", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, - INITIAL_WIDTH, INITIAL_HEIGHT, - SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE); + // Create window with SDL3 + window = SDL_CreateWindow("GlaMaC", INITIAL_WIDTH, INITIAL_HEIGHT, + SDL_WINDOW_RESIZABLE); if (window == NULL) { printf("Window could not be created! SDL_Error: %s\n", SDL_GetError()); TTF_Quit(); @@ -56,7 +46,7 @@ int main(int argc, char* argv[]) { } // Create renderer with hardware acceleration and vsync - renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); + renderer = SDL_CreateRenderer(window, NULL); if (renderer == NULL) { printf("Renderer could not be created! SDL_Error: %s\n", SDL_GetError()); SDL_DestroyWindow(window); @@ -65,6 +55,9 @@ int main(int argc, char* argv[]) { return 1; } + // Enable vsync + SDL_SetRenderVSync(renderer, 1); + // Load fonts if (!load_fonts(&fonts)) { SDL_DestroyRenderer(renderer); @@ -93,12 +86,12 @@ int main(int argc, char* argv[]) { b32 dragging = 0; // Enable text input - SDL_StartTextInput(); + SDL_StartTextInput(window); // Main loop while (!quit) { // Handle events on queue - while (SDL_PollEvent(&e) != 0) { + while (SDL_PollEvent(&e)) { process_events(&e, &view, window, &lastMouseX, &lastMouseY, &dragging, &quit); } @@ -107,7 +100,7 @@ int main(int argc, char* argv[]) { } // Stop text input - SDL_StopTextInput(); + SDL_StopTextInput(window); // Clean up resources free_fonts(&fonts); diff --git a/src/glamac/glamac_events.c b/src/glamac/glamac_events.c index 29b7232..e5c706c 100644 --- a/src/glamac/glamac_events.c +++ b/src/glamac/glamac_events.c @@ -1,22 +1,13 @@ /** * glamac_events.c - source file detailing keyboard and mouse events used in GlaMaC. - * - * Copyright (C) 2025 https://optics-design.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * See the COPYING file for the full license text. */ -#include +#include #include "glamac_view.h" // Process key event b32 process_key_event(SDL_KeyboardEvent *key, ViewState *view, SDL_Window *window, b32 *quit) { - switch (key->keysym.sym) { - case SDLK_g: + switch (key->key) { + case SDLK_G: // First key in sequence view->gKeyPressed = 1; // Store the time when 'g' was pressed @@ -28,7 +19,7 @@ b32 process_key_event(SDL_KeyboardEvent *key, ViewState *view, SDL_Window *windo // Check if this is part of "g?" sequence (with shift for '?') if (view->gKeyPressed && (SDL_GetTicks() - view->gKeyTime < 1000)) { // If Shift is held (for '?' on most layouts) or it's a direct '?' key - if ((key->keysym.mod & KMOD_SHIFT) || key->keysym.sym == SDLK_QUESTION) { + if ((key->mod & SDL_KMOD_SHIFT) || key->key == SDLK_QUESTION) { view->showHelp = !view->showHelp; } view->gKeyPressed = 0; @@ -48,7 +39,7 @@ b32 process_key_event(SDL_KeyboardEvent *key, ViewState *view, SDL_Window *windo view->gKeyPressed = 0; return 1; - case SDLK_q: + case SDLK_Q: if (view->showHelp) { view->showHelp = 0; } else { @@ -72,38 +63,38 @@ b32 process_key_event(SDL_KeyboardEvent *key, ViewState *view, SDL_Window *windo view->gKeyPressed = 0; // Reset g key state return 1; - case SDLK_r: + case SDLK_R: // Reset view reset_view(view); view->gKeyPressed = 0; // Reset g key state return 1; - case SDLK_f: + case SDLK_F: // Toggle fullscreen toggle_fullscreen(window); view->gKeyPressed = 0; // Reset g key state return 1; // Vim-like navigation - case SDLK_h: + case SDLK_H: // Move left view->offsetX += PAN_STEP; view->gKeyPressed = 0; // Reset g key state return 1; - case SDLK_l: + case SDLK_L: // Move right view->offsetX -= PAN_STEP; view->gKeyPressed = 0; // Reset g key state return 1; - case SDLK_k: + case SDLK_K: // Move up view->offsetY -= PAN_STEP; view->gKeyPressed = 0; // Reset g key state return 1; - case SDLK_j: + case SDLK_J: // Move down view->offsetY += PAN_STEP; view->gKeyPressed = 0; // Reset g key state @@ -115,15 +106,15 @@ b32 process_key_event(SDL_KeyboardEvent *key, ViewState *view, SDL_Window *windo // Process mouse button event b32 process_mouse_button(SDL_MouseButtonEvent *button, ViewState *view, i32 *lastMouseX, i32 *lastMouseY, b32 *dragging) { - i32 mouseX, mouseY; + f32 mouseX, mouseY; switch (button->button) { case SDL_BUTTON_LEFT: - if (button->type == SDL_MOUSEBUTTONDOWN) { + if (button->type == SDL_EVENT_MOUSE_BUTTON_DOWN) { SDL_GetMouseState(&mouseX, &mouseY); // Check if click is near a glass point - i32 nearestGlass = find_nearest_glass(mouseX, mouseY, view, 15); // 15 pixels max distance + i32 nearestGlass = find_nearest_glass((i32)mouseX, (i32)mouseY, view, 15); // 15 pixels max distance if (nearestGlass >= 0) { view->selectedGlass = nearestGlass; // Don't start dragging when selecting a glass @@ -132,11 +123,11 @@ b32 process_mouse_button(SDL_MouseButtonEvent *button, ViewState *view, i32 *las view->selectedGlass = -1; // Start dragging for panning *dragging = 1; - *lastMouseX = mouseX; - *lastMouseY = mouseY; + *lastMouseX = (i32)mouseX; + *lastMouseY = (i32)mouseY; } return 1; - } else if (button->type == SDL_MOUSEBUTTONUP) { + } else if (button->type == SDL_EVENT_MOUSE_BUTTON_UP) { *dragging = 0; return 1; } @@ -150,21 +141,21 @@ b32 process_mouse_button(SDL_MouseButtonEvent *button, ViewState *view, i32 *las b32 process_mouse_motion(SDL_MouseMotionEvent *motion, ViewState *view, i32 *lastMouseX, i32 *lastMouseY, b32 dragging) { if (dragging) { // Get current mouse position - i32 mouseX, mouseY; + f32 mouseX, mouseY; SDL_GetMouseState(&mouseX, &mouseY); // Calculate normalized delta const i32 padding = (i32)(view->windowWidth * PADDING_PERCENT); - const f32 dx = (f32)(mouseX - *lastMouseX) / (view->windowWidth - 2 * padding); - const f32 dy = (f32)(mouseY - *lastMouseY) / (view->windowHeight - 2 * padding); + const f32 dx = (mouseX - *lastMouseX) / (view->windowWidth - 2 * padding); + const f32 dy = (mouseY - *lastMouseY) / (view->windowHeight - 2 * padding); // Update offset - inverted movement for natural feel view->offsetX += dx; view->offsetY -= dy; // Update last mouse position - *lastMouseX = mouseX; - *lastMouseY = mouseY; + *lastMouseX = (i32)mouseX; + *lastMouseY = (i32)mouseY; return 1; } @@ -174,11 +165,10 @@ b32 process_mouse_motion(SDL_MouseMotionEvent *motion, ViewState *view, i32 *las // Process window event b32 process_window_event(SDL_WindowEvent *window_event, ViewState *view) { - switch (window_event->event) { - case SDL_WINDOWEVENT_RESIZED: - case SDL_WINDOWEVENT_SIZE_CHANGED: - view->windowWidth = window_event->data1; - view->windowHeight = window_event->data2; + switch (window_event->type) { + case SDL_EVENT_WINDOW_RESIZED: + view->windowWidth = (i32)window_event->data1; + view->windowHeight = (i32)window_event->data2; return 1; } @@ -189,29 +179,31 @@ b32 process_window_event(SDL_WindowEvent *window_event, ViewState *view) { b32 process_events(SDL_Event *event, ViewState *view, SDL_Window *window, i32 *lastMouseX, i32 *lastMouseY, b32 *dragging, b32 *quit) { switch (event->type) { - case SDL_QUIT: + case SDL_EVENT_QUIT: *quit = 1; return 1; - case SDL_KEYDOWN: + case SDL_EVENT_KEY_DOWN: return process_key_event(&event->key, view, window, quit); - case SDL_MOUSEWHEEL: + case SDL_EVENT_MOUSE_WHEEL: // Get mouse position for centered zoom - i32 mouseX, mouseY; + f32 mouseX, mouseY; SDL_GetMouseState(&mouseX, &mouseY); - handle_mouse_wheel_zoom(event->wheel.y, mouseX, mouseY, view); + handle_mouse_wheel_zoom((i32)event->wheel.y, (i32)mouseX, (i32)mouseY, view); return 1; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: + case SDL_EVENT_MOUSE_BUTTON_DOWN: + case SDL_EVENT_MOUSE_BUTTON_UP: return process_mouse_button(&event->button, view, lastMouseX, lastMouseY, dragging); - case SDL_MOUSEMOTION: + case SDL_EVENT_MOUSE_MOTION: return process_mouse_motion(&event->motion, view, lastMouseX, lastMouseY, *dragging); - case SDL_WINDOWEVENT: - return process_window_event(&event->window, view); + case SDL_EVENT_WINDOW_RESIZED: + view->windowWidth = (i32)event->window.data1; + view->windowHeight = (i32)event->window.data2; + return 1; } return 0; diff --git a/src/glamac/glamac_render.c b/src/glamac/glamac_render.c index a39a670..619a6e0 100644 --- a/src/glamac/glamac_render.c +++ b/src/glamac/glamac_render.c @@ -1,18 +1,11 @@ /** - * glamac_render.c - source file dealing with the rendering of GlaMaC using SDL2. - * - * Copyright (C) 2025 https://optics-design.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * See the COPYING file for the full license text. + * glamac_render.c - source file dealing with the rendering of GlaMaC using SDL3. */ #include #include #include +#include +#include #include "glamac_render.h" #include "glass_data.h" @@ -33,7 +26,7 @@ typedef struct { static CachedText textCache[MAX_TEXT_CACHE] = {0}; static i32 cacheCount = 0; -// Function to draw text using SDL_ttf with caching for improved performance +// Function to draw text using SDL3_ttf with caching for improved performance void draw_text(SDL_Renderer *renderer, TTF_Font *font, const char *text, i32 x, i32 y, SDL_Color color) { // Check if we already have this text cached for (i32 i = 0; i < cacheCount; i++) { @@ -48,29 +41,29 @@ void draw_text(SDL_Renderer *renderer, TTF_Font *font, const char *text, i32 x, entry->color.a == color.a) { // Use the cached texture - SDL_Rect rect = {x, y, entry->width, entry->height}; - SDL_RenderCopy(renderer, entry->texture, NULL, &rect); + SDL_FRect rect = {(f32)x, (f32)y, (f32)entry->width, (f32)entry->height}; + SDL_RenderTexture(renderer, entry->texture, NULL, &rect); return; } } // Text not in cache, create a new texture - SDL_Surface *surface = TTF_RenderText_Blended(font, text, color); + SDL_Surface *surface = TTF_RenderText_Blended(font, text, 0, color); if (!surface) { - printf("TTF_RenderText_Blended failed: %s\n", TTF_GetError()); + printf("TTF_RenderText_Blended failed: %s\n", SDL_GetError()); return; } SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, surface); if (!texture) { printf("SDL_CreateTextureFromSurface failed: %s\n", SDL_GetError()); - SDL_FreeSurface(surface); + SDL_DestroySurface(surface); return; } // Draw the text - SDL_Rect rect = {x, y, surface->w, surface->h}; - SDL_RenderCopy(renderer, texture, NULL, &rect); + SDL_FRect rect = {(f32)x, (f32)y, (f32)surface->w, (f32)surface->h}; + SDL_RenderTexture(renderer, texture, NULL, &rect); // Add to cache if there is space if (cacheCount < MAX_TEXT_CACHE) { @@ -90,21 +83,11 @@ void draw_text(SDL_Renderer *renderer, TTF_Font *font, const char *text, i32 x, SDL_DestroyTexture(texture); } - SDL_FreeSurface(surface); + SDL_DestroySurface(surface); } -// Clear the text cache - should be called on shutdown -void clear_text_cache(void) { - for (i32 i = 0; i < cacheCount; i++) { - if (textCache[i].texture) { - SDL_DestroyTexture(textCache[i].texture); - textCache[i].texture = NULL; - } - } - cacheCount = 0; -} -// Function to draw a filled circle using SDL2's primitive functions +// Function to draw a filled circle using SDL3's primitive functions void draw_filled_circle(SDL_Renderer *renderer, i32 centerX, i32 centerY, i32 radius) { // Draw a filled circle using a series of horizontal lines // This is significantly faster than the pixel-by-pixel approach @@ -113,10 +96,10 @@ void draw_filled_circle(SDL_Renderer *renderer, i32 centerX, i32 centerY, i32 ra i32 x_width = (i32)sqrtf((float)(radius * radius - y * y)); // Draw a horizontal line from left to right edge of the circle - SDL_RenderDrawLine( + SDL_RenderLine( renderer, - centerX - x_width, centerY + y, - centerX + x_width, centerY + y + (f32)(centerX - x_width), (f32)(centerY + y), + (f32)(centerX + x_width), (f32)(centerY + y) ); } } @@ -130,12 +113,12 @@ void draw_axes(SDL_Renderer *renderer, TTF_Font *font, TTF_Font *titleFont, cons // X-axis SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - SDL_RenderDrawLine(renderer, padding, view->windowHeight - padding, - view->windowWidth - padding, view->windowHeight - padding); + SDL_RenderLine(renderer, (f32)padding, (f32)(view->windowHeight - padding), + (f32)(view->windowWidth - padding), (f32)(view->windowHeight - padding)); // Y-axis - SDL_RenderDrawLine(renderer, padding, padding, - padding, view->windowHeight - padding); + SDL_RenderLine(renderer, (f32)padding, (f32)padding, + (f32)padding, (f32)(view->windowHeight - padding)); // Calculate visible range based on current view f32 visibleMinAbbe, visibleMaxAbbe, visibleMinRI, visibleMaxRI; @@ -148,7 +131,8 @@ void draw_axes(SDL_Renderer *renderer, TTF_Font *font, TTF_Font *titleFont, cons f32 value = visibleMaxAbbe - i * (visibleMaxAbbe - visibleMinAbbe) / 5; i32 x = padding + i * (view->windowWidth - 2 * padding) / 5; - SDL_RenderDrawLine(renderer, x, view->windowHeight - padding, x, view->windowHeight - padding + 5); + SDL_RenderLine(renderer, (f32)x, (f32)(view->windowHeight - padding), + (f32)x, (f32)(view->windowHeight - padding + 5)); sprintf(label, "%.1f", value); draw_text(renderer, font, label, x - 15, view->windowHeight - padding + 10, black); } @@ -158,7 +142,7 @@ void draw_axes(SDL_Renderer *renderer, TTF_Font *font, TTF_Font *titleFont, cons f32 value = visibleMinRI + i * (visibleMaxRI - visibleMinRI) / 5; i32 y = view->windowHeight - padding - i * (view->windowHeight - 2 * padding) / 5; - SDL_RenderDrawLine(renderer, padding - 5, y, padding, y); + SDL_RenderLine(renderer, (f32)(padding - 5), (f32)y, (f32)padding, (f32)y); sprintf(label, "%.3f", value); draw_text(renderer, font, label, padding - 50, y - 10, black); } @@ -178,6 +162,7 @@ void draw_axes(SDL_Renderer *renderer, TTF_Font *font, TTF_Font *titleFont, cons // Draw the closing parenthesis draw_text(renderer, titleFont, ")", padding + 141, padding - 35, black); } + // Function to draw a grid based on visible data range void draw_grid(SDL_Renderer *renderer, const ViewState* view) { const i32 padding = (i32)(view->windowWidth * PADDING_PERCENT); @@ -208,7 +193,8 @@ void draw_grid(SDL_Renderer *renderer, const ViewState* view) { data_to_screen_coords(x, visibleMinRI, view, &screenX, &screenY); if (screenX >= padding && screenX <= view->windowWidth - padding) { - SDL_RenderDrawLine(renderer, screenX, padding, screenX, view->windowHeight - padding); + SDL_RenderLine(renderer, (f32)screenX, (f32)padding, + (f32)screenX, (f32)(view->windowHeight - padding)); } } @@ -218,7 +204,8 @@ void draw_grid(SDL_Renderer *renderer, const ViewState* view) { data_to_screen_coords(visibleMinAbbe, y, view, &screenX, &screenY); if (screenY >= padding && screenY <= view->windowHeight - padding) { - SDL_RenderDrawLine(renderer, padding, screenY, view->windowWidth - padding, screenY); + SDL_RenderLine(renderer, (f32)padding, (f32)screenY, + (f32)(view->windowWidth - padding), (f32)screenY); } } } @@ -289,14 +276,14 @@ void draw_glass_properties(SDL_Renderer *renderer, TTF_Font *font, TTF_Font *tit } // Draw background with slight transparency - SDL_Rect windowRect = {windowX, windowY, windowWidth, windowHeight}; + SDL_FRect windowRect = {(f32)windowX, (f32)windowY, (f32)windowWidth, (f32)windowHeight}; SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawColor(renderer, 245, 245, 245, 235); SDL_RenderFillRect(renderer, &windowRect); // Draw border SDL_SetRenderDrawColor(renderer, 40, 40, 40, 255); - SDL_RenderDrawRect(renderer, &windowRect); + SDL_RenderRect(renderer, &windowRect); // Draw glass name as title SDL_Color darkBlue = {0, 0, 120, 255}; @@ -326,14 +313,14 @@ void draw_help_window(SDL_Renderer *renderer, TTF_Font *font, TTF_Font *titleFon i32 x = (view->windowWidth - width) / 2; i32 y = (view->windowHeight - height) / 2; - SDL_Rect helpRect = {x, y, width, height}; + SDL_FRect helpRect = {(f32)x, (f32)y, (f32)width, (f32)height}; SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawColor(renderer, 245, 245, 245, 230); SDL_RenderFillRect(renderer, &helpRect); // Draw border SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); - SDL_RenderDrawRect(renderer, &helpRect); + SDL_RenderRect(renderer, &helpRect); // Draw help title SDL_Color black = {0, 0, 0, 255}; @@ -390,7 +377,7 @@ void render(SDL_Renderer *renderer, TTF_Font *font, TTF_Font *titleFont, TTF_Fon } // Add a small hint about help in the corner - draw_text(renderer, labelFont, "Press g? for help", 10, 0.975*view->windowHeight, black); + draw_text(renderer, labelFont, "Press g? for help", 10, (i32)(0.975*view->windowHeight), black); // Draw help window if toggled if (view->showHelp) { @@ -403,27 +390,104 @@ void render(SDL_Renderer *renderer, TTF_Font *font, TTF_Font *titleFont, TTF_Fon // Font management +// Helper function to try loading a font with fallbacks +static TTF_Font* try_load_font_from_paths(const char** fontNames, i32 numFonts, i32 size) { + TTF_Font* font = NULL; + + // Try all font paths + for (i32 i = 0; i < numFonts; i++) { + font = TTF_OpenFont(fontNames[i], size); + if (font) { + printf("Successfully loaded font: %s (size %d)\n", fontNames[i], size); + return font; + } + } + + // If all specific paths fail, try some generic system approaches + #ifndef _WIN32 + // Try to find any sans-serif font using common naming patterns + const char* genericFonts[] = { + "/usr/share/fonts/truetype/droid/DroidSans.ttf", + "/usr/share/fonts/truetype/noto/NotoSans-Regular.ttf", + "/usr/share/fonts/TTF/DroidSans.ttf", + "/usr/share/fonts/noto/NotoSans-Regular.ttf", + "/usr/share/fonts/google-noto/NotoSans-Regular.ttf", + }; + + const i32 numGeneric = sizeof(genericFonts) / sizeof(genericFonts[0]); + for (i32 i = 0; i < numGeneric; i++) { + font = TTF_OpenFont(genericFonts[i], size); + if (font) { + printf("Successfully loaded generic font: %s (size %d)\n", genericFonts[i], size); + return font; + } + } + #endif + + return NULL; +} + // Load all required fonts b32 load_fonts(FontSet *fonts) { - fonts->regular = TTF_OpenFont("C:\\Windows\\Fonts\\arial.ttf", 14); + // Common font names to try, in order of preference + const char* fontNames[] = { + #ifdef _WIN32 + "C:\\Windows\\Fonts\\arial.ttf", + "C:\\Windows\\Fonts\\tahoma.ttf", + "C:\\Windows\\Fonts\\verdana.ttf", + "C:\\Windows\\Fonts\\calibri.ttf", + #else + // Ubuntu/Debian paths + "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf", + "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf", + "/usr/share/fonts/truetype/freefont/FreeSans.ttf", + // Arch Linux paths + "/usr/share/fonts/TTF/DejaVuSans.ttf", + "/usr/share/fonts/TTF/LiberationSans-Regular.ttf", + "/usr/share/fonts/gnu-free/FreeSans.ttf", + // Fedora/CentOS paths + "/usr/share/fonts/dejavu/DejaVuSans.ttf", + "/usr/share/fonts/liberation/LiberationSans-Regular.ttf", + // OpenSUSE paths + "/usr/share/fonts/truetype/DejaVuSans.ttf", + // Alternative common locations + "/usr/share/fonts/TTF/arial.ttf", + "/usr/share/fonts/truetype/msttcorefonts/arial.ttf", + "/System/Library/Fonts/Arial.ttf", // macOS + // Try local fonts directory + "./fonts/DejaVuSans.ttf", + "./DejaVuSans.ttf", + #endif + }; + + const i32 numFonts = sizeof(fontNames) / sizeof(fontNames[0]); + i32 fontSizes[] = {14, 18, 12}; // regular, title, label + + // Load regular font + fonts->regular = try_load_font_from_paths(fontNames, numFonts, fontSizes[0]); if (!fonts->regular) { - printf("Failed to load regular font! TTF_Error: %s\n", TTF_GetError()); + printf("Failed to load any regular font!\n"); + printf("SDL_Error: %s\n", SDL_GetError()); + #ifndef _WIN32 + printf("Suggestion: Install fonts with: sudo apt install fonts-dejavu-core fonts-liberation (Ubuntu/Debian)\n"); + printf(" sudo pacman -S ttf-dejavu ttf-liberation (Arch)\n"); + printf(" sudo dnf install dejavu-sans-fonts liberation-fonts (Fedora)\n"); + #endif return 0; } - fonts->title = TTF_OpenFont("C:\\Windows\\Fonts\\arial.ttf", 18); + // Load title font (try larger size first, fallback to regular font) + fonts->title = try_load_font_from_paths(fontNames, numFonts, fontSizes[1]); if (!fonts->title) { - printf("Failed to load title font! TTF_Error: %s\n", TTF_GetError()); - TTF_CloseFont(fonts->regular); - return 0; + printf("Warning: Could not load title font, using regular font\n"); + fonts->title = fonts->regular; // Use the same font } - fonts->label = TTF_OpenFont("C:\\Windows\\Fonts\\arial.ttf", 12); + // Load label font (try smaller size first, fallback to regular font) + fonts->label = try_load_font_from_paths(fontNames, numFonts, fontSizes[2]); if (!fonts->label) { - printf("Failed to load label font! TTF_Error: %s\n", TTF_GetError()); - TTF_CloseFont(fonts->title); - TTF_CloseFont(fonts->regular); - return 0; + printf("Warning: Could not load label font, using regular font\n"); + fonts->label = fonts->regular; // Use the same font } return 1; @@ -431,7 +495,19 @@ b32 load_fonts(FontSet *fonts) { // Free all fonts void free_fonts(FontSet *fonts) { + // Only close fonts that are different from regular font if (fonts->regular) TTF_CloseFont(fonts->regular); - if (fonts->title) TTF_CloseFont(fonts->title); - if (fonts->label) TTF_CloseFont(fonts->label); + if (fonts->title && fonts->title != fonts->regular) TTF_CloseFont(fonts->title); + if (fonts->label && fonts->label != fonts->regular) TTF_CloseFont(fonts->label); +} + +// Clear text cache +void clear_text_cache(void) { + for (i32 i = 0; i < cacheCount; i++) { + if (textCache[i].texture) { + SDL_DestroyTexture(textCache[i].texture); + textCache[i].texture = NULL; + } + } + cacheCount = 0; } diff --git a/src/glamac/glamac_view.c b/src/glamac/glamac_view.c index 3078ae8..22d6401 100644 --- a/src/glamac/glamac_view.c +++ b/src/glamac/glamac_view.c @@ -1,16 +1,8 @@ /** * glamac_view.c - Source file dealing with view states, filtering, zooming etc. of GlaMaC. - * - * Copyright (C) 2025 https://optics-design.com - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * See the COPYING file for the full license text. */ #include +#include #include "glamac_view.h" #include "glass_data.h" @@ -103,11 +95,12 @@ void handle_mouse_wheel_zoom(i32 wheelY, i32 mouseX, i32 mouseY, ViewState* view // Toggle fullscreen void toggle_fullscreen(SDL_Window* window) { - const u32 flags = SDL_GetWindowFlags(window); - if ((flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == 0) { - SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP); + bool isFullscreen = SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN; + + if (!isFullscreen) { + SDL_SetWindowFullscreen(window, true); } else { - SDL_SetWindowFullscreen(window, 0); + SDL_SetWindowFullscreen(window, false); } } -- cgit v1.2.3