Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
masks.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2013-2014, 2016, 2019, 2021 Aldric Renaudin.
4 Copyright (C) 2013, 2018, 2020-2021 Pascal Obry.
5 Copyright (C) 2013 Simon Spannagel.
6 Copyright (C) 2013-2014, 2016-2018 Tobias Ellinghaus.
7 Copyright (C) 2013-2017, 2019-2020 Ulrich Pegelow.
8 Copyright (C) 2014-2016 Roman Lebedev.
9 Copyright (C) 2017-2019 Edgardo Hoszowski.
10 Copyright (C) 2021 Hanno Schwalm.
11 Copyright (C) 2021 Hubert Kowalski.
12 Copyright (C) 2021 luzpaz.
13 Copyright (C) 2021 Philipp Lutz.
14 Copyright (C) 2021 Ralf Brown.
15 Copyright (C) 2022 Martin Bařinka.
16 Copyright (C) 2023, 2025-2026 Aurélien PIERRE.
17 Copyright (C) 2023 Luca Zulberti.
18 Copyright (C) 2025 Alynx Zhou.
19 Copyright (C) 2025-2026 Guillaume Stutin.
20
21 darktable is free software: you can redistribute it and/or modify
22 it under the terms of the GNU General Public License as published by
23 the Free Software Foundation, either version 3 of the License, or
24 (at your option) any later version.
25
26 darktable is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 GNU General Public License for more details.
30
31 You should have received a copy of the GNU General Public License
32 along with darktable. If not, see <http://www.gnu.org/licenses/>.
33*/
34
35
36/*
37Typical forms tree structure :
38
39GList dev->forms
40 |
41 0) dt_masks_form_t circle --------------------> ID 1771813676, "circle #2"
42 | { GList *points
43 | | dt_masks_form_t --------------------> dt_masks_type_t type; const dt_masks_functions_t *functions;
44 | | float source[2]; char name[128]; int formid; int version;
45 | { GList *points;
46 | | dt_masks_node_circle_t ----> float center[2]; float radius; float border;
47 |
48 |
49 1) dt_masks_form_t group ---------------------> ID 1771813678, "grp retouch"
50 | { GList *points
51 | |-> dt_masks_form_group_t : ID 1771813676, parentid: 1771813678, state: use show union
52 | |-> dt_masks_form_group_t : ID 1771942330, parentid: 1771813678, state: use show union
53 |
54 |
55 2) dt_masks_form_t polygon -------------------> ID 1771815454, "polygon #1"
56 | { GList *points
57 | | dt_masks_form_t -------------------> dt_masks_type_t type; const dt_masks_functions_t *functions;
58 | | float source[2]; char name[128]; int formid; int version;
59 | { GList *points;
60 | | dt_masks_node_polygon_t ---> float node[2]; float ctrl1[2]; float ctrl2[2]; float border[2];
61 | | dt_masks_node_polygon_t ---> ...
62 | | ...
63 | | ...
64 |
65 |
66 3) dt_masks_form_t group ---------------------> ID 1771942331, "grp exposure"
67 | { GList *points
68 | |-> dt_masks_form_group_t : ID 1771815454, parentid: 1771942331, state: use show union
69 | |-> dt_masks_form_group_t : ID 1771877226, parentid: 1771942331, state: use show union
70 | |-> dt_masks_form_group_t : ID 1771877232, parentid: 1771942331, state: use show union
71 |
72 |
73 4) dt_masks_form_t ellipse -------------------> ID 1771877226, "ellipse #1"
74 | { GList *points
75 | | dt_masks_form_t --------------------> dt_masks_type_t type; const dt_masks_functions_t *functions;
76 | | float source[2]; char name[128]; int formid; int version;
77 | { GList *points;
78 | | dt_masks_node_ellipse_t ---> float center[2]; float radius[2]; float rotation;
79 | float border; dt_masks_ellipse_flags_t flags;
80 |
81 |
82 5) dt_masks_form_t brush ---------------------> ID 1771877232, "brush #1"
83 | { GList *points
84 | | dt_masks_form_t --------------------> dt_masks_type_t type; const dt_masks_functions_t *functions;
85 | | float source[2]; char name[128]; int formid; int version;
86 | { GList *points;
87 | | dt_masks_node_brush_t -----> float node[2]; float pressure; float fading; float size;
88 | | dt_masks_pressure_sensitivity_t pressure_sensitivity;
89 | | dt_masks_node_brush_t -----> ...
90 | |
91 | | ...
92 | | ...
93 |
94 |
95 6) dt_masks_form_t gradient -------------------> ID 1771942330, "gradient #1"
96 | { GList *points
97 | | dt_masks_form_t ---------------------> dt_masks_type_t type; const dt_masks_functions_t *functions;
98 | | float source[2]; char name[128]; int formid; int version;
99 | { GList *points;
100 | | dt_masks_anchor_gradient_t -> float center[2]; float rotation; float extent; float steepness; float curvature;
101 |
102 7)...
103 |
104 ...
105
106
107*/
108
109#ifndef DT_DEVELOP_MASKS_H
110#define DT_DEVELOP_MASKS_H
111
112#include "develop/masks_types.h" // the vocabulary: shape kinds, states, and the value types
113#include "system/atomic.h"
114#include "common/logging.h"
115#include "system/macros.h"
116#include "system/simd.h"
117#include "common/times.h"
119#include "develop/develop.h" // dt_develop_t, and dt_iop_module_t through imageop.h
120#include "develop/pixelpipe.h"
121
122/* The per-shape function table is an implementation detail: every one of its members is
123 * dispatched from inside src/develop/masks/ and nowhere else (measured), so its definition
124 * lives in develop/masks/masks_functions.h and only this forward declaration is public.
125 * That is what lets this header drop widgets/draw.h -- the table was the only thing here
126 * naming a drawing type. The interactive-editing state (dt_masks_form_gui_t) and the whole
127 * event/drawing/menu API live in develop/masks_gui.h. */
129
130#include <assert.h>
131
132#ifdef __cplusplus
133extern "C" {
134#endif
135
136#define DEVELOP_MASKS_VERSION (6)
137
138
139
152
153
159
165
166
167
168
169
179
185
192
195{
196 float center[2]; // point in normalized input space
197 float radius;
198 float border;
200
210
220
232
243
244
245
246
247
248
249
251typedef struct dt_masks_form_t
252{
253 GList *points; // list of point structures (nodes)
256 // TRUE when gui_points->points uses the Bezier layout (points[k*6+2])
258
259 // position of the origin point of source (used only for clone)
260 // in normalized coordinates in raw input space
261 float source[2];
262
263 // cached center of gravity
264 // in normalized coordinates in raw input space
266 // FALSE means gravity_center/area are stale and must be recomputed before being read
267 // (see dt_masks_form_update_gravity_center() / dt_masks_form_invalidate_gravity_center()).
268 // Lets bulk paths (loading history, undo/redo) defer the actual computation to the one
269 // GUI hit-testing read site instead of paying it for every form up front.
271
272 // cached shape area, taken as a weight estimator to get
273 // the gravity center of multi-shapes by combining
274 // weight and gravity centers of all shapes
275 float area;
276 // name of the form
277 char name[128];
278 // id used to store the form
280 // version of the form
282
283 // number of live pointers to this form: dev->forms/allforms, hist->forms
284 // snapshots, undo/redo snapshots. See develop/masks/masks_history.h.
287
288// dt_masks_form_t must be fully defined above this include.
290
291/* Rasterisation entry points: dispatch through the private table. */
318
326
327
329typedef struct dt_masks_area_t
330{
331 int x;
332 int y;
333 int width;
336
338void dt_masks_area_scale(dt_masks_area_t *area, const double scale);
339
341gboolean dt_masks_area_intersects(const dt_masks_area_t *area, const dt_iop_roi_t *roi);
342
348gboolean dt_masks_form_is_in_roi(const dt_iop_module_t *iop_module, const dt_dev_pixelpipe_t *pipe,
350 const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out);
351
355 dt_masks_area_t *area);
356
357
358
360typedef struct dt_masks_dynbuf_t
361{
362 float *buffer;
363 char tag[128];
364 size_t pos;
365 size_t size;
367
368
369
370// Clone and spot forms share the same default presets, while regular drawn masks use their own.
371static inline gboolean dt_masks_form_uses_spot_defaults(const dt_masks_form_t *form)
372{
373 return (form->type & (DT_MASKS_CLONE | DT_MASKS_NON_CLONE)) != 0;
374}
375
376static inline gboolean dt_masks_form_is_clone(const dt_masks_form_t *form)
377{
378 return (form->type & DT_MASKS_CLONE) != 0;
379}
380
381static inline void dt_masks_reset_source(dt_masks_form_t *form)
382{
383 form->source[0] = 0.0f;
384 form->source[1] = 0.0f;
385}
386
387static inline void dt_masks_translate_source(dt_masks_form_t *form, const float delta_x, const float delta_y)
388{
389 form->source[0] += delta_x;
390 form->source[1] += delta_y;
391}
392
393static inline void dt_masks_translate_ctrl_node(float node[2], float ctrl1[2], float ctrl2[2],
394 const float delta_x, const float delta_y)
395{
396 node[0] += delta_x;
397 node[1] += delta_y;
398 ctrl1[0] += delta_x;
399 ctrl1[1] += delta_y;
400 ctrl2[0] += delta_x;
401 ctrl2[1] += delta_y;
402}
403
404static inline void dt_masks_set_ctrl_points(float ctrl1[2], float ctrl2[2], const float control_points[4])
405{
406 ctrl1[0] = control_points[0];
407 ctrl1[1] = control_points[1];
408 ctrl2[0] = control_points[2];
409 ctrl2[1] = control_points[3];
410}
411
412
415 const dt_dev_pixelpipe_iop_t *const piece,
416 dt_masks_form_t *const form,
417 float **buffer, dt_masks_area_t *area);
418
426 const dt_iop_roi_t *roi, float *buffer);
427
428// returns current masks version
429int dt_masks_version(void);
430
431
432
433// update masks from older versions
434int dt_masks_legacy_params(dt_develop_t *dev, void *params, const int old_version, const int new_version);
435/*
436 * TODO:
437 *
438 * int
439 * dt_masks_legacy_params(
440 * dt_develop_t *dev,
441 * const void *const old_params, const int old_version,
442 * void *new_params, const int new_version);
443 */
444
450dt_masks_form_t *dt_masks_get_from_id_ext(GList *forms, int id);
459 const struct dt_iop_module_t *mod_src);
462
464void dt_masks_read_masks_history(dt_develop_t *dev, const int32_t imgid);
466void dt_masks_write_masks_history_item(const int32_t imgid, const int num, dt_masks_form_t *form);
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
505
506void dt_masks_iop_use_same_as(struct dt_iop_module_t *module, struct dt_iop_module_t *src);
515
517int dt_masks_form_change_opacity(dt_develop_t *dev, dt_masks_form_t *form, int parentid, int up, const int flow);
518void dt_masks_form_move(dt_masks_form_t *grp, int formid, int up);
529int dt_masks_form_duplicate_in_group(dt_develop_t *dev, int group_id, int form_id);
530/* returns a duplicate tof form, including the formid */
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
554void dt_masks_duplicate_points(const dt_masks_form_t *base, dt_masks_form_t *dest, size_t node_size);
555
556
557
558
559
560
561
562
564static inline gboolean _dt_masks_dynbuf_growto(dt_masks_dynbuf_t *a, size_t size)
565{
566 const size_t newsize = dt_round_size_sse(sizeof(float) * size) / sizeof(float);
567 float *newbuf = dt_pixelpipe_cache_alloc_align_float_cache(newsize, 0);
568 if (IS_NULL_PTR(newbuf))
569 {
570 // not much we can do here except emit an error message
571 fprintf(stderr, "critical: out of memory for dynbuf '%s' with size request %" G_GSIZE_FORMAT "!\n", a->tag, size);
572 return FALSE;
573 }
574 if (a->buffer)
575 {
576 memcpy(newbuf, a->buffer, a->size * sizeof(float));
577 dt_print(DT_DEBUG_MASKS, "[masks dynbuf '%s'] grows to size %lu (is %p, was %p)\n", a->tag,
578 (unsigned long)a->size, newbuf, a->buffer);
580 }
581 a->size = newsize;
582 a->buffer = newbuf;
583 return TRUE;
584}
585
586static inline dt_masks_dynbuf_t *dt_masks_dynbuf_init(size_t size, const char *tag)
587{
588 assert(size > 0);
589 dt_masks_dynbuf_t *a = (dt_masks_dynbuf_t *)calloc(1, sizeof(dt_masks_dynbuf_t));
590
591 if(!IS_NULL_PTR(a))
592 {
593 g_strlcpy(a->tag, tag, sizeof(a->tag)); //only for debugging purposes
594 a->pos = 0;
596 dt_print(DT_DEBUG_MASKS, "[masks dynbuf '%s'] with initial size %lu (is %p)\n", a->tag,
597 (unsigned long)a->size, a->buffer);
598 if(IS_NULL_PTR(a->buffer))
599 {
600 dt_free(a);
601 }
602 }
603 return a;
604}
605
606static inline void dt_masks_dynbuf_add_2(dt_masks_dynbuf_t *a, float value1, float value2)
607{
608 assert(!IS_NULL_PTR(a));
609 assert(a->pos <= a->size);
610 if(__builtin_expect(a->pos + 2 >= a->size, 0))
611 {
612 if (a->size == 0 || !_dt_masks_dynbuf_growto(a, 2 * (a->size+1)))
613 return;
614 }
615 a->buffer[a->pos++] = value1;
616 a->buffer[a->pos++] = value2;
617}
618
619// Return a pointer to N floats past the current end of the dynbuf's contents, marking them as already in use.
620// The caller should then fill in the reserved elements using the returned pointer.
621static inline float *dt_masks_dynbuf_reserve_n(dt_masks_dynbuf_t *a, const int n)
622{
623 assert(!IS_NULL_PTR(a));
624 assert(a->pos <= a->size);
625 if(__builtin_expect(a->pos + n >= a->size, 0))
626 {
627 if(a->size == 0) return NULL;
628 size_t newsize = a->size;
629 while(a->pos + n >= newsize) newsize *= 2;
630 if (!_dt_masks_dynbuf_growto(a, newsize))
631 {
632 return NULL;
633 }
634 }
635 // get the current end of the (possibly reallocated) buffer, then mark the next N items as in-use
636 float *reserved = a->buffer + a->pos;
637 a->pos += n;
638 return reserved;
639}
640
641static inline void dt_masks_dynbuf_add_zeros(dt_masks_dynbuf_t *a, const int n)
642{
643 assert(!IS_NULL_PTR(a));
644 assert(a->pos <= a->size);
645 if(__builtin_expect(a->pos + n >= a->size, 0))
646 {
647 if(a->size == 0) return;
648 size_t newsize = a->size;
649 while(a->pos + n >= newsize) newsize *= 2;
650 if (!_dt_masks_dynbuf_growto(a, newsize))
651 {
652 return;
653 }
654 }
655 // now that we've ensured a sufficiently large buffer add N zeros to the end of the existing data
656 memset(a->buffer + a->pos, 0, n * sizeof(float));
657 a->pos += n;
658}
659
660
661static inline float dt_masks_dynbuf_get(dt_masks_dynbuf_t *a, int offset)
662{
663 assert(!IS_NULL_PTR(a));
664 // offset: must be negative distance relative to end of buffer
665 assert(offset < 0);
666 assert((long)a->pos + offset >= 0);
667 return (a->buffer[a->pos + offset]);
668}
669
670static inline void dt_masks_dynbuf_set(dt_masks_dynbuf_t *a, int offset, float value)
671{
672 assert(!IS_NULL_PTR(a));
673 // offset: must be negative distance relative to end of buffer
674 assert(offset < 0);
675 assert((long)a->pos + offset >= 0);
676 a->buffer[a->pos + offset] = value;
677}
678
680{
681 assert(!IS_NULL_PTR(a));
682 return a->buffer;
683}
684
685static inline gboolean dt_masks_center_of_gravity_from_points(const float *points, const int points_count,
686 float center[2], float *area)
687{
688 if(IS_NULL_PTR(points) || IS_NULL_PTR(center) || IS_NULL_PTR(area) || points_count <= 0)
689 {
690 if(center)
691 {
692 center[0] = 0.0f;
693 center[1] = 0.0f;
694 }
695 if(!IS_NULL_PTR(area)) *area = 0.0f;
696 return FALSE;
697 }
698
699 double start = 0.;
701
702 // Points must be ordered sequentially along the polygon boundary.
703 // Use the shoelace formula to compute area and centroid.
704 if(points_count >= 3)
705 {
706 double area2 = 0.0;
707 double cx = 0.0;
708 double cy = 0.0;
709
710 for(int i = 0; i < points_count; i++)
711 {
712 const int j = (i + 1 < points_count) ? (i + 1) : 0;
713 const double x0 = points[i * 2];
714 const double y0 = points[i * 2 + 1];
715 const double x1 = points[j * 2];
716 const double y1 = points[j * 2 + 1];
717
718 const double cross = x0 * y1 - x1 * y0;
719 area2 += cross;
720 cx += (x0 + x1) * cross;
721 cy += (y0 + y1) * cross;
722 }
723
724 if(fabs(area2) > 1e-12)
725 {
726 const double inv = 1.0 / (3.0 * area2);
727 center[0] = (float)(cx * inv);
728 center[1] = (float)(cy * inv);
729
730 *area = (float)(0.5 * fabs(area2));
731 return TRUE;
732 }
733 }
734
735 // Fallback to arithmetic mean for degenerate polygons or short lists.
736 float sum_x = 0.0f;
737 float sum_y = 0.0f;
738 const float inv_count = 1.0f / (float)points_count;
739 for(int i = 0; i < points_count; i++)
740 {
741 sum_x += points[i * 2] * inv_count;
742 sum_y += points[i * 2 + 1] * inv_count;
743 }
744
746 dt_print(DT_DEBUG_MASKS, "[masks] computing centroid took %0.04f sec\n",
747 dt_get_wtime() - start);
748
749
750 center[0] = sum_x;
751 center[1] = sum_y;
752 *area = 0.0f;
753 return TRUE;
754}
755
757{
758 assert(!IS_NULL_PTR(a));
759 return a->pos;
760}
761
763{
764 assert(!IS_NULL_PTR(a));
765 a->pos = 0;
766}
767
769{
770 // take out data buffer and make dynamic buffer obsolete
771 if(IS_NULL_PTR(a)) return NULL;
772 float *r = a->buffer;
773 a->buffer = NULL;
774 a->pos = a->size = 0;
775 return r;
776}
777
779{
780 if(IS_NULL_PTR(a)) return;
781 dt_print(DT_DEBUG_MASKS, "[masks dynbuf '%s'] freed (was %p)\n", a->tag,
782 a->buffer);
784 dt_free(a);
785}
786
787static inline int dt_masks_roundup(int num, int mult)
788{
789 const int rem = num % mult;
790
791 return (rem == 0) ? num : num + mult - rem;
792}
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
822#ifdef __cplusplus
823}
824#endif
825
826#endif // DT_DEVELOP_MASKS_H
827
828// clang-format off
829// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
830// vim: shiftwidth=2 expandtab tabstop=2 cindent
831// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
832// clang-format on
static double * inv
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
atomic_int dt_atomic_int
Definition atomic.h:68
static const dt_dev_pixelpipe_t * pipe
Definition layers.h:49
static const dt_dev_pixelpipe_t const dt_dev_pixelpipe_iop_t * piece
Definition layers.h:50
hash
Definition layers.h:90
static const dt_iop_drawlayer_params_t * params
Definition layers.h:80
_lib_location_type_t type
Definition location.c:1
@ DT_DEBUG_PERF
Definition logging.h:55
@ DT_DEBUG_MASKS
Definition logging.h:62
int32_t dt_get_debug_flags(void)
Definition darktable.c:2094
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
#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
int dt_masks_legacy_params(dt_develop_t *dev, void *params, const int old_version, const int new_version)
Definition masks.c:821
static float * dt_masks_dynbuf_buffer(dt_masks_dynbuf_t *a)
Definition masks.h:679
uint64_t dt_masks_group_get_hash_ext(uint64_t hash, GList *masks, dt_masks_form_t *form)
Definition masks.c:1422
static void dt_masks_dynbuf_add_2(dt_masks_dynbuf_t *a, float value1, float value2)
Definition masks.h:606
dt_masks_raster_result_t dt_masks_get_mask(const dt_iop_module_t *const module, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *const piece, dt_masks_form_t *const form, float **buffer, dt_masks_area_t *area)
Definition masks.c:1647
dt_masks_form_t * dt_masks_get_from_id_in_pipe(const dt_dev_pixelpipe_t *pipe, int id)
Definition masks.c:933
static dt_masks_raster_result_t dt_masks_raster_from_status(const int status)
Definition masks.h:322
struct dt_iop_module_t * dt_masks_get_mask_manager(struct dt_develop_t *dev)
Definition masks.c:938
void dt_masks_free_form(dt_masks_form_t *form)
Definition masks.c:1161
static dt_masks_dynbuf_t * dt_masks_dynbuf_init(size_t size, const char *tag)
Definition masks.h:586
static void dt_masks_translate_source(dt_masks_form_t *form, const float delta_x, const float delta_y)
Definition masks.h:387
void dt_masks_iop_use_same_as(struct dt_iop_module_t *module, struct dt_iop_module_t *src)
Definition masks.c:1178
dt_masks_raster_result_t
What a rasterisation attempt produced.
Definition masks.h:313
@ DT_MASKS_RASTER_ERROR
Definition masks.h:316
@ DT_MASKS_RASTER_EMPTY
Definition masks.h:315
@ DT_MASKS_RASTER_OK
Definition masks.h:314
void dt_masks_read_masks_history(dt_develop_t *dev, const int32_t imgid)
Definition masks.c:1118
uint64_t dt_masks_form_get_own_hash(uint64_t hash, GList *masks, const dt_masks_form_t *form)
Definition masks.c:1460
static float dt_masks_dynbuf_get(dt_masks_dynbuf_t *a, int offset)
Definition masks.h:661
static void dt_masks_translate_ctrl_node(float node[2], float ctrl1[2], float ctrl2[2], const float delta_x, const float delta_y)
Definition masks.h:393
dt_masks_form_t * dt_masks_dup_masks_form(const dt_masks_form_t *form)
Deep-copy a mask form, including its points list.
Definition masks.c:77
void dt_masks_duplicate_points(const dt_masks_form_t *base, dt_masks_form_t *dest, size_t node_size)
Duplicate a points list for a mask using a fixed node size.
Definition masks.c:1353
void dt_masks_write_masks_history_item(const int32_t imgid, const int num, dt_masks_form_t *form)
Definition masks.c:1131
static float * dt_masks_dynbuf_reserve_n(dt_masks_dynbuf_t *a, const int n)
Definition masks.h:621
dt_masks_raster_result_t dt_masks_get_area(const dt_iop_module_t *iop_module, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, dt_masks_area_t *area)
Definition masks.c:464
static gboolean _dt_masks_dynbuf_growto(dt_masks_dynbuf_t *a, size_t size)
Definition masks.h:564
int dt_masks_version(void)
Definition masks.c:502
int dt_masks_form_duplicate_in_group(dt_develop_t *dev, int group_id, int form_id)
Duplicate a shape (dt_masks_form_duplicate) and, if group_id names a valid group, attach the duplicat...
Definition masks.c:210
static gboolean dt_masks_center_of_gravity_from_points(const float *points, const int points_count, float center[2], float *area)
Definition masks.h:685
dt_masks_ellipse_flags_t
Definition masks.h:181
@ DT_MASKS_ELLIPSE_PROPORTIONAL
Definition masks.h:183
@ DT_MASKS_ELLIPSE_EQUIDISTANT
Definition masks.h:182
static size_t dt_masks_dynbuf_position(dt_masks_dynbuf_t *a)
Definition masks.h:756
dt_masks_form_t * dt_masks_create_ext(dt_develop_t *dev, dt_masks_type_t type)
Definition masks.c:901
dt_masks_source_pos_type_t
Definition masks.h:187
@ DT_MASKS_SOURCE_POS_RELATIVE_TEMP
Definition masks.h:189
@ DT_MASKS_SOURCE_POS_RELATIVE
Definition masks.h:188
@ DT_MASKS_SOURCE_POS_ABSOLUTE
Definition masks.h:190
void dt_masks_cleanup_unused(dt_develop_t *dev)
Cleanup unused masks and refresh the current forms snapshot.
Definition masks.c:1608
dt_masks_event_t
Definition masks.h:143
@ DT_MASKS_EVENT_NONE
Definition masks.h:144
@ DT_MASKS_EVENT_UPDATE
Definition masks.h:147
@ DT_MASKS_EVENT_RESET
Definition masks.h:150
@ DT_MASKS_EVENT_ADD
Definition masks.h:145
@ DT_MASKS_EVENT_DELETE
Definition masks.h:148
@ DT_MASKS_EVENT_REMOVE
Definition masks.h:146
@ DT_MASKS_EVENT_CHANGE
Definition masks.h:149
dt_masks_form_t * dt_masks_create(dt_masks_type_t type)
Definition masks.c:867
void dt_masks_area_scale(dt_masks_area_t *area, const double scale)
Definition masks.c:450
int dt_masks_form_change_opacity(dt_develop_t *dev, dt_masks_form_t *form, int parentid, int up, const int flow)
Definition masks_gui.c:5840
gboolean dt_masks_area_intersects(const dt_masks_area_t *area, const dt_iop_roi_t *roi)
Definition masks.c:458
static gboolean dt_masks_form_is_clone(const dt_masks_form_t *form)
Definition masks.h:376
static void dt_masks_dynbuf_add_zeros(dt_masks_dynbuf_t *a, const int n)
Definition masks.h:641
void dt_masks_form_move(dt_masks_form_t *grp, int formid, int up)
Definition masks.c:1370
dt_masks_pressure_sensitivity_t
Definition masks.h:171
@ DT_MASKS_PRESSURE_OPACITY_REL
Definition masks.h:175
@ DT_MASKS_PRESSURE_OPACITY_ABS
Definition masks.h:176
@ DT_MASKS_PRESSURE_BRUSHSIZE_REL
Definition masks.h:177
@ DT_MASKS_PRESSURE_FADING_REL
Definition masks.h:173
@ DT_MASKS_PRESSURE_OFF
Definition masks.h:172
@ DT_MASKS_PRESSURE_FADING_ABS
Definition masks.h:174
dt_masks_form_t * dt_masks_get_from_id_ext(GList *forms, int id)
Definition masks.c:915
void dt_masks_form_delete(dt_develop_t *dev, struct dt_iop_module_t *module, dt_masks_form_t *grp, dt_masks_form_t *form)
Definition masks.c:1217
dt_masks_form_t * dt_masks_get_from_id(dt_develop_t *dev, int id)
Definition masks.c:925
dt_masks_points_states_t
Definition masks.h:155
@ DT_MASKS_POINT_STATE_NORMAL
Definition masks.h:156
@ DT_MASKS_POINT_STATE_USER
Definition masks.h:157
dt_masks_edit_mode_t dt_masks_get_edit_mode(struct dt_iop_module_t *module)
Definition masks.c:1169
dt_masks_gradient_states_t
Definition masks.h:161
@ DT_MASKS_GRADIENT_STATE_SIGMOIDAL
Definition masks.h:163
@ DT_MASKS_GRADIENT_STATE_LINEAR
Definition masks.h:162
static int dt_masks_roundup(int num, int mult)
Definition masks.h:787
static float * dt_masks_dynbuf_harvest(dt_masks_dynbuf_t *a)
Definition masks.h:768
dt_masks_raster_result_t dt_masks_get_source_area(const dt_iop_module_t *iop_module, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, dt_masks_area_t *area)
Definition masks.c:486
void dt_masks_set_edit_mode(struct dt_iop_module_t *module, dt_masks_edit_mode_t value)
Definition masks_gui.c:5809
static void dt_masks_dynbuf_set(dt_masks_dynbuf_t *a, int offset, float value)
Definition masks.h:670
int dt_masks_form_duplicate(dt_develop_t *dev, int formid)
Definition masks.c:186
static gboolean dt_masks_form_uses_spot_defaults(const dt_masks_form_t *form)
Definition masks.h:371
static void dt_masks_dynbuf_reset(dt_masks_dynbuf_t *a)
Definition masks.h:762
gboolean dt_masks_form_is_in_roi(const dt_iop_module_t *iop_module, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out)
Definition masks.c:475
static void dt_masks_dynbuf_free(dt_masks_dynbuf_t *a)
Definition masks.h:778
static void dt_masks_reset_source(dt_masks_form_t *form)
Definition masks.h:381
static void dt_masks_set_ctrl_points(float ctrl1[2], float ctrl2[2], const float control_points[4])
Definition masks.h:404
dt_masks_raster_result_t dt_masks_group_render_roi(dt_iop_module_t *module, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, const dt_iop_roi_t *roi, float *buffer)
Definition group.c:963
int dt_masks_copy_used_forms_for_module(dt_develop_t *dev_dest, dt_develop_t *dev_src, const struct dt_iop_module_t *mod_src)
The masks vocabulary: the enumerations a caller needs to NAME a shape or an operation,...
dt_masks_edit_mode_t
dt_masks_type_t
Definition masks_types.h:62
@ DT_MASKS_NON_CLONE
Definition masks_types.h:71
@ DT_MASKS_CLONE
Definition masks_types.h:67
static size_t dt_round_size_sse(const size_t size)
Round size up to the next multiple of 64.
Definition mem_alloc.h:111
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
Definition mem_alloc.h:171
dt_imageio_retval_t status
Definition mipmap_cache.c:8
size_t size
Definition mipmap_cache.c:3
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
static const dt_aligned_pixel_simd_t value
Definition simd.h:144
const float r
unsigned __int64 uint64_t
Definition strptime.c:75
GHashTable * masks
Definition imageop.h:362
struct dt_develop_t * dev
Definition imageop.h:311
Region of interest passed through the pixelpipe.
Definition format.h:49
dt_masks_gradient_states_t state
Definition masks.h:241
char tag[128]
Definition masks.h:363
float * buffer
Definition masks.h:362
const dt_masks_functions_t * functions
Definition masks.h:255
dt_masks_type_t type
Definition masks.h:254
dt_atomic_int refcount
Definition masks.h:285
gboolean gravity_center_valid
Definition masks.h:270
float source[2]
Definition masks.h:261
char name[128]
Definition masks.h:277
GList * points
Definition masks.h:253
float gravity_center[2]
Definition masks.h:265
gboolean uses_bezier_points_layout
Definition masks.h:257
dt_masks_points_states_t state
Definition masks.h:230
dt_masks_ellipse_flags_t flags
Definition masks.h:208
dt_masks_points_states_t state
Definition masks.h:218
static double dt_get_wtime(void)
Definition times.h:43