diff --git a/options/m_option.c b/options/m_option.c index 7ba87232fa..14fd119704 100644 --- a/options/m_option.c +++ b/options/m_option.c @@ -2381,6 +2381,64 @@ const m_option_type_t m_option_type_size_box = { .equal = geometry_equal, }; +void m_rect_apply(struct mp_rect *rc, int scrw, int scrh, struct m_geometry *gm) +{ + *rc = (struct mp_rect){0}; + m_geometry_apply(&rc->x0, &rc->y0, &rc->x1, &rc->y1, scrw, scrh, gm); + if (!gm->xy_valid && gm->wh_valid && rc->x1 == 0 && rc->y1 == 0) + return; + if (!gm->xy_valid) { + rc->x0 = 0; + rc->y0 = 0; + } + if (!gm->wh_valid || rc->x1 == 0 || rc->x1 == INT_MIN) + rc->x1 = scrw - rc->x0; + if (!gm->wh_valid || rc->y1 == 0 || rc->y1 == INT_MIN) + rc->y1 = scrh - rc->y0; + rc->x1 += rc->x0; + rc->y1 += rc->y0; +} + +static int parse_rect(struct mp_log *log, const m_option_t *opt, + struct bstr name, struct bstr param, void *dst) +{ + bool is_help = bstr_equals0(param, "help"); + if (is_help) + goto exit; + + struct m_geometry gm; + if (!parse_geometry_str(&gm, param)) + goto exit; + + if (gm.x_sign || gm.y_sign || gm.ws || + (gm.wh_valid && (gm.w < 0 || gm.h < 0)) || + (gm.xy_valid && (gm.x < 0 || gm.y < 0))) + { + goto exit; + } + + if (dst) + *((struct m_geometry *)dst) = gm; + + return 1; + +exit: + if (!is_help) { + mp_err(log, "Option %.*s: invalid rect: '%.*s'\n", + BSTR_P(name), BSTR_P(param)); + } + mp_info(log, "Valid format: W[%%][xH[%%]][+x+y]\n"); + return is_help ? M_OPT_EXIT : M_OPT_INVALID; +} + +const m_option_type_t m_option_type_rect = { + .name = "Video rect", + .size = sizeof(struct m_geometry), + .parse = parse_rect, + .print = print_geometry, + .copy = copy_opt, + .equal = geometry_equal, +}; #include "video/img_format.h" diff --git a/options/m_option.h b/options/m_option.h index c868487b3e..0683822988 100644 --- a/options/m_option.h +++ b/options/m_option.h @@ -25,6 +25,7 @@ #include "misc/bstr.h" #include "audio/chmap.h" +#include "common/common.h" // m_option allows to parse, print and copy data of various types. @@ -66,6 +67,7 @@ extern const m_option_type_t m_option_type_channels; extern const m_option_type_t m_option_type_aspect; extern const m_option_type_t m_option_type_obj_settings_list; extern const m_option_type_t m_option_type_node; +extern const m_option_type_t m_option_type_rect; // Used internally by m_config.c extern const m_option_type_t m_option_type_alias; @@ -103,6 +105,7 @@ struct m_geometry { void m_geometry_apply(int *xpos, int *ypos, int *widw, int *widh, int scrw, int scrh, struct m_geometry *gm); +void m_rect_apply(struct mp_rect *rc, int scrw, int scrh, struct m_geometry *gm); struct m_channels { bool set : 1; @@ -654,6 +657,9 @@ extern const char m_option_path_separator; #define OPT_SIZE_BOX(field) \ OPT_TYPED_FIELD(m_option_type_size_box, struct m_geometry, field) +#define OPT_RECT(field) \ + OPT_TYPED_FIELD(m_option_type_rect, struct m_geometry, field) + #define OPT_TRACKCHOICE(field) \ OPT_CHOICE(field, {"no", -2}, {"auto", -1}), \ M_RANGE(0, 8190)