Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
masks_history.c
Go to the documentation of this file.
1/*
2 This file is part of Ansel
3 Copyright (C) 2026 Guillaume Stutin.
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 darktable. If not, see <http://www.gnu.org/licenses/>.
17*/
18
20
21#include "common/atomic.h"
22#include "develop/develop.h"
23
25{
26 if(IS_NULL_PTR(form)) return NULL;
27 dt_atomic_add_int(&form->refcount, 1);
28 return form;
29}
30
32{
33 if(IS_NULL_PTR(form)) return;
34 // dt_atomic_sub_int returns the value *before* the decrement.
35 if(dt_atomic_sub_int(&form->refcount, 1) == 1) dt_masks_free_form(form);
36}
37
39{
40 if(IS_NULL_PTR(dev) || IS_NULL_PTR(form)) return form;
41 if(dt_atomic_get_int(&form->refcount) <= 1) return form;
42
44
45 GList *node = g_list_find(dev->forms, form);
46 if(IS_NULL_PTR(node))
47 {
48 // Not (yet) a member of dev->forms: e.g. a transient in-creation shape.
49 // Nothing to splice, leave it alone.
51 return form;
52 }
53
55 node->data = clone;
56
58
59 if(!IS_NULL_PTR(dev->form_gui) && dev->form_gui->form_visible == form)
60 dev->form_gui->form_visible = clone;
61
63
64 return clone;
65}
66
68{
70
71 GList *forms_shared = g_list_copy(forms);
72 for(GList *node = forms_shared; node; node = g_list_next(node))
74
75 GList *old_forms = dev->forms;
76 dev->forms = forms_shared;
77
79
80 // form_visible is a raw pointer cached outside dev->forms (dt_masks_form_gui_t::form_visible).
81 // If it pointed at an object we're about to release below, re-resolve it by formid in the new
82 // dev->forms (or drop it if that formid is gone) before old_forms is freed -- otherwise the
83 // very next mask interaction (mouse move, scroll...) dereferences freed memory.
85 && g_list_find(old_forms, dev->form_gui->form_visible))
86 {
87 const int visible_formid = dev->form_gui->form_visible->formid;
88 dev->form_gui->form_visible = dt_masks_get_from_id_ext(dev->forms, visible_formid);
89 }
90
91 g_list_free_full(old_forms, (void (*)(void *))dt_masks_form_unref);
92
93 // Don't recompute gravity_center/area for every form here: this runs on every history
94 // load, undo/redo and history navigation, for every mask of every module in the image,
95 // whether or not the mask editor is even open. Just invalidate -- the one GUI hit-testing
96 // read site (masks.c, group member selection) recomputes lazily on first actual use.
97 for(GList *form_node = dev->forms; form_node; form_node = g_list_next(form_node))
99}
100
101GList *dt_masks_snapshot_current_forms(dt_develop_t *dev, gboolean reset_changed)
102{
104
105 GList *forms_snapshot = g_list_copy(dev->forms);
106 for(GList *node = forms_snapshot; node; node = g_list_next(node))
107 dt_masks_form_ref((dt_masks_form_t *)node->data);
108
110
111 if(reset_changed) dev->forms_changed = FALSE;
112 return forms_snapshot;
113}
#define FALSE
Definition ashift_lsd.c:158
int dt_atomic_get_int(dt_atomic_int *var)
int dt_atomic_sub_int(dt_atomic_int *var, int decr)
int dt_atomic_add_int(dt_atomic_int *var, int incr)
#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 darktable.h:293
static int dt_pthread_rwlock_unlock(dt_pthread_rwlock_t *rwlock)
Definition dtpthread.h:452
static int dt_pthread_rwlock_rdlock(dt_pthread_rwlock_t *rwlock)
Definition dtpthread.h:502
static int dt_pthread_rwlock_wrlock(dt_pthread_rwlock_t *rwlock)
Definition dtpthread.h:534
void dt_masks_free_form(dt_masks_form_t *form)
dt_masks_form_t * dt_masks_dup_masks_form(const dt_masks_form_t *form)
Deep-copy a mask form, including its points list.
void dt_masks_form_invalidate_gravity_center(struct dt_masks_form_t *form)
dt_masks_form_t * dt_masks_get_from_id_ext(GList *forms, int id)
GList * dt_masks_snapshot_current_forms(dt_develop_t *dev, gboolean reset_changed)
void dt_masks_replace_current_forms(dt_develop_t *dev, GList *forms)
dt_masks_form_t * dt_masks_form_ref(dt_masks_form_t *form)
void dt_masks_form_unref(dt_masks_form_t *form)
dt_masks_form_t * dt_masks_cow_touch(dt_develop_t *dev, dt_masks_form_t *form)
gboolean forms_changed
Definition develop.h:332
struct dt_masks_form_gui_t * form_gui
Definition develop.h:333
dt_pthread_rwlock_t masks_mutex
Definition develop.h:339
GList * forms
Definition develop.h:327
dt_masks_form_t * form_visible
Definition masks.h:444
dt_atomic_int refcount
Definition masks.h:411