Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
draw.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2009-2013, 2016 johannes hanika.
4 Copyright (C) 2010-2011 Henrik Andersson.
5 Copyright (C) 2010, 2012-2014, 2016, 2018 Tobias Ellinghaus.
6 Copyright (C) 2011 Jochen Schroeder.
7 Copyright (C) 2011 Robert Bieber.
8 Copyright (C) 2012 Richard Wonka.
9 Copyright (C) 2014, 2016 Roman Lebedev.
10 Copyright (C) 2018-2020, 2025 Aurélien PIERRE.
11 Copyright (C) 2019 Andreas Schneider.
12 Copyright (C) 2019 Edgardo Hoszowski.
13 Copyright (C) 2019 Heiko Bauke.
14 Copyright (C) 2019 Jakub Filipowicz.
15 Copyright (C) 2019-2020, 2022 Pascal Obry.
16 Copyright (C) 2019 Philippe Weyland.
17 Copyright (C) 2020, 2022 Chris Elston.
18 Copyright (C) 2020-2021 Dan Torop.
19 Copyright (C) 2020 Ralf Brown.
20 Copyright (C) 2022 Aldric Renaudin.
21 Copyright (C) 2022 Martin Bařinka.
22 Copyright (C) 2025 Alynx Zhou.
23 Copyright (C) 2026 Guillaume Stutin.
24
25 darktable is free software: you can redistribute it and/or modify
26 it under the terms of the GNU General Public License as published by
27 the Free Software Foundation, either version 3 of the License, or
28 (at your option) any later version.
29
30 darktable is distributed in the hope that it will be useful,
31 but WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 GNU General Public License for more details.
34
35 You should have received a copy of the GNU General Public License
36 along with darktable. If not, see <http://www.gnu.org/licenses/>.
37*/
38
39#pragma once
40
43#ifdef HAVE_CONFIG_H
44#include "config.h"
45#endif
46
47#include "common/curve_tools.h"
48#include "common/darktable.h"
49#include "common/splines.h"
50#include "control/conf.h"
51#include "develop/develop.h"
52#include <cairo.h>
53#include <glib.h>
54#include <math.h>
55#include <stdint.h>
56#include <stdlib.h>
57#include <gui/gtk.h>
58
59#ifdef __cplusplus
60extern "C" {
61#endif
62
63#ifndef M_PI
64#define M_PI 3.141592654
65#endif
66
67// TODO: enter directly the values applied to this factor in each following macro later once
68// we're happy with it.
69#define DT_DRAW_SIZE_GLOBAL_FACTOR 0.75f
70
72#define DT_DRAW_SIZE_LINE DT_PIXEL_APPLY_DPI_DPP(1.5f * DT_DRAW_SIZE_GLOBAL_FACTOR)
73#define DT_DRAW_SIZE_LINE_SELECTED DT_PIXEL_APPLY_DPI_DPP(3.0f * DT_DRAW_SIZE_GLOBAL_FACTOR)
74#define DT_DRAW_SIZE_LINE_HIGHLIGHT (DT_PIXEL_APPLY_DPI_DPP(4.0f * DT_DRAW_SIZE_GLOBAL_FACTOR) + DT_DRAW_SIZE_LINE)
75#define DT_DRAW_SIZE_LINE_HIGHLIGHT_SELECTED (DT_PIXEL_APPLY_DPI_DPP(5.0f * DT_DRAW_SIZE_GLOBAL_FACTOR) + DT_DRAW_SIZE_LINE_SELECTED)
76#define DT_DRAW_SIZE_CROSS DT_PIXEL_APPLY_DPI_DPP(7.0f * DT_DRAW_SIZE_GLOBAL_FACTOR)
77
79#define DT_DRAW_SCALE_DASH DT_PIXEL_APPLY_DPI_DPP(12.0f * DT_DRAW_SIZE_GLOBAL_FACTOR)
80#define DT_DRAW_SCALE_ARROW DT_PIXEL_APPLY_DPI_DPP(18.0f * DT_DRAW_SIZE_GLOBAL_FACTOR)
81
82// radius/width of node (handles are set to be 3/4 of a node size)
83#define DT_DRAW_RADIUS_NODE DT_PIXEL_APPLY_DPI_DPP(5.0f * DT_DRAW_SIZE_GLOBAL_FACTOR)
84#define DT_DRAW_RADIUS_NODE_SELECTED (1.25f * DT_DRAW_RADIUS_NODE)
85
86// used to detect the area where rotation of a shape is possible. Don't apply the global factor here since it's an user interaction area.
87#define DT_DRAW_SELECTION_ROTATION_AREA DT_PIXEL_APPLY_DPI_DPP(50.0f)
88#define DT_DRAW_SELECTION_ROTATION_RADIUS(dev) (DT_DRAW_SELECTION_ROTATION_AREA / dt_dev_get_zoom_level((dt_develop_t *)dev))
89
97
104
106static inline void dt_draw_set_color_overlay(cairo_t *cr, gboolean bright, double alpha)
107{
108 double amt;
109
110 if(bright)
111 amt = 0.5 + darktable.gui->overlay_contrast * 0.5;
112 else
113 amt = (1.0 - darktable.gui->overlay_contrast) * 0.5;
114
115 cairo_set_source_rgba(cr, darktable.gui->overlay_red * amt, darktable.gui->overlay_green * amt, darktable.gui->overlay_blue * amt, alpha);
116}
117
120static inline void dt_draw_star(cairo_t *cr, float x, float y, float r1, float r2)
121{
122 const float d = 2.0 * M_PI * 0.1f;
123 const float dx[10] = { sinf(0.0), sinf(d), sinf(2 * d), sinf(3 * d), sinf(4 * d),
124 sinf(5 * d), sinf(6 * d), sinf(7 * d), sinf(8 * d), sinf(9 * d) };
125 const float dy[10] = { cosf(0.0), cosf(d), cosf(2 * d), cosf(3 * d), cosf(4 * d),
126 cosf(5 * d), cosf(6 * d), cosf(7 * d), cosf(8 * d), cosf(9 * d) };
127
128 cairo_move_to(cr, x + r1 * dx[0], y - r1 * dy[0]);
129 for(int k = 1; k < 10; k++)
130 if(k & 1)
131 cairo_line_to(cr, x + r2 * dx[k], y - r2 * dy[k]);
132 else
133 cairo_line_to(cr, x + r1 * dx[k], y - r1 * dy[k]);
134 cairo_close_path(cr);
135}
136
137static inline void dt_draw_line(cairo_t *cr, float left, float top, float right, float bottom)
138{
139 cairo_move_to(cr, left, top);
140 cairo_line_to(cr, right, bottom);
141}
142
143static inline void dt_draw_grid(cairo_t *cr, const int num, const int left, const int top, const int right,
144 const int bottom)
145{
146 float width = right - left;
147 float height = bottom - top;
148
149 for(int k = 1; k < num; k++)
150 {
151 dt_draw_line(cr, left + k / (float)num * width, top, left + k / (float)num * width, bottom);
152 cairo_stroke(cr);
153 dt_draw_line(cr, left, top + k / (float)num * height, right, top + k / (float)num * height);
154 cairo_stroke(cr);
155 }
156}
157
158static inline float dt_curve_to_mouse(const float x, const float zoom_factor, const float offset)
159{
160 return (x - offset) * zoom_factor;
161}
162
163/* left, right, top, bottom are in curve coordinates [0..1] */
164static inline void dt_draw_grid_zoomed(cairo_t *cr, const int num, const float left, const float top,
165 const float right, const float bottom, const float width,
166 const float height, const float zoom_factor, const float zoom_offset_x,
167 const float zoom_offset_y)
168{
169 for(int k = 1; k < num; k++)
170 {
171 dt_draw_line(cr, dt_curve_to_mouse(left + k / (float)num, zoom_factor, zoom_offset_x) * width,
172 dt_curve_to_mouse(top, zoom_factor, zoom_offset_y) * -height,
173 dt_curve_to_mouse(left + k / (float)num, zoom_factor, zoom_offset_x) * width,
174 dt_curve_to_mouse(bottom, zoom_factor, zoom_offset_y) * -height);
175 cairo_stroke(cr);
176
177 dt_draw_line(cr, dt_curve_to_mouse(left, zoom_factor, zoom_offset_x) * width,
178 dt_curve_to_mouse(top + k / (float)num, zoom_factor, zoom_offset_y) * -height,
179 dt_curve_to_mouse(right, zoom_factor, zoom_offset_x) * width,
180 dt_curve_to_mouse(top + k / (float)num, zoom_factor, zoom_offset_y) * -height);
181 cairo_stroke(cr);
182 }
183}
184
185__OMP_DECLARE_SIMD__(uniform(base))
186static inline float dt_log_scale_axis(const float x, const float base)
187{
188 return logf(x * (base - 1.0f) + 1.f) / logf(base);
189}
190
191static inline void dt_draw_loglog_grid(cairo_t *cr, const int num, const int left, const int top, const int right,
192 const int bottom, const float base)
193{
194 float width = right - left;
195 float height = bottom - top;
196
197 for(int k = 1; k < num; k++)
198 {
199 const float x = dt_log_scale_axis(k / (float)num, base);
200 dt_draw_line(cr, left + x * width, top, left + x * width, bottom);
201 cairo_stroke(cr);
202 dt_draw_line(cr, left, top + x * height, right, top + x * height);
203 cairo_stroke(cr);
204 }
205}
206
207static inline void dt_draw_semilog_x_grid(cairo_t *cr, const int num, const int left, const int top,
208 const int right, const int bottom, const float base)
209{
210 float width = right - left;
211 float height = bottom - top;
212
213 for(int k = 1; k < num; k++)
214 {
215 const float x = dt_log_scale_axis(k / (float)num, base);
216 dt_draw_line(cr, left + x * width, top, left + x * width, bottom);
217 cairo_stroke(cr);
218 dt_draw_line(cr, left, top + k / (float)num * height, right, top + k / (float)num * height);
219 cairo_stroke(cr);
220 }
221}
222
223static inline void dt_draw_semilog_y_grid(cairo_t *cr, const int num, const int left, const int top,
224 const int right, const int bottom, const float base)
225{
226 float width = right - left;
227 float height = bottom - top;
228
229 for(int k = 1; k < num; k++)
230 {
231 const float x = dt_log_scale_axis(k / (float)num, base);
232 dt_draw_line(cr, left + k / (float)num * width, top, left + k / (float)num * width, bottom);
233 cairo_stroke(cr);
234 dt_draw_line(cr, left, top + x * height, right, top + x * height);
235 cairo_stroke(cr);
236 }
237}
238
239
240static inline void dt_draw_vertical_lines(cairo_t *cr, const int num, const int left, const int top,
241 const int right, const int bottom)
242{
243 float width = right - left;
244
245 for(int k = 1; k < num; k++)
246 {
247 cairo_move_to(cr, left + k / (float)num * width, top);
248 cairo_line_to(cr, left + k / (float)num * width, bottom);
249 cairo_stroke(cr);
250 }
251}
252
253static inline void dt_draw_horizontal_lines(cairo_t *cr, const int num, const int left, const int top,
254 const int right, const int bottom)
255{
256 float height = bottom - top;
257
258 for(int k = 1; k < num; k++)
259 {
260 cairo_move_to(cr, left, top + k / (float)num * height);
261 cairo_line_to(cr, right, top + k / (float)num * height);
262 cairo_stroke(cr);
263 }
264}
265
266static inline dt_draw_curve_t *dt_draw_curve_new(const float min, const float max, unsigned int type)
267{
268 dt_draw_curve_t *c = (dt_draw_curve_t *)malloc(sizeof(dt_draw_curve_t));
269 c->csample.m_samplingRes = 0x10000;
270 c->csample.m_outputRes = 0x10000;
271 c->csample.m_Samples = (uint16_t *)malloc(sizeof(uint16_t) * 0x10000);
272
273 c->c.m_spline_type = type;
274 c->c.m_numAnchors = 0;
275 c->c.m_min_x = 0.0;
276 c->c.m_max_x = 1.0;
277 c->c.m_min_y = 0.0;
278 c->c.m_max_y = 1.0;
279 return c;
280}
281
283{
284 dt_free(c->csample.m_Samples);
285 dt_free(c);
286}
287
288static inline void dt_draw_curve_set_point(dt_draw_curve_t *c, const int num, const float x, const float y)
289{
290 c->c.m_anchors[num].x = x;
291 c->c.m_anchors[num].y = y;
292}
293
294static inline void dt_draw_curve_smaple_values(dt_draw_curve_t *c, const float min, const float max, const int res,
295 float *x, float *y)
296{
297 if(x)
298 {
300 for(int k = 0; k < res; k++) x[k] = k * (1.0f / res);
301 }
302 if(y)
303 {
305 for(int k = 0; k < res; k++) y[k] = min + (max - min) * c->csample.m_Samples[k] * (1.0f / 0x10000);
306 }
307}
308
309static inline void dt_draw_curve_calc_values(dt_draw_curve_t *c, const float min, const float max, const int res,
310 float *x, float *y)
311{
312 c->csample.m_samplingRes = res;
313 c->csample.m_outputRes = 0x10000;
314 CurveDataSample(&c->c, &c->csample);
315 dt_draw_curve_smaple_values(c, min, max, res, x, y);
316}
317
318static inline void dt_draw_curve_calc_values_V2_nonperiodic(dt_draw_curve_t *c, const float min, const float max,
319 const int res, float *x, float *y)
320{
321 c->csample.m_samplingRes = res;
322 c->csample.m_outputRes = 0x10000;
323 CurveDataSampleV2(&c->c, &c->csample);
324 dt_draw_curve_smaple_values(c, min, max, res, x, y);
325}
326
327static inline void dt_draw_curve_calc_values_V2_periodic(dt_draw_curve_t *c, const float min, const float max,
328 const int res, float *x, float *y)
329{
330 c->csample.m_samplingRes = res;
331 c->csample.m_outputRes = 0x10000;
332 CurveDataSampleV2Periodic(&c->c, &c->csample);
333 dt_draw_curve_smaple_values(c, min, max, res, x, y);
334}
335
336static inline void dt_draw_curve_calc_values_V2(dt_draw_curve_t *c, const float min, const float max,
337 const int res, float *x, float *y, const gboolean periodic)
338{
339 if(periodic)
341 else
343 }
344
345static inline float dt_draw_curve_calc_value(dt_draw_curve_t *c, const float x)
346{
347 float xa[20], ya[20];
348 float val = 0.f;
349 float *ypp = NULL;
350 for(int i = 0; i < c->c.m_numAnchors; i++)
351 {
352 xa[i] = c->c.m_anchors[i].x;
353 ya[i] = c->c.m_anchors[i].y;
354 }
355 ypp = interpolate_set(c->c.m_numAnchors, xa, ya, c->c.m_spline_type);
356 if(ypp)
357 {
358 val = interpolate_val(c->c.m_numAnchors, xa, x, ya, ypp, c->c.m_spline_type);
359 dt_free(ypp);
360 }
361 return MIN(MAX(val, c->c.m_min_y), c->c.m_max_y);
362}
363
364static inline int dt_draw_curve_add_point(dt_draw_curve_t *c, const float x, const float y)
365{
366 c->c.m_anchors[c->c.m_numAnchors].x = x;
367 c->c.m_anchors[c->c.m_numAnchors].y = y;
368 c->c.m_numAnchors++;
369 return 0;
370}
371
372// linear x linear y
373static inline void dt_draw_histogram_8_linxliny(cairo_t *cr, const uint32_t *hist, int32_t channels,
374 int32_t channel)
375{
376 cairo_move_to(cr, 0, 0);
377 for(int k = 0; k < 256; k++) cairo_line_to(cr, k, hist[channels * k + channel]);
378 cairo_line_to(cr, 255, 0);
379 cairo_close_path(cr);
380 cairo_fill(cr);
381}
382
383static inline void dt_draw_histogram_8_zoomed(cairo_t *cr, const uint32_t *hist, int32_t channels, int32_t channel,
384 const float zoom_factor, const float zoom_offset_x,
385 const float zoom_offset_y, gboolean linear)
386{
387 cairo_move_to(cr, -zoom_offset_x, -zoom_offset_y);
388 for(int k = 0; k < 256; k++)
389 {
390 const float value = ((float)hist[channels * k + channel] - zoom_offset_y) * zoom_factor;
391 const float hist_value = value < 0 ? 0.f : value;
392 cairo_line_to(cr, ((float)k - zoom_offset_x) * zoom_factor, linear ? hist_value : logf(1.0f + hist_value));
393 }
394 cairo_line_to(cr, (255.f - zoom_offset_x), -zoom_offset_y * zoom_factor);
395 cairo_close_path(cr);
396 cairo_fill(cr);
397}
398
399// log x (scalable) & linear y
400static inline void dt_draw_histogram_8_logxliny(cairo_t *cr, const uint32_t *hist, int32_t channels,
401 int32_t channel, float base_log)
402{
403 cairo_move_to(cr, 0, 0);
404 for(int k = 0; k < 256; k++)
405 {
406 const float x = logf((float)k / 255.0f * (base_log - 1.0f) + 1.0f) / logf(base_log) * 255.0f;
407 const float y = hist[channels * k + channel];
408 cairo_line_to(cr, x, y);
409 }
410 cairo_line_to(cr, 255, 0);
411 cairo_close_path(cr);
412 cairo_fill(cr);
413}
414
415// log x (scalable) & log y
416static inline void dt_draw_histogram_8_logxlogy(cairo_t *cr, const uint32_t *hist, int32_t channels,
417 int32_t channel, float base_log)
418{
419 cairo_move_to(cr, 0, 0);
420 for(int k = 0; k < 256; k++)
421 {
422 const float x = logf((float)k / 255.0f * (base_log - 1.0f) + 1.0f) / logf(base_log) * 255.0f;
423 const float y = logf(1.0 + hist[channels * k + channel]);
424 cairo_line_to(cr, x, y);
425 }
426 cairo_line_to(cr, 255, 0);
427 cairo_close_path(cr);
428 cairo_fill(cr);
429}
430
431// linear x log y
432static inline void dt_draw_histogram_8_linxlogy(cairo_t *cr, const uint32_t *hist, int32_t channels,
433 int32_t channel)
434{
435 cairo_move_to(cr, 0, 0);
436 for(int k = 0; k < 256; k++) cairo_line_to(cr, k, logf(1.0 + hist[channels * k + channel]));
437 cairo_line_to(cr, 255, 0);
438 cairo_close_path(cr);
439 cairo_fill(cr);
440}
441
442// log x (scalable)
443static inline void dt_draw_histogram_8_log_base(cairo_t *cr, const uint32_t *hist, int32_t channels,
444 int32_t channel, const gboolean linear, float base_log)
445{
446
447 if(linear) // linear y
448 dt_draw_histogram_8_logxliny(cr, hist, channels, channel, base_log);
449 else // log y
450 dt_draw_histogram_8_logxlogy(cr, hist, channels, channel, base_log);
451}
452
453// linear x
454static inline void dt_draw_histogram_8(cairo_t *cr, const uint32_t *hist, int32_t channels, int32_t channel,
455 const gboolean linear)
456{
457 if(linear) // linear y
458 dt_draw_histogram_8_linxliny(cr, hist, channels, channel);
459 else // log y
460 dt_draw_histogram_8_linxlogy(cr, hist, channels, channel);
461}
462
464static inline void dt_draw_cairo_to_gdk_pixbuf(uint8_t *data, unsigned int width, unsigned int height)
465{
466 for(uint32_t y = 0; y < height; y++)
467 for(uint32_t x = 0; x < width; x++)
468 {
469 uint8_t *r, *g, *b, *a, tmp;
470 r = &data[(y * width + x) * 4 + 0];
471 g = &data[(y * width + x) * 4 + 1];
472 b = &data[(y * width + x) * 4 + 2];
473 a = &data[(y * width + x) * 4 + 3];
474
475 // switch r and b
476 tmp = *r;
477 *r = *b;
478 *b = tmp;
479
480 // cairo uses premultiplied alpha, reverse that
481 if(*a != 0)
482 {
483 float inv_a = 255.0 / *a;
484 *r *= inv_a;
485 *g *= inv_a;
486 *b *= inv_a;
487 }
488 }
489}
490
491static inline void dt_cairo_perceptual_gradient(cairo_pattern_t *grad, double alpha)
492{
493 // Create a linear gradient from black to white
494 cairo_pattern_add_color_stop_rgba(grad, 0.0, 0.0, 0.0, 0.0, alpha);
495 cairo_pattern_add_color_stop_rgba(grad, 1.0, 1.0, 1.0, 1.0, alpha);
496}
497
498static inline GdkPixbuf *dt_draw_paint_to_pixbuf
499 (GtkWidget *widget, const guint pixbuf_size, const int flags,
500 void (*dtgtk_cairo_paint_fct)(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data))
501{
502 GdkRGBA fg_color;
503 GtkStyleContext *context = gtk_widget_get_style_context(widget);
504 GtkStateFlags state = gtk_widget_get_state_flags(widget);
505 gtk_style_context_get_color(context, state, &fg_color);
506
507 const int dim = DT_PIXEL_APPLY_DPI(pixbuf_size);
508 cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, dim, dim);
509 cairo_t *cr = cairo_create(cst);
510 gdk_cairo_set_source_rgba(cr, &fg_color);
511 (*dtgtk_cairo_paint_fct)(cr, 0, 0, dim, dim, flags, NULL);
512 cairo_destroy(cr);
513 uint8_t *data = cairo_image_surface_get_data(cst);
514 dt_draw_cairo_to_gdk_pixbuf(data, dim, dim);
515 const size_t size = (size_t)dim * dim * 4;
516 uint8_t *buf = (uint8_t *)malloc(size);
517 memcpy(buf, data, size);
518 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data(buf, GDK_COLORSPACE_RGB, TRUE, 8, dim, dim, dim * 4,
519 (GdkPixbufDestroyNotify)free, NULL);
520 cairo_surface_destroy(cst);
521 return pixbuf;
522}
523
524/***** SHAPES */
525
526// Helper that fills the current path with CAIRO_OPERATOR_CLEAR,
527// effectively erasing all drawings below,
528// but preserving the path for further drawing.
529static void _draw_fill_clear(cairo_t *cr, gboolean preserve)
530{
531 cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
532 if(preserve)
533 cairo_fill_preserve(cr);
534 else
535 cairo_fill(cr);
536 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
537}
538
539static void _fill_clear(cairo_t *cr)
540{
542}
543
544static void _fill_clear_preserve(cairo_t *cr)
545{
547}
548
549static inline void dt_draw_set_dash_style(cairo_t *cr, dt_draw_dash_type_t type, float zoom_scale)
550{
551 // return early if no dash is needed
553 {
554 cairo_set_dash(cr, NULL, 0, 0);
555 return;
556 }
557
558 double pattern[2];
559
560 switch(type)
561 {
562 case DT_MASKS_NO_DASH:
563 pattern[0] = 0.0f;
564 pattern[1] = 0.0f;
565 break;
566
568 pattern[0] = DT_DRAW_SCALE_DASH / zoom_scale;
569 pattern[1] = DT_DRAW_SCALE_DASH / zoom_scale;
570 break;
571
573 pattern[0] = (DT_DRAW_SCALE_DASH * 0.25f) / zoom_scale;
574 pattern[1] = (DT_DRAW_SCALE_DASH) / zoom_scale;
575 break;
576
577 default:
578 cairo_set_dash(cr, NULL, 0, 0);
579 return;
580
581 }
582 const int pattern_len = 2;
583 cairo_set_dash(cr, pattern, pattern_len, 0);
584}
585
597static inline void dt_draw_node(cairo_t *cr, const gboolean square, const gboolean point_action, const gboolean selected, const float zoom_scale, const float x, const float y)
598{
599 cairo_save(cr);
600
601 const float node_width = (selected || point_action) ? DT_DRAW_RADIUS_NODE_SELECTED / zoom_scale : DT_DRAW_RADIUS_NODE / zoom_scale;
602 // square for corner nodes, circle for others (curve)
603 if(square)
604 {
605 const float pos = node_width * 0.7071f; // radius * sin(45°) to have the same diagonal as the circle
606 cairo_rectangle(cr, x - pos, y - pos, node_width * 2.f, node_width * 2.f);
607 }
608 else
609 cairo_arc(cr, x, y, node_width * 1.2f, 0.0, 2.0 * M_PI);
610
611 // Erase all drawings below
613
614 const float line_width = (point_action && selected) ? DT_DRAW_SIZE_LINE_SELECTED / zoom_scale
615 : DT_DRAW_SIZE_LINE / zoom_scale;
616
617 cairo_set_line_width(cr, line_width);
618 dt_draw_set_color_overlay(cr, TRUE, selected || point_action ? 1 : 0.8);
619 cairo_fill_preserve(cr);
620
621 // draw dark border
622 cairo_set_line_width(cr, (selected && !point_action) ? line_width * 2. : line_width);
624 cairo_stroke(cr);
625
627 {
628 const float debug_radius = DT_GUI_MOUSE_EFFECT_RADIUS_SCALED;
629 cairo_arc(cr, x, y, debug_radius, 0.0, 2.0 * M_PI);
630 cairo_set_line_width(cr, line_width);
631 cairo_set_source_rgba(cr, 0.0, 1.0, 0.0, 1.0);
632 cairo_stroke(cr);
633 }
634
635 cairo_restore(cr);
636}
637
648static inline void dt_draw_handle(cairo_t *cr, const float pt[2], const float zoom_scale,
649 const float handle[2], const gboolean selected, const gboolean square)
650{
651 cairo_save(cr);
652
653
654 // Draw only if the line is long enough
655 // and shorten the line by the size of the nodes so it does not overlap with them
656 //float shorten = 0; //(DT_DRAW_RADIUS_NODE / zoom_scale) * 0.5f;
657 //float f = shorten / tail_len;
658 if(pt)
659 {
660 float delta_x = handle[0] - pt[0];
661 float delta_y = handle[1] - pt[1];
662 float start_x = pt[0] + delta_x;
663 float start_y = pt[1] + delta_y;
664 float end_x = handle[0] - delta_x;
665 float end_y = handle[1] - delta_y;
666 cairo_move_to(cr, start_x, start_y);
667 cairo_line_to(cr, end_x, end_y);
668
669 cairo_set_line_width(cr, DT_DRAW_SIZE_LINE_HIGHLIGHT * 0.6 / zoom_scale);
671 cairo_stroke_preserve(cr);
672 cairo_set_line_width(cr, DT_DRAW_SIZE_LINE * 0.6 / zoom_scale);
674 cairo_stroke(cr);
675 }
676
677 // Draw the control handle (1/4 smaller than a node)
678 const float handle_radius = 0.75 * (selected ? DT_DRAW_RADIUS_NODE_SELECTED / zoom_scale
679 : DT_DRAW_RADIUS_NODE / zoom_scale);
680
681 if(square)
682 {
683 const float square_width = handle_radius * 0.7071f; // handle_radius * sin(45°) to have the same diagonal as the circle
684 cairo_rectangle(cr, handle[0] - square_width, handle[1] - square_width, square_width * 2.f, square_width * 2.f);
685 }
686 else
687 cairo_arc(cr, handle[0], handle[1], handle_radius, 0, 2.0 * M_PI);
688
689 const float line_width_dark = selected
691 : (DT_DRAW_SIZE_LINE_HIGHLIGHT / zoom_scale);
692 const float line_width_bright = selected
693 ? (DT_DRAW_SIZE_LINE_SELECTED / zoom_scale)
694 : (DT_DRAW_SIZE_LINE / zoom_scale);
695
696 // OUTLINE (dark)
697 cairo_set_line_width(cr, line_width_dark * 1.125);
699 cairo_stroke_preserve(cr);
700 // NORMAL (bright)
701 cairo_set_line_width(cr, line_width_bright * 1.5);
703 cairo_stroke_preserve(cr);
704 // Erase all drawings below
705 _fill_clear(cr);
706
707
708 // uncomment this part if you want to see "real" control points
709 /*cairo_move_to(cr, gpt->points[n*6+2],gpt->points[n*6+3]);
710 cairo_line_to(cr, gpt->points[n*6],gpt->points[n*6+1]);
711 cairo_stroke(cr);
712 cairo_move_to(cr, gpt->points[n*6+2],gpt->points[n*6+3]);
713 cairo_line_to(cr, gpt->points[n*6+4],gpt->points[n*6+5]);
714 cairo_stroke(cr);*/
715
716 cairo_restore(cr);
717}
718
719typedef void (*shape_draw_function_t)(cairo_t *cr, const float *points, const int points_count, const int nb, const gboolean border, const gboolean source);
720
734static inline void dt_draw_shape_lines(const dt_draw_dash_type_t dash_type, const gboolean source, cairo_t *cr, const int nb, const gboolean selected,
735 const float zoom_scale, const float *points, const int points_count, const shape_draw_function_t *draw_shape_func, const cairo_line_cap_t line_cap)
736{
737 cairo_save(cr);
738
739 cairo_set_line_cap(cr, line_cap);
740 // Are we drawing a border ?
741 const gboolean border = (dash_type != DT_MASKS_NO_DASH);
742
743 // Draw the shape from the integrated function if any
744 if(points && points_count >= 2 && draw_shape_func)
745 (*draw_shape_func)(cr, points, points_count, nb, border, FALSE);
746
747 const dt_draw_dash_type_t dash = (dash_type && !source)
748 ? dash_type : DT_MASKS_NO_DASH;
749
750 dt_draw_set_dash_style(cr, dash, zoom_scale);
751
752 const float line_width_dark = selected
754 : DT_DRAW_SIZE_LINE_HIGHLIGHT / zoom_scale;
755 const float line_width_bright = selected
756 ? DT_DRAW_SIZE_LINE_SELECTED / zoom_scale
757 : DT_DRAW_SIZE_LINE / zoom_scale;
758
759 // OUTLINE (dark)
760 cairo_set_line_width(cr, line_width_dark);
761 dt_draw_set_color_overlay(cr, FALSE, dash_type ? 0.3f : 0.9f);
762 cairo_stroke_preserve(cr);
763
764 // NORMAL (bright)
765 cairo_set_line_width(cr, line_width_bright);
767 cairo_stroke(cr);
768
769 cairo_restore(cr);
770}
771
781static inline void dt_draw_stroke_line(const dt_draw_dash_type_t dash_type, const gboolean source, cairo_t *cr,
782 const gboolean selected, const float zoom_scale, const cairo_line_cap_t line_cap)
783{
784 dt_draw_shape_lines(dash_type, source, cr, 0, selected, zoom_scale, NULL, 0, NULL, line_cap);
785}
786
787static void _draw_arrow_head(cairo_t *cr, const float arrow[2], const float arrow_x_a, const float arrow_y_a,
788 const float arrow_x_b, const float arrow_y_b)
789{
790 //draw the arrow head
791 cairo_move_to(cr, arrow_x_a, arrow_y_a);
792 cairo_line_to(cr, arrow[0], arrow[1]);
793 cairo_line_to(cr, arrow_x_b, arrow_y_b);
794 // close the arrow head
795 cairo_close_path(cr);
796}
797
798static void _draw_arrow_tail(cairo_t *cr, const float arrow_bud_x, const float arrow_bud_y,
799 const float tail[2], const gboolean draw_tail)
800{
801 if(draw_tail) dt_draw_line(cr, arrow_bud_x, arrow_bud_y, tail[0], tail[1]);
802}
803
817static inline void dt_draw_arrow(cairo_t *cr, const float zoom_scale,const gboolean selected, const gboolean draw_tail,
818 const dt_draw_dash_type_t dash_style, const float arrow[2], const float tail[2], const float angle)
819{
820 // calculate the coordinates of the two base points of the arrow head
821 const float arrow_x_a = arrow[0] + (DT_DRAW_SCALE_ARROW / zoom_scale) * cosf(angle + (0.4f));
822 const float arrow_y_a = arrow[1] + (DT_DRAW_SCALE_ARROW / zoom_scale) * sinf(angle + (0.4f));
823 const float arrow_x_b = arrow[0] + (DT_DRAW_SCALE_ARROW / zoom_scale) * cosf(angle - (0.4f));
824 const float arrow_y_b = arrow[1] + (DT_DRAW_SCALE_ARROW / zoom_scale) * sinf(angle - (0.4f));
825 // Calculate the coordinates of the arrow base's midpoint
826 const float arrow_bud_x = (arrow_x_a + arrow_x_b) * 0.5f;
827 const float arrow_bud_y = (arrow_y_a + arrow_y_b) * 0.5f;
828
829 cairo_save(cr);
830 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
831
832 // we need to draw the arrow head and tail in two passes to get the dark and bright effect correctly
833
834 // dark
835 {
836 // arrow head
837 _draw_arrow_head(cr, arrow, arrow_x_a, arrow_y_a, arrow_x_b, arrow_y_b);
838 // Erase all drawings below
840
843
844 if(selected)
845 cairo_set_line_width(cr, 0.8f * DT_DRAW_SIZE_LINE_HIGHLIGHT_SELECTED / zoom_scale);
846 else
847 cairo_set_line_width(cr, 0.8f * DT_DRAW_SIZE_LINE_HIGHLIGHT / zoom_scale);
848 cairo_stroke(cr);
849
850 // arrow tail
851 _draw_arrow_tail(cr, arrow_bud_x, arrow_bud_y, tail, draw_tail);
852 dt_draw_set_dash_style(cr, dash_style, zoom_scale);
854 if(selected)
855 cairo_set_line_width(cr, DT_DRAW_SIZE_LINE_HIGHLIGHT_SELECTED / zoom_scale);
856 else
857 cairo_set_line_width(cr, DT_DRAW_SIZE_LINE_HIGHLIGHT / zoom_scale);
858 cairo_stroke(cr);
859 }
860
861 // bright
862 {
863 // arrow head
864 _draw_arrow_head(cr, arrow, arrow_x_a, arrow_y_a, arrow_x_b, arrow_y_b);
865 // erase all drawings below
866 cairo_set_source_rgba(cr, 0., 0., 0., 0.);
867 cairo_fill_preserve(cr);
868
871 if(selected)
872 cairo_set_line_width(cr, (2 * DT_DRAW_SIZE_LINE) / zoom_scale);
873 else
874 cairo_set_line_width(cr, (DT_DRAW_SIZE_LINE) / zoom_scale);
875 cairo_stroke(cr);
876
877 // arrow tail
878 _draw_arrow_tail(cr, arrow_bud_x, arrow_bud_y, tail, draw_tail);
879 dt_draw_set_dash_style(cr, dash_style, zoom_scale);
881 if(selected)
882 cairo_set_line_width(cr, (3 * DT_DRAW_SIZE_LINE) / zoom_scale);
883 else
884 cairo_set_line_width(cr, (2 * DT_DRAW_SIZE_LINE) / zoom_scale);
885 cairo_stroke(cr);
886 }
887 cairo_restore(cr);
888}
889
890static inline void dt_draw_cross(cairo_t *cr, const float zoom_scale, const float x, const float y)
891{
892 const float dx = DT_DRAW_SIZE_CROSS / zoom_scale;
893 const float dy = DT_DRAW_SIZE_CROSS / zoom_scale;
894 cairo_save(cr);
895
896 cairo_set_line_cap(cr, CAIRO_LINE_CAP_SQUARE);
898 cairo_set_line_width(cr, DT_DRAW_SIZE_LINE_HIGHLIGHT / zoom_scale);
900
901 cairo_move_to(cr, x + dx, y);
902 cairo_line_to(cr, x - dx, y);
903 cairo_move_to(cr, x, y + dy);
904 cairo_line_to(cr, x, y - dy);
905 cairo_stroke_preserve(cr);
906
907 cairo_set_line_width(cr, DT_DRAW_SIZE_LINE / zoom_scale);
909 cairo_stroke(cr);
910
911 cairo_restore(cr);
912}
913
914static inline void dt_draw_source_shape(cairo_t *cr, const float zoom_scale, const gboolean selected,
915 const float *source_pts, const int source_pts_count, const int nodes_nb, const shape_draw_function_t *draw_shape_func)
916{
917 cairo_save(cr);
918
919 cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND);
921
922 if(draw_shape_func)
923 (*draw_shape_func)(cr, source_pts, source_pts_count, nodes_nb, FALSE, TRUE);
924
925 //dark line
926 if(selected)
927 cairo_set_line_width(cr, DT_DRAW_SIZE_LINE_HIGHLIGHT_SELECTED / zoom_scale);
928 else
929 cairo_set_line_width(cr, DT_DRAW_SIZE_LINE_HIGHLIGHT / zoom_scale);
931 cairo_stroke_preserve(cr);
932
933 //bright line
934 if(selected)
935 cairo_set_line_width(cr, DT_DRAW_SIZE_LINE_SELECTED / zoom_scale);
936 else
937 cairo_set_line_width(cr, (1.5f * DT_DRAW_SIZE_LINE) / zoom_scale);
939 cairo_stroke(cr);
940
941 cairo_restore(cr);
942}
943
944static inline GdkPixbuf *dt_draw_get_pixbuf_from_cairo(DTGTKCairoPaintIconFunc paint, const int width, const int height)
945{
946 cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
947 cairo_t *cr = cairo_create(cst);
949 paint(cr, 0, 0, width, height, 0, NULL);
950 cairo_destroy(cr);
951 guchar *data = cairo_image_surface_get_data(cst);
953 return gdk_pixbuf_new_from_data(data, GDK_COLORSPACE_RGB, TRUE, 8, width, height,
954 cairo_image_surface_get_stride(cst), NULL, NULL);
955}
956
957#ifdef __cplusplus
958}
959#endif
960
961// clang-format off
962// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
963// vim: shiftwidth=2 expandtab tabstop=2 cindent
964// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
965// clang-format on
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
int width
Definition bilateral.h:1
int height
Definition bilateral.h:1
const float i
Definition colorspaces_inline_conversions.h:440
const float g
Definition colorspaces_inline_conversions.h:674
const float d
Definition colorspaces_inline_conversions.h:680
static const float const float const float min
Definition colorspaces_inline_conversions.h:438
const float max
Definition colorspaces_inline_conversions.h:490
const float top
Definition colorspaces_inline_conversions.h:443
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
int type
Definition common/metadata.c:62
float * interpolate_set(int n, float x[], float y[], unsigned int type)
Definition curve_tools.c:514
int CurveDataSample(CurveData *curve, CurveSample *sample)
Definition curve_tools.c:677
float interpolate_val(int n, float x[], float xval, float y[], float tangents[], unsigned int type)
Definition curve_tools.c:519
darktable_t darktable
Definition darktable.c:173
@ DT_DEBUG_MASKS
Definition darktable.h:726
#define dt_free(ptr)
Definition darktable.h:456
#define __OMP_DECLARE_SIMD__(...)
Definition darktable.h:263
static const dt_aligned_pixel_simd_t value
Definition darktable.h:577
#define __OMP_PARALLEL_FOR_SIMD__(...)
Definition darktable.h:259
static float dt_curve_to_mouse(const float x, const float zoom_factor, const float offset)
Definition draw.h:158
#define DT_DRAW_SCALE_DASH
Definition draw.h:79
#define DT_DRAW_SIZE_LINE
Definition draw.h:72
static void _draw_fill_clear(cairo_t *cr, gboolean preserve)
Definition draw.h:529
#define DT_DRAW_RADIUS_NODE_SELECTED
Definition draw.h:84
static void dt_draw_set_dash_style(cairo_t *cr, dt_draw_dash_type_t type, float zoom_scale)
Definition draw.h:549
static GdkPixbuf * dt_draw_paint_to_pixbuf(GtkWidget *widget, const guint pixbuf_size, const int flags, void(*dtgtk_cairo_paint_fct)(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data))
Definition draw.h:499
static void dt_draw_curve_calc_values(dt_draw_curve_t *c, const float min, const float max, const int res, float *x, float *y)
Definition draw.h:309
static void dt_draw_stroke_line(const dt_draw_dash_type_t dash_type, const gboolean source, cairo_t *cr, const gboolean selected, const float zoom_scale, const cairo_line_cap_t line_cap)
Stroke a line with style.
Definition draw.h:781
static void dt_draw_horizontal_lines(cairo_t *cr, const int num, const int left, const int top, const int right, const int bottom)
Definition draw.h:253
static void dt_draw_histogram_8_zoomed(cairo_t *cr, const uint32_t *hist, int32_t channels, int32_t channel, const float zoom_factor, const float zoom_offset_x, const float zoom_offset_y, gboolean linear)
Definition draw.h:383
static void dt_draw_handle(cairo_t *cr, const float pt[2], const float zoom_scale, const float handle[2], const gboolean selected, const gboolean square)
Draw a control handle attached to a point with a tail between the node and the handle.
Definition draw.h:648
#define DT_DRAW_SIZE_LINE_HIGHLIGHT
Definition draw.h:74
static void dt_draw_cross(cairo_t *cr, const float zoom_scale, const float x, const float y)
Definition draw.h:890
#define DT_DRAW_SIZE_LINE_SELECTED
Definition draw.h:73
static void dt_draw_histogram_8_logxlogy(cairo_t *cr, const uint32_t *hist, int32_t channels, int32_t channel, float base_log)
Definition draw.h:416
static void dt_draw_cairo_to_gdk_pixbuf(uint8_t *data, unsigned int width, unsigned int height)
Definition draw.h:464
static void dt_draw_histogram_8_linxlogy(cairo_t *cr, const uint32_t *hist, int32_t channels, int32_t channel)
Definition draw.h:432
static float dt_log_scale_axis(const float x, const float base)
Definition draw.h:186
static void _fill_clear_preserve(cairo_t *cr)
Definition draw.h:544
static void dt_draw_set_color_overlay(cairo_t *cr, gboolean bright, double alpha)
Definition draw.h:106
static void dt_draw_line(cairo_t *cr, float left, float top, float right, float bottom)
Definition draw.h:137
static void dt_draw_curve_smaple_values(dt_draw_curve_t *c, const float min, const float max, const int res, float *x, float *y)
Definition draw.h:294
static void dt_draw_histogram_8_linxliny(cairo_t *cr, const uint32_t *hist, int32_t channels, int32_t channel)
Definition draw.h:373
static void dt_draw_vertical_lines(cairo_t *cr, const int num, const int left, const int top, const int right, const int bottom)
Definition draw.h:240
static void dt_draw_grid(cairo_t *cr, const int num, const int left, const int top, const int right, const int bottom)
Definition draw.h:143
static void dt_draw_semilog_y_grid(cairo_t *cr, const int num, const int left, const int top, const int right, const int bottom, const float base)
Definition draw.h:223
static float dt_draw_curve_calc_value(dt_draw_curve_t *c, const float x)
Definition draw.h:345
static void dt_cairo_perceptual_gradient(cairo_pattern_t *grad, double alpha)
Definition draw.h:491
dt_draw_dash_type_t
Definition draw.h:92
@ DT_MASKS_DASH_STICK
Definition draw.h:94
@ DT_MASKS_DASH_ROUND
Definition draw.h:95
@ DT_MASKS_NO_DASH
Definition draw.h:93
static void dt_draw_star(cairo_t *cr, float x, float y, float r1, float r2)
Definition draw.h:120
static void dt_draw_curve_calc_values_V2_nonperiodic(dt_draw_curve_t *c, const float min, const float max, const int res, float *x, float *y)
Definition draw.h:318
#define DT_DRAW_SCALE_ARROW
Definition draw.h:80
static void dt_draw_curve_destroy(dt_draw_curve_t *c)
Definition draw.h:282
static void dt_draw_curve_calc_values_V2(dt_draw_curve_t *c, const float min, const float max, const int res, float *x, float *y, const gboolean periodic)
Definition draw.h:336
#define DT_DRAW_SIZE_CROSS
Definition draw.h:76
static void dt_draw_shape_lines(const dt_draw_dash_type_t dash_type, const gboolean source, cairo_t *cr, const int nb, const gboolean selected, const float zoom_scale, const float *points, const int points_count, const shape_draw_function_t *draw_shape_func, const cairo_line_cap_t line_cap)
Draw the lines of a mask shape.
Definition draw.h:734
static void dt_draw_histogram_8_log_base(cairo_t *cr, const uint32_t *hist, int32_t channels, int32_t channel, const gboolean linear, float base_log)
Definition draw.h:443
#define DT_DRAW_RADIUS_NODE
Definition draw.h:83
static void dt_draw_curve_set_point(dt_draw_curve_t *c, const int num, const float x, const float y)
Definition draw.h:288
static void dt_draw_arrow(cairo_t *cr, const float zoom_scale, const gboolean selected, const gboolean draw_tail, const dt_draw_dash_type_t dash_style, const float arrow[2], const float tail[2], const float angle)
Draw an arrow with head and, if needed, tail. The length of the arrow head is defined by DT_DRAW_SCAL...
Definition draw.h:817
static int dt_draw_curve_add_point(dt_draw_curve_t *c, const float x, const float y)
Definition draw.h:364
static void dt_draw_histogram_8_logxliny(cairo_t *cr, const uint32_t *hist, int32_t channels, int32_t channel, float base_log)
Definition draw.h:400
static GdkPixbuf * dt_draw_get_pixbuf_from_cairo(DTGTKCairoPaintIconFunc paint, const int width, const int height)
Definition draw.h:944
static void _fill_clear(cairo_t *cr)
Definition draw.h:539
#define DT_DRAW_SIZE_LINE_HIGHLIGHT_SELECTED
Definition draw.h:75
static void dt_draw_semilog_x_grid(cairo_t *cr, const int num, const int left, const int top, const int right, const int bottom, const float base)
Definition draw.h:207
static void dt_draw_histogram_8(cairo_t *cr, const uint32_t *hist, int32_t channels, int32_t channel, const gboolean linear)
Definition draw.h:454
static dt_draw_curve_t * dt_draw_curve_new(const float min, const float max, unsigned int type)
Definition draw.h:266
#define M_PI
Definition draw.h:64
void(* shape_draw_function_t)(cairo_t *cr, const float *points, const int points_count, const int nb, const gboolean border, const gboolean source)
Definition draw.h:719
static void dt_draw_loglog_grid(cairo_t *cr, const int num, const int left, const int top, const int right, const int bottom, const float base)
Definition draw.h:191
static void _draw_arrow_head(cairo_t *cr, const float arrow[2], const float arrow_x_a, const float arrow_y_a, const float arrow_x_b, const float arrow_y_b)
Definition draw.h:787
static void dt_draw_curve_calc_values_V2_periodic(dt_draw_curve_t *c, const float min, const float max, const int res, float *x, float *y)
Definition draw.h:327
static void dt_draw_source_shape(cairo_t *cr, const float zoom_scale, const gboolean selected, const float *source_pts, const int source_pts_count, const int nodes_nb, const shape_draw_function_t *draw_shape_func)
Definition draw.h:914
static void dt_draw_grid_zoomed(cairo_t *cr, const int num, const float left, const float top, const float right, const float bottom, const float width, const float height, const float zoom_factor, const float zoom_offset_x, const float zoom_offset_y)
Definition draw.h:164
static void dt_draw_node(cairo_t *cr, const gboolean square, const gboolean point_action, const gboolean selected, const float zoom_scale, const float x, const float y)
Draw an node point of a mask.
Definition draw.h:597
static void _draw_arrow_tail(cairo_t *cr, const float arrow_bud_x, const float arrow_bud_y, const float tail[2], const gboolean draw_tail)
Definition draw.h:798
void(* DTGTKCairoPaintIconFunc)(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
Definition dtgtk/paint.h:75
void dt_gui_gtk_set_source_rgba(cairo_t *cr, dt_gui_color_t color, float opacity_coef)
Definition gtk.c:369
@ DT_GUI_COLOR_BUTTON_FG
Definition gtk.h:107
#define DT_GUI_MOUSE_EFFECT_RADIUS_SCALED
Definition gtk.h:71
#define DT_PIXEL_APPLY_DPI(value)
Definition gtk.h:75
static const float x
Definition iop_profile.h:235
@ linear
Definition lightroom.c:368
float *const restrict const size_t k
Definition luminance_mask.h:78
size_t size
Definition mipmap_cache.c:3
dt_mipmap_buffer_dsc_flags flags
Definition mipmap_cache.c:4
struct _GtkWidget GtkWidget
Definition splash.h:29
int CurveDataSampleV2Periodic(CurveData *curve, CurveSample *sample)
Definition splines.cpp:848
int CurveDataSampleV2(CurveData *curve, CurveSample *sample)
Definition splines.cpp:752
const float uint32_t state[4]
Definition src/develop/noise_generator.h:72
const float r
Definition src/develop/noise_generator.h:101
Definition curve_tools.h:64
Definition curve_tools.h:84
struct dt_gui_gtk_t * gui
Definition darktable.h:774
int32_t unmuted
Definition darktable.h:759
Definition draw.h:100
CurveSample csample
Definition draw.h:102
CurveData c
Definition draw.h:101
double overlay_contrast
Definition gtk.h:160
double overlay_red
Definition gtk.h:160
double overlay_green
Definition gtk.h:160
double overlay_blue
Definition gtk.h:160
#define MIN(a, b)
Definition thinplate.c:32
#define MAX(a, b)
Definition thinplate.c:29