Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
iop/drawlayer/conf.c
Go to the documentation of this file.
1/*
2 This file is part of the Ansel project.
3 Copyright (C) 2026 Aurélien PIERRE.
4
5 Ansel is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 Ansel is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with Ansel. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#include "iop/drawlayer/conf.h"
20
21#include "iop/drawlayer/runtime.h" // dt_iop_drawlayer_gui_data_t (dereferenced here)
22#include "iop/drawlayer/widgets.h" // DT_DRAWLAYER_COLOR_HISTORY_COUNT, ..._set_color_history()
23
24#include "control/redraw.h" // dt_control_queue_redraw_center()
25#include "develop/imageop_gui.h" // dt_iop_gui_data()
26#include "gui/application.h" // dt_gui_get_global()
27#include "widgets/widget_settings.h" // dt_gui_widgets_suppressed()
28#include "widgets/bauhaus.h" // dt_bauhaus_slider_get(), dt_bauhaus_combobox_get()
29
30/*
31 * drawlayer config subsystem
32 *
33 * This file intentionally has no public header/API.
34 */
35
43{
69 {
70 const gboolean migrated = dt_conf_key_exists(DRAWLAYER_CONF_BASE "map_speed_size")
71 ? dt_conf_get_bool(DRAWLAYER_CONF_BASE "map_speed_size")
72 : FALSE;
74 }
76 {
77 const gboolean migrated = dt_conf_key_exists(DRAWLAYER_CONF_BASE "map_speed_opacity")
78 ? dt_conf_get_bool(DRAWLAYER_CONF_BASE "map_speed_opacity")
79 : FALSE;
81 }
83 {
84 const gboolean migrated = dt_conf_key_exists(DRAWLAYER_CONF_BASE "map_speed_flow")
85 ? dt_conf_get_bool(DRAWLAYER_CONF_BASE "map_speed_flow")
86 : FALSE;
88 }
90 {
91 const gboolean migrated = dt_conf_key_exists(DRAWLAYER_CONF_BASE "map_speed_softness")
92 ? dt_conf_get_bool(DRAWLAYER_CONF_BASE "map_speed_softness")
93 : FALSE;
95 }
99}
100
107
114
117{
118 return CLAMP(dt_conf_get_float(DRAWLAYER_CONF_SIZE), 1.0f, 2048.0f);
119}
120
123{
124 return CLAMP(dt_conf_get_float(DRAWLAYER_CONF_OPACITY), 0.0f, 100.0f);
125}
126
129{
130 return CLAMP(dt_conf_get_float(DRAWLAYER_CONF_FLOW), 0.0f, 100.0f);
131}
132
135{
136 return CLAMP(dt_conf_get_float(DRAWLAYER_CONF_SPRINKLES), 0.0f, 100.0f);
137}
138
141{
142 return CLAMP(dt_conf_get_float(DRAWLAYER_CONF_SPRINKLE_SIZE), 1.0f, 256.0f);
143}
144
150
153{
154 return CLAMP(dt_conf_get_float(DRAWLAYER_CONF_DISTANCE), 0.0f, 100.0f);
155}
156
159{
160 return CLAMP(dt_conf_get_float(DRAWLAYER_CONF_SMOOTHING), 0.0f, 100.0f);
161}
162
164static float _conf_softness(void)
165{
167}
168
171{
172 return 1.0f - _conf_softness();
173}
174
177{
178 return CLAMP(dt_conf_get_float(DRAWLAYER_CONF_HDR_EV), 0.0f, 4.0f);
179}
180
187
194
202
204static void _color_history_key(const int index, const char channel, char *key, const size_t key_size)
205{
206 g_snprintf(key, key_size, DRAWLAYER_CONF_BASE "color_history_%d_%c", index, channel);
207}
208
210static void _color_history_valid_key(const int index, char *key, const size_t key_size)
211{
212 g_snprintf(key, key_size, DRAWLAYER_CONF_BASE "color_history_%d_valid", index);
213}
214
217{
218 if(IS_NULL_PTR(g) || !g->ui.widgets) return;
219
220 float history[DT_DRAWLAYER_COLOR_HISTORY_COUNT][3] = { { 0.0f } };
221 gboolean valid[DT_DRAWLAYER_COLOR_HISTORY_COUNT] = { FALSE };
222
223 char key[128] = { 0 };
224 for(int i = 0; i < DT_DRAWLAYER_COLOR_HISTORY_COUNT; i++)
225 {
228
229 _color_history_key(i, 'r', key, sizeof(key));
230 history[i][0] = _clamp01(dt_conf_key_exists(key) ? dt_conf_get_float(key) : 0.0f);
231 _color_history_key(i, 'g', key, sizeof(key));
232 history[i][1] = _clamp01(dt_conf_key_exists(key) ? dt_conf_get_float(key) : 0.0f);
233 _color_history_key(i, 'b', key, sizeof(key));
234 history[i][2] = _clamp01(dt_conf_key_exists(key) ? dt_conf_get_float(key) : 0.0f);
235 }
236 dt_drawlayer_widgets_set_color_history(g->ui.widgets, history, valid);
237}
238
241{
242 if(IS_NULL_PTR(g) || !g->ui.widgets) return;
243
244 float history[DT_DRAWLAYER_COLOR_HISTORY_COUNT][3] = { { 0.0f } };
245 gboolean valid[DT_DRAWLAYER_COLOR_HISTORY_COUNT] = { FALSE };
246 dt_drawlayer_widgets_get_color_history(g->ui.widgets, history, valid);
247
248 char key[128] = { 0 };
249 for(int i = 0; i < DT_DRAWLAYER_COLOR_HISTORY_COUNT; i++)
250 {
252 dt_conf_set_bool(key, valid[i]);
253
254 _color_history_key(i, 'r', key, sizeof(key));
255 dt_conf_set_float(key, history[i][0]);
256 _color_history_key(i, 'g', key, sizeof(key));
257 dt_conf_set_float(key, history[i][1]);
258 _color_history_key(i, 'b', key, sizeof(key));
259 dt_conf_set_float(key, history[i][2]);
260 }
261}
262
264void dt_drawlayer_conf_remember_display_color(dt_iop_module_t *self, const float display_rgb[3])
265{
267 if(IS_NULL_PTR(g) || !g->ui.widgets || !display_rgb) return;
268
269 if(!dt_drawlayer_widgets_push_color_history(g->ui.widgets, display_rgb)) return;
271 if(g->controls.color_swatch) gtk_widget_queue_draw(g->controls.color_swatch);
272}
273
275void dt_drawlayer_conf_apply_display_brush_color(dt_iop_module_t *self, const float display_rgb[3], const gboolean remember)
276{
278 if(IS_NULL_PTR(self) || IS_NULL_PTR(g) || !g->ui.widgets || !display_rgb) return;
279
284 dt_drawlayer_sync_cached_brush_colors(self, display_rgb);
285
286 dt_drawlayer_widgets_set_display_color(g->ui.widgets, display_rgb);
288
289 if(remember) dt_drawlayer_conf_remember_display_color(self, display_rgb);
290
291 if(g->controls.color) gtk_widget_queue_draw(g->controls.color);
292 if(g->controls.color_swatch) gtk_widget_queue_draw(g->controls.color_swatch);
294}
295
298{
300 if(IS_NULL_PTR(g) || !g->ui.widgets) return;
301
302 float display_rgb[3] = { 0.0f };
304 dt_drawlayer_sync_cached_brush_colors(self, display_rgb);
305
306 dt_drawlayer_widgets_set_display_color(g->ui.widgets, display_rgb);
307 if(g->controls.color_swatch) gtk_widget_queue_draw(g->controls.color_swatch);
308}
309
310
313{
314 if(IS_NULL_PTR(g) || IS_NULL_PTR(rows)) return;
315
316 rows[0] = (dt_drawlayer_mapping_row_t){
317 .targets = { { &g->controls.map_pressure_size, DRAWLAYER_CONF_MAP_PRESSURE_SIZE },
318 { &g->controls.map_pressure_opacity, DRAWLAYER_CONF_MAP_PRESSURE_OPACITY },
319 { &g->controls.map_pressure_flow, DRAWLAYER_CONF_MAP_PRESSURE_FLOW },
320 { &g->controls.map_pressure_softness, DRAWLAYER_CONF_MAP_PRESSURE_SOFTNESS } },
321 .profile = { &g->controls.pressure_profile, DRAWLAYER_CONF_PRESSURE_PROFILE },
322 };
323 rows[1] = (dt_drawlayer_mapping_row_t){
324 .targets = { { &g->controls.map_tilt_size, DRAWLAYER_CONF_MAP_TILT_SIZE },
325 { &g->controls.map_tilt_opacity, DRAWLAYER_CONF_MAP_TILT_OPACITY },
326 { &g->controls.map_tilt_flow, DRAWLAYER_CONF_MAP_TILT_FLOW },
327 { &g->controls.map_tilt_softness, DRAWLAYER_CONF_MAP_TILT_SOFTNESS } },
328 .profile = { &g->controls.tilt_profile, DRAWLAYER_CONF_TILT_PROFILE },
329 };
330 rows[2] = (dt_drawlayer_mapping_row_t){
331 .targets = { { &g->controls.map_accel_size, DRAWLAYER_CONF_MAP_ACCEL_SIZE },
332 { &g->controls.map_accel_opacity, DRAWLAYER_CONF_MAP_ACCEL_OPACITY },
333 { &g->controls.map_accel_flow, DRAWLAYER_CONF_MAP_ACCEL_FLOW },
334 { &g->controls.map_accel_softness, DRAWLAYER_CONF_MAP_ACCEL_SOFTNESS } },
335 .profile = { &g->controls.accel_profile, DRAWLAYER_CONF_ACCEL_PROFILE },
336 };
337}
338
340void dt_drawlayer_conf_sync_params_from_gui(dt_iop_module_t *self, const gboolean record_history)
341{
343 (void)record_history;
345
346 /* Every widget edit lands here, so this is where the resolved-brush cache goes stale. */
359 if(g->controls.image_colorpicker_source)
360 dt_conf_set_int(DRAWLAYER_CONF_PICK_SOURCE, dt_bauhaus_combobox_get(g->controls.image_colorpicker_source));
362
363 /* The targets are read unguarded and the profiles behind a NULL check, exactly as the
364 * fifteen unrolled lines this replaced did. */
367 for(int r = 0; r < DT_DRAWLAYER_MAPPING_ROWS; r++)
368 {
369 for(int c = 0; c < DT_DRAWLAYER_MAPPING_TARGETS; c++)
370 dt_conf_set_bool(mapping[r].targets[c].conf_key,
371 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(*mapping[r].targets[c].widget)));
372 if(*mapping[r].profile.widget)
373 dt_conf_set_int(mapping[r].profile.conf_key, dt_bauhaus_combobox_get(*mapping[r].profile.widget));
374 }
375}
#define FALSE
Definition ashift_lsd.c:158
float dt_bauhaus_slider_get(GtkWidget *widget)
Definition bauhaus.c:3283
int dt_bauhaus_combobox_get(GtkWidget *widget)
Definition bauhaus.c:2139
dt_drawlayer_brush_mode_t
Pixel blending behavior used while stamping a dab.
Definition brush.h:49
@ DT_DRAWLAYER_BRUSH_MODE_PAINT
Definition brush.h:50
@ DT_DRAWLAYER_BRUSH_MODE_SMUDGE
Definition brush.h:53
dt_drawlayer_brush_shape_t
Supported analytic fall-off profiles for brush alpha.
Definition brush.h:40
@ DT_DRAWLAYER_BRUSH_SHAPE_SIGMOIDAL
Definition brush.h:44
@ DT_DRAWLAYER_BRUSH_SHAPE_LINEAR
Definition brush.h:41
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
static dt_aligned_pixel_t rgb
void dt_conf_set_bool(const char *name, int val)
int dt_conf_get_bool(const char *name)
int dt_conf_key_exists(const char *key)
Does key have a value?
void dt_conf_set_float(const char *name, float val)
float dt_conf_get_float(const char *name)
Float for name, clamped to its declared bounds.
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
void dt_control_queue_redraw_center()
Request a redraw of the centre view.
Definition control.c:970
struct dt_gui_gtk_t * dt_gui_get_global(void)
Definition darktable.c:526
void dt_drawlayer_invalidate_brush_settings_cache(dt_iop_drawlayer_gui_data_t *g)
Definition drawlayer.c:243
void dt_drawlayer_sync_cached_brush_colors(dt_iop_module_t *self, const float display_rgb[3])
Cache brush colors in GUI state so stroke input snapshots don't re-transform per event.
Definition drawlayer.c:185
static dt_iop_gui_data_t * dt_iop_gui_data(const struct dt_iop_module_t *m)
The module's GUI data blob, NULL-safe for headless callers: IOP process() implementations read it for...
Definition imageop_gui.h:81
static float _clamp01(const float v)
Clamp scalar to [0,1].
void dt_drawlayer_conf_remember_display_color(dt_iop_module_t *self, const float display_rgb[3])
Push current display color to history and trigger swatch redraw.
void dt_drawlayer_conf_sync_params_from_gui(dt_iop_module_t *self, const gboolean record_history)
Sync active GUI widget values back into persistent config keys.
float dt_drawlayer_conf_hardness(void)
Derive hardness as complementary value of softness.
drawlayer_pick_source_t dt_drawlayer_conf_pick_source(void)
Read and clamp color picker source selector.
float dt_drawlayer_conf_sprinkle_coarseness(void)
Read and clamp configured sprinkle octave mix (%).
static float _conf_softness(void)
Read configured softness in [0,1].
float dt_drawlayer_conf_smoothing(void)
Read and clamp configured smoothing parameter (%).
drawlayer_mapping_profile_t dt_drawlayer_conf_mapping_profile(const char *key)
Read and clamp one mapping-profile enum key.
void dt_drawlayer_conf_ensure_defaults(void)
Ensure all drawlayer GUI config keys exist with sane defaults.
void dt_drawlayer_conf_display_color(float rgb[3])
Read configured display RGB brush color.
float dt_drawlayer_conf_hdr_exposure(void)
Read and clamp HDR picker exposure compensation (EV).
dt_iop_drawlayer_brush_shape_t dt_drawlayer_conf_brush_shape(void)
Read and clamp configured brush shape.
static void _color_history_key(const int index, const char channel, char *key, const size_t key_size)
Build config key for one color-history channel entry.
dt_iop_drawlayer_brush_mode_t dt_drawlayer_conf_brush_mode(void)
Read and clamp configured brush blend mode.
static void _color_history_valid_key(const int index, char *key, const size_t key_size)
Build config key for one color-history validity entry.
float dt_drawlayer_conf_sprinkles(void)
Read and clamp configured sprinkles amount (%).
void dt_drawlayer_conf_load_color_history(dt_iop_drawlayer_gui_data_t *g)
Load persisted color-history stack from config into widgets state.
void dt_drawlayer_conf_apply_display_brush_color(dt_iop_module_t *self, const float display_rgb[3], const gboolean remember)
Apply display-space brush color to conf, widgets and redraw.
float dt_drawlayer_conf_opacity(void)
Read and clamp configured stroke opacity (%).
float dt_drawlayer_conf_size(void)
Read and clamp configured brush size (px).
void dt_drawlayer_conf_sync_color_picker(dt_iop_module_t *self)
Refresh picker widgets from persisted config color.
float dt_drawlayer_conf_flow(void)
Read and clamp configured flow (%).
float dt_drawlayer_conf_distance(void)
Read and clamp configured distance/sampling parameter (%).
void dt_drawlayer_mapping_rows(dt_iop_drawlayer_gui_data_t *g, dt_drawlayer_mapping_row_t rows[DT_DRAWLAYER_MAPPING_ROWS])
float dt_drawlayer_conf_sprinkle_size(void)
Read and clamp configured sprinkle feature size (px).
static void _store_color_history(const dt_iop_drawlayer_gui_data_t *g)
Persist current widget color-history stack into config.
The brush settings the drawlayer module keeps in the application configuration.
#define DRAWLAYER_CONF_BRUSH_MODE
#define DRAWLAYER_CONF_MAP_TILT_SIZE
#define DRAWLAYER_CONF_COLOR_R
#define DRAWLAYER_CONF_PICK_SOURCE
#define DRAWLAYER_CONF_OPACITY
#define DRAWLAYER_CONF_DISTANCE
#define DRAWLAYER_CONF_MAP_PRESSURE_SIZE
#define DRAWLAYER_CONF_ACCEL_PROFILE
#define DRAWLAYER_CONF_SPRINKLES
#define DRAWLAYER_CONF_SMOOTHING
#define DRAWLAYER_CONF_MAP_PRESSURE_SOFTNESS
#define DRAWLAYER_CONF_PRESSURE_PROFILE
#define DRAWLAYER_CONF_MAP_TILT_FLOW
#define DRAWLAYER_CONF_MAP_ACCEL_FLOW
#define DRAWLAYER_CONF_BASE
#define DRAWLAYER_CONF_MAP_ACCEL_SIZE
#define DRAWLAYER_CONF_SPRINKLE_SIZE
#define DRAWLAYER_CONF_MAP_PRESSURE_OPACITY
#define DRAWLAYER_CONF_SIZE
#define DRAWLAYER_CONF_FLOW
#define DRAWLAYER_CONF_MAP_TILT_SOFTNESS
#define DRAWLAYER_CONF_TILT_PROFILE
#define DRAWLAYER_CONF_MAP_ACCEL_OPACITY
#define DRAWLAYER_CONF_HDR_EV
#define DRAWLAYER_CONF_MAP_PRESSURE_FLOW
#define DRAWLAYER_CONF_COLOR_G
#define DRAWLAYER_CONF_COLOR_B
#define DRAWLAYER_CONF_MAP_TILT_OPACITY
#define DRAWLAYER_CONF_MAP_ACCEL_SOFTNESS
#define DRAWLAYER_CONF_SOFTNESS
#define DRAWLAYER_CONF_SPRINKLE_COARSENESS
#define DRAWLAYER_CONF_BRUSH_SHAPE
drawlayer_mapping_profile_t
@ DRAWLAYER_PROFILE_INV_QUADRATIC
@ DRAWLAYER_PROFILE_LINEAR
drawlayer_pick_source_t
@ DRAWLAYER_PICK_SOURCE_INPUT
@ DRAWLAYER_PICK_SOURCE_OUTPUT
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
Definition macros.h:96
char * key
Asking the interface to repaint itself.
void dt_drawlayer_ui_cursor_clear(dt_drawlayer_ui_state_t *state)
Definition runtime.c:958
Private runtime state/helpers shared by drawlayer module entrypoints.
#define DT_DRAWLAYER_MAPPING_ROWS
How many input axes the tablet mapping offers (pressure, tilt, acceleration).
Definition runtime.h:392
#define DT_DRAWLAYER_MAPPING_TARGETS
How many brush properties each axis can drive (size, opacity, flow, hardness).
Definition runtime.h:394
const float r
One input axis: the four properties it can drive, and its response curve.
Definition runtime.h:405
gboolean dt_gui_widgets_suppressed(void)
gboolean dt_drawlayer_widgets_push_color_history(dt_drawlayer_widgets_t *widgets, const float display_rgb[3])
Push one color to history head if different from current head.
Definition widgets.c:414
void dt_drawlayer_widgets_set_color_history(dt_drawlayer_widgets_t *widgets, const float history[DT_DRAWLAYER_COLOR_HISTORY_COUNT][3], const gboolean valid[DT_DRAWLAYER_COLOR_HISTORY_COUNT])
Replace full color-history content and validity flags.
Definition widgets.c:384
int dt_drawlayer_widgets_get_brush_profile_selection(const dt_drawlayer_widgets_t *widgets)
Read currently selected brush profile.
Definition widgets.c:723
void dt_drawlayer_widgets_get_color_history(const dt_drawlayer_widgets_t *widgets, float history[DT_DRAWLAYER_COLOR_HISTORY_COUNT][3], gboolean valid[DT_DRAWLAYER_COLOR_HISTORY_COUNT])
Copy full color-history content and validity flags out.
Definition widgets.c:399
void dt_drawlayer_widgets_set_display_color(dt_drawlayer_widgets_t *widgets, const float display_rgb[3])
Set current color and synchronize picker internals.
Definition widgets.c:369
Public color-picker/history widget API for drawlayer GUI.
#define DT_DRAWLAYER_COLOR_HISTORY_COUNT
Definition widgets.h:29