aboutsummaryrefslogtreecommitdiffstats
path: root/preferences.c
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2026-10-14 18:54:48 +0200
committerMattias Andrée <m@maandree.se>2026-10-14 18:54:48 +0200
commit6bbfc093885043abdfa18826511ee053e52d08fa (patch)
tree2d76b446617658412930ba4147e0d2db837d000a /preferences.c
parentFourth commit (diff)
downloadgbild-6bbfc093885043abdfa18826511ee053e52d08fa.tar.gz
gbild-6bbfc093885043abdfa18826511ee053e52d08fa.tar.bz2
gbild-6bbfc093885043abdfa18826511ee053e52d08fa.tar.xz
Fifth commitHEAD0.1master
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to 'preferences.c')
-rw-r--r--preferences.c141
1 files changed, 134 insertions, 7 deletions
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;
+}