From 22e50aa4e2f47e236c88fd1ec60f621b1ddda6ab Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Sat, 5 Oct 2024 09:45:48 -0400 Subject: [PATCH] common/box: add box_fit_within() Factor out common math from ssd's get_scale_box() for use elsewhere. --- include/common/box.h | 21 +++++++++++++++------ src/common/box.c | 26 ++++++++++++++++++++++++++ src/ssd/ssd-part.c | 27 +++++---------------------- 3 files changed, 46 insertions(+), 28 deletions(-) diff --git a/include/common/box.h b/include/common/box.h index 105ff297..651fcff0 100644 --- a/include/common/box.h +++ b/include/common/box.h @@ -4,14 +4,23 @@ #include -bool -box_contains(struct wlr_box *box_super, struct wlr_box *box_sub); +bool box_contains(struct wlr_box *box_super, struct wlr_box *box_sub); -bool -box_intersects(struct wlr_box *box_a, struct wlr_box *box_b); +bool box_intersects(struct wlr_box *box_a, struct wlr_box *box_b); /* Returns the bounding box of 2 boxes */ -void -box_union(struct wlr_box *box_dest, struct wlr_box *box_a, struct wlr_box *box_b); +void box_union(struct wlr_box *box_dest, struct wlr_box *box_a, + struct wlr_box *box_b); + +/* + * Fits and centers a content box (width & height) within a bounding box + * (max_width & max_height). The content box is downscaled if necessary + * (preserving aspect ratio) but not upscaled. + * + * The returned x & y coordinates are the centered content position + * relative to the top-left corner of the bounding box. + */ +struct wlr_box box_fit_within(int width, int height, int max_width, + int max_height); #endif /* LABWC_BOX_H */ diff --git a/src/common/box.c b/src/common/box.c index 1a56cfe2..eefa535c 100644 --- a/src/common/box.c +++ b/src/common/box.c @@ -47,3 +47,29 @@ box_union(struct wlr_box *box_dest, struct wlr_box *box_a, struct wlr_box *box_b box_dest->width = x2 - x1; box_dest->height = y2 - y1; } + +struct wlr_box +box_fit_within(int width, int height, int max_width, int max_height) +{ + struct wlr_box box; + + if (width <= max_width && height <= max_height) { + /* No downscaling needed */ + box.width = width; + box.height = height; + } else if (width * max_height > height * max_width) { + /* Wider content, fit width */ + box.width = max_width; + box.height = (height * max_width + (width / 2)) / width; + } else { + /* Taller content, fit height */ + box.width = (width * max_height + (height / 2)) / height; + box.height = max_height; + } + + /* Compute centered position */ + box.x = (max_width - box.width) / 2; + box.y = (max_height - box.height) / 2; + + return box; +} diff --git a/src/ssd/ssd-part.c b/src/ssd/ssd-part.c index 2e572966..58305e0c 100644 --- a/src/ssd/ssd-part.c +++ b/src/ssd/ssd-part.c @@ -2,6 +2,7 @@ #include #include "buffer.h" +#include "common/box.h" #include "common/list.h" #include "common/mem.h" #include "labwc.h" @@ -80,29 +81,11 @@ add_scene_buffer(struct wl_list *list, enum ssd_part_type type, } static struct wlr_box -get_scale_box(struct lab_data_buffer *buffer, double container_width, - double container_height) +get_scale_box(struct lab_data_buffer *buffer, int container_width, + int container_height) { - struct wlr_box icon_geo = { - .width = buffer->logical_width, - .height = buffer->logical_height - }; - - /* Scale down buffer if required */ - if (icon_geo.width && icon_geo.height) { - double scale = MIN(container_width / icon_geo.width, - container_height / icon_geo.height); - if (scale < 1.0f) { - icon_geo.width = (double)icon_geo.width * scale; - icon_geo.height = (double)icon_geo.height * scale; - } - } - - /* Center buffer on both axis */ - icon_geo.x = (container_width - icon_geo.width) / 2; - icon_geo.y = (container_height - icon_geo.height) / 2; - - return icon_geo; + return box_fit_within(buffer->logical_width, buffer->logical_height, + container_width, container_height); } void -- 2.52.0