diff --git a/app/meson.build b/app/meson.build index 03540af1..b88e4a4f 100644 --- a/app/meson.build +++ b/app/meson.build @@ -57,6 +57,7 @@ src = [ 'src/util/process.c', 'src/util/process_intr.c', 'src/util/rand.c', + 'src/util/rect.c', 'src/util/sdl.c', 'src/util/strbuf.c', 'src/util/str.c', diff --git a/app/src/screen.c b/app/src/screen.c index 8845eb99..c42f0b05 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -8,6 +8,7 @@ #include "icon.h" #include "options.h" #include "util/log.h" +#include "util/rect.h" #include "util/sdl.h" #define DISPLAY_MARGINS 96 @@ -55,16 +56,6 @@ get_preferred_display_bounds(struct sc_size *bounds) { return true; } -static bool -is_optimal_size(struct sc_size current_size, struct sc_size content_size) { - // The size is optimal if we can recompute one dimension of the current - // size from the other - return current_size.height == current_size.width * content_size.height - / content_size.width - || current_size.width == current_size.height * content_size.width - / content_size.height; -} - // return the optimal size of the window, with the following constraints: // - it attempts to keep at least one dimension of the current_size (i.e. it // crops the black borders) @@ -90,7 +81,7 @@ get_optimal_size(struct sc_size current_size, struct sc_size content_size, window_size.height = MIN(current_size.height, display_size.height); } - if (is_optimal_size(window_size, content_size)) { + if (sc_rect_is_optimal_size(window_size, content_size)) { return window_size; } @@ -143,44 +134,6 @@ sc_screen_is_relative_mode(struct sc_screen *screen) { return screen->im.mp && screen->im.mp->relative_mode; } -static void -compute_rect(struct sc_size render_size, struct sc_size content_size, - bool can_upscale, SDL_FRect *rect) { - if (is_optimal_size(render_size, content_size)) { - rect->x = 0; - rect->y = 0; - rect->w = render_size.width; - rect->h = render_size.height; - return; - } - - if (!can_upscale && content_size.width <= render_size.width - && content_size.height <= render_size.height) { - // Center without upscaling - rect->x = (render_size.width - content_size.width) / 2.f; - rect->y = (render_size.height - content_size.height) / 2.f; - rect->w = content_size.width; - rect->h = content_size.height; - return; - } - - bool keep_width = content_size.width * render_size.height - > content_size.height * render_size.width; - if (keep_width) { - rect->x = 0; - rect->w = render_size.width; - rect->h = (float) render_size.width * content_size.height - / content_size.width; - rect->y = (render_size.height - rect->h) / 2.f; - } else { - rect->y = 0; - rect->h = render_size.height; - rect->w = (float) render_size.height * content_size.width - / content_size.height; - rect->x = (render_size.width - rect->w) / 2.f; - } -} - static void sc_screen_update_content_rect(struct sc_screen *screen) { // Only upscale video frames, not icon @@ -188,7 +141,8 @@ sc_screen_update_content_rect(struct sc_screen *screen) { struct sc_size render_size = sc_sdl_get_render_output_size(screen->renderer); - compute_rect(render_size, screen->content_size, can_upscale, &screen->rect); + sc_rect_get_content_location(render_size, screen->content_size, can_upscale, + &screen->rect); } // render the texture to the renderer diff --git a/app/src/util/rect.c b/app/src/util/rect.c new file mode 100644 index 00000000..9868ceb9 --- /dev/null +++ b/app/src/util/rect.c @@ -0,0 +1,52 @@ +#include "rect.h" + +bool +sc_rect_is_optimal_size(struct sc_size current_size, + struct sc_size content_size) { + // The size is optimal if we can recompute one dimension of the current + // size from the other + return current_size.height == current_size.width * content_size.height + / content_size.width + || current_size.width == current_size.height * content_size.width + / content_size.height; +} + +// Compute the content location, preserving its aspect ratio +void +sc_rect_get_content_location(struct sc_size render_size, + struct sc_size content_size, bool can_upscale, + SDL_FRect *out) { + if (sc_rect_is_optimal_size(render_size, content_size)) { + out->x = 0; + out->y = 0; + out->w = render_size.width; + out->h = render_size.height; + return; + } + + if (!can_upscale && content_size.width <= render_size.width + && content_size.height <= render_size.height) { + // Center without upscaling + out->x = (render_size.width - content_size.width) / 2.f; + out->y = (render_size.height - content_size.height) / 2.f; + out->w = content_size.width; + out->h = content_size.height; + return; + } + + bool keep_width = content_size.width * render_size.height + > content_size.height * render_size.width; + if (keep_width) { + out->x = 0; + out->w = render_size.width; + out->h = (float) render_size.width * content_size.height + / content_size.width; + out->y = (render_size.height - out->h) / 2.f; + } else { + out->y = 0; + out->h = render_size.height; + out->w = (float) render_size.height * content_size.width + / content_size.height; + out->x = (render_size.width - out->w) / 2.f; + } +} diff --git a/app/src/util/rect.h b/app/src/util/rect.h new file mode 100644 index 00000000..ea85ebae --- /dev/null +++ b/app/src/util/rect.h @@ -0,0 +1,24 @@ +#ifndef SC_RECT_H +#define SC_RECT_H + +#include "common.h" + +#include + +#include "coords.h" + +// Return whether the size is optimal +// +// It is optimal if it does not require black borders to preserve the aspect +// ratio, with rounding applied at pixel boundaries. +bool +sc_rect_is_optimal_size(struct sc_size current_size, + struct sc_size content_size); + +// Compute the content location, preserving its aspect ratio +void +sc_rect_get_content_location(struct sc_size render_size, + struct sc_size content_size, bool can_upscale, + SDL_FRect *out); + +#endif