From 6bbfc093885043abdfa18826511ee053e52d08fa Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Wed, 14 Oct 2026 18:54:48 +0200 Subject: Fifth commit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- preferences.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 134 insertions(+), 7 deletions(-) (limited to 'preferences.c') diff --git a/preferences.c b/preferences.c index e4d73e2..d1849df 100644 --- a/preferences.c +++ b/preferences.c @@ -13,7 +13,9 @@ GdkColor chequer_colours[2] = { }; uint16_t chequer_alphas[2] = {0xFFFFu, 0xFFFFu}; int chequered_background = 0; -int chequer_size = 16; +int chequer_size = DEFAULT_CHEQUER_SIZE; +int apply_embedded_orientation = 0; +int normal_size_is_physical_size = 0; static GtkWidget *preferences_window; static GtkWidget *transparency_controls; @@ -75,6 +77,33 @@ chequer_size_changed(GtkSpinButton *button, void *user) gtk_widget_queue_draw(display_area); } +static void +apply_embedded_orientation_changed(GtkToggleButton *button, void *user) +{ + struct file *file; + enum transformation t; + int active = gtk_toggle_button_get_active(button); + (void) user; + if (apply_embedded_orientation == active) + return; + apply_embedded_orientation = active; + file = get_file(); + if (file && (t = file->image.embedded_transformation)) + transform_redraw(active ? t : inverse_transformation(t)); + collection_redraw_embedded_orientations(); +} + +static void +normal_size_is_physical_size_changed(GtkToggleButton *button, void *user) +{ + int active = gtk_toggle_button_get_active(button); + (void) user; + if (normal_size_is_physical_size == active) + return; + normal_size_is_physical_size = active; + /* TODO implement */ +} + static GtkWidget * new_section(const char *title) { @@ -117,9 +146,8 @@ new_scaling_section(void) return section; } -#ifdef TODO static GtkWidget * -new_unimplemented_section(void) +new_image_handling_section(void) { GtkWidget *section = new_section("Image handling"); GtkWidget *box = gtk_bin_get_child(GTK_BIN(section)); @@ -128,11 +156,14 @@ new_unimplemented_section(void) orientation = gtk_check_button_new_with_mnemonic("Apply embedded _orientation"); physical_size = gtk_check_button_new_with_mnemonic("Normal size is _physical size"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(orientation), apply_embedded_orientation); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(physical_size), normal_size_is_physical_size); gtk_box_pack_start(GTK_BOX(box), orientation, 0, 0, 0u); gtk_box_pack_start(GTK_BOX(box), physical_size, 0, 0, 0u); + g_signal_connect(orientation, "toggled", G_CALLBACK(&apply_embedded_orientation_changed), NULL); + g_signal_connect(physical_size, "toggled", G_CALLBACK(&normal_size_is_physical_size_changed), NULL); return section; } -#endif static GtkWidget * new_transparency_section(void) @@ -211,9 +242,7 @@ open_preferences(void) gtk_container_add(GTK_CONTAINER(alignment), box); gtk_box_pack_start(GTK_BOX(box), new_scaling_section(), 0, 0, 0u); -#ifdef TODO - gtk_box_pack_start(GTK_BOX(box), new_unimplemented_section(), 0, 0, 0u); -#endif + gtk_box_pack_start(GTK_BOX(box), new_image_handling_section(), 0, 0, 0u); gtk_box_pack_start(GTK_BOX(box), new_transparency_section(), 0, 0, 0u); g_signal_connect(preferences_window, "response", G_CALLBACK(&preferences_response), NULL); @@ -221,3 +250,101 @@ open_preferences(void) gtk_widget_show_all(preferences_window); } + +int +parse_and_set_scaling_filter(const char *s) +{ +#define X(I, V, T) if (!strcasecmp(s, T)) { scaling_filter = V; return 1; } + LIST_SCALING_FILTERS(X, ) +#undef X + return 0; +} + +int +parse_and_set_chequer_size(const char *s) +{ + char *end; + long int size; + errno = 0; + size = strtol(s, &end, 10); + if (errno || end == s || *end || size < 0 || size > INT_MAX) + return 0; + chequer_size = (int)size; + chequered_background = size != 0; + return 1; +} + +static const char * +parse_chequer_colour(const char *s, GdkColor *colour_out, uint16_t *alpha_out) +{ + int has_precent_alpha = 0; + size_t i, j, len, digits, nchannels; + uint16_t mul, channels[] = {0u, 0u, 0u, 65535u}; + + if ('0' <= *s && *s <= '9' && strchr(s, '%')) { + while ('0' <= *s && *s <= '9' && channels[3] < 100u) + channels[3] = (uint16_t)(channels[3] * 10u + (unsigned)(*s++ - '9')); + if (channels[3] > 100u || *s != '%') + return NULL; + s = &s[1]; + channels[3] = (uint16_t)(655.35 * (double)channels[3]); + has_precent_alpha = 1; + } + + if (*s == '#') + s = &s[1u]; + else if (*s == '0' && (s[1u] == 'x' || s[1u] == 'X')) + s = &s[2u]; + + len = strspn(s, "0123456789abcdefABCDEF"); + switch (len) { + case 3u: digits = 1u; mul = 0x1111u; nchannels = 3u; break; + case 4u: digits = 1u; mul = 0x1111u; nchannels = 4u; break; + case 6u: digits = 2u; mul = 0x0101u; nchannels = 3u; break; + case 8u: digits = 2u; mul = 0x0101u; nchannels = 4u; break; + case 12u: digits = 4u; mul = 0x0001u; nchannels = 3u; break; + case 16u: digits = 4u; mul = 0x0001u; nchannels = 4u; break; + default: + return NULL; + } + if (has_precent_alpha && nchannels == 4u) + return NULL; + + for (i = 0u; i < nchannels; i++) { + for (j = 0u; j < digits; j++, s++) { + channels[i] <<= 4; + channels[i] |= (uint16_t)(((int)*s & 15) + (*s > '9' ? 9 : 0)); + } + channels[i] = (uint16_t)(mul * channels[i]); + } + + colour_out->red = channels[0]; + colour_out->green = channels[1]; + colour_out->blue = channels[2]; + *alpha_out = channels[3]; + return s; +} + +int +parse_and_set_chequer_colours(const char *s) +{ + GdkColor colours[2]; + uint16_t alphas[2]; + s = parse_chequer_colour(s, &colours[0u], &alphas[0u]); + if (!s) + return 0; + if (*s == ':') { + s = parse_chequer_colour(&s[1u], &colours[1u], &alphas[1u]); + } else { + colours[1] = colours[0]; + alphas[1] = alphas[0]; + } + if (!s || *s != ':') + return 0; + chequer_colours[0] = colours[0]; + chequer_colours[1] = colours[1]; + chequer_alphas[0] = alphas[0]; + chequer_alphas[1] = alphas[1]; + chequered_background = 1; + return 1; +} -- cgit v1.3.1