Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
coordinates.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
20
21static gboolean _virtual_piece_layer_geometry(dt_iop_module_t *self, int *layer_width, int *layer_height)
22{
23 if(!IS_NULL_PTR(layer_width)) *layer_width = 0;
24 if(!IS_NULL_PTR(layer_height)) *layer_height = 0;
25 if(IS_NULL_PTR(self) || IS_NULL_PTR(self->dev)) return FALSE;
26
27 /* GUI coordinate mapping should prefer the virtual pipe geometry because it
28 * tracks the currently committed distortion stack even before the global
29 * darkroom ROI bookkeeping is fully refreshed. Falling back to `dev->roi`
30 * too early makes the first displayed layer appear stretched until the next
31 * display-pipe refresh catches up. */
32 int resolved_width = 0;
33 int resolved_height = 0;
34 if(self->dev->virtual_pipe && self->dev->virtual_pipe->processed_width > 0
35 && self->dev->virtual_pipe->processed_height > 0)
36 {
37 resolved_width = self->dev->virtual_pipe->processed_width;
38 resolved_height = self->dev->virtual_pipe->processed_height;
39 }
40 else
41 {
42 resolved_width = self->dev->roi.processed_width;
43 resolved_height = self->dev->roi.processed_height;
44 }
45 if(!IS_NULL_PTR(layer_width)) *layer_width = resolved_width;
46 if(!IS_NULL_PTR(layer_height)) *layer_height = resolved_height;
47 return resolved_width > 0 && resolved_height > 0;
48}
49
50gboolean dt_drawlayer_widget_points_to_layer_coords(dt_iop_module_t *self, float *pts, const int count)
51{
52 if(IS_NULL_PTR(self) || IS_NULL_PTR(self->dev) || IS_NULL_PTR(self->dev->virtual_pipe) || IS_NULL_PTR(pts) || count <= 0) return FALSE;
53
56
59 return FALSE;
62
63 return TRUE;
64}
65
80
81gboolean dt_drawlayer_widget_to_layer_coords(dt_iop_module_t *self, const double wx, const double wy,
82 float *lx, float *ly)
83{
84 if(IS_NULL_PTR(lx) || IS_NULL_PTR(ly)) return FALSE;
85
86 float pt[2] = { (float)wx, (float)wy };
88
89 *lx = pt[0];
90 *ly = pt[1];
91 return TRUE;
92}
93
94gboolean dt_drawlayer_layer_to_widget_coords(dt_iop_module_t *self, const float x, const float y,
95 float *wx, float *wy)
96{
97 if(IS_NULL_PTR(wx) || IS_NULL_PTR(wy)) return FALSE;
98
99 float pt[2] = { x, y };
100 if(!dt_drawlayer_layer_points_to_widget_coords(self, pt, 1)) return FALSE;
101 *wx = pt[0];
102 *wy = pt[1];
103 return TRUE;
104}
105
106gboolean dt_drawlayer_layer_bounds_to_widget_bounds(dt_iop_module_t *self, const float x0, const float y0,
107 const float x1, const float y1,
108 float *left, float *top,
109 float *right, float *bottom)
110{
111 float pts[8] = {
112 x0, y0, x1, y0, x0, y1, x1, y1,
113 };
114
115 if(!dt_drawlayer_layer_points_to_widget_coords(self, pts, 4)) return FALSE;
116
117 float min_x = pts[0];
118 float max_x = pts[0];
119 float min_y = pts[1];
120 float max_y = pts[1];
121 for(int i = 1; i < 4; i++)
122 {
123 min_x = fminf(min_x, pts[2 * i]);
124 max_x = fmaxf(max_x, pts[2 * i]);
125 min_y = fminf(min_y, pts[2 * i + 1]);
126 max_y = fmaxf(max_y, pts[2 * i + 1]);
127 }
128
129 if(!IS_NULL_PTR(left)) *left = min_x;
130 if(!IS_NULL_PTR(top)) *top = min_y;
131 if(!IS_NULL_PTR(right)) *right = max_x;
132 if(!IS_NULL_PTR(bottom)) *bottom = max_y;
133 return TRUE;
134}
135
137 const float fallback)
138{
139 if(IS_NULL_PTR(self) || IS_NULL_PTR(self->dev) || IS_NULL_PTR(self->dev->virtual_pipe) || IS_NULL_PTR(dab)) return fallback;
140
141 float pts[6] = {
142 dab->x, dab->y, dab->x + dab->radius, dab->y, dab->x, dab->y + dab->radius,
143 };
144
145 if(!dt_drawlayer_layer_points_to_widget_coords(self, pts, 3)) return fallback;
146
147 const float rx = hypotf(pts[2] - pts[0], pts[3] - pts[1]);
148 const float ry = hypotf(pts[4] - pts[0], pts[5] - pts[1]);
149 const float radius = 0.5f * (rx + ry);
150 return fmaxf(0.5f, isfinite(radius) ? radius : fallback);
151}
152
154{
156 .radius = fmaxf(_conf_size(), 0.5f),
157 .hardness = _conf_hardness(),
158 .shape = _conf_brush_shape(),
159 };
160 return ceilf(dab.radius + 1.0f);
161}
162
164{
165 if(IS_NULL_PTR(self) || IS_NULL_PTR(self->dev) || IS_NULL_PTR(view)) return FALSE;
166
167 int layer_width = 0;
168 int layer_height = 0;
169 if(!_virtual_piece_layer_geometry(self, &layer_width, &layer_height)) return FALSE;
170
171 const float widget_w = (float)self->dev->roi.orig_width;
172 const float widget_h = (float)self->dev->roi.orig_height;
173 const float preview_w = self->dev->roi.preview_width;
174 const float preview_h = self->dev->roi.preview_height;
175 if(widget_w <= 0.0f || widget_h <= 0.0f || preview_w <= 0.0f || preview_h <= 0.0f) return FALSE;
176
177 const float zoom_scale = dt_dev_get_overlay_scale(self->dev);
178 const float border = (float)self->dev->roi.border_size;
179 const float roi_w = fminf(widget_w, preview_w * zoom_scale);
180 const float roi_h = fminf(widget_h, preview_h * zoom_scale);
181 const float rec_x = fmaxf(border, 0.5f * (widget_w - roi_w));
182 const float rec_y = fmaxf(border, 0.5f * (widget_h - roi_h));
183 const float rec_w = fminf(widget_w - 2.0f * border, roi_w);
184 const float rec_h = fminf(widget_h - 2.0f * border, roi_h);
185 if(rec_w <= 0.0f || rec_h <= 0.0f) return FALSE;
186
187 float pts[8] = {
188 rec_x, rec_y, rec_x + rec_w, rec_y, rec_x, rec_y + rec_h, rec_x + rec_w, rec_y + rec_h,
189 };
190 if(!dt_drawlayer_widget_points_to_layer_coords(self, pts, 4)) return FALSE;
191
192 float min_x = pts[0];
193 float max_x = pts[0];
194 float min_y = pts[1];
195 float max_y = pts[1];
196 for(int i = 1; i < 4; i++)
197 {
198 min_x = fminf(min_x, pts[2 * i]);
199 max_x = fmaxf(max_x, pts[2 * i]);
200 min_y = fminf(min_y, pts[2 * i + 1]);
201 max_y = fmaxf(max_y, pts[2 * i + 1]);
202 }
203
204 view->layer_x0 = min_x;
205 view->layer_y0 = min_y;
206 view->layer_x1 = max_x;
207 view->layer_y1 = max_y;
208
209 view->patch.x = MAX(0, (int)floorf(min_x - padding));
210 view->patch.y = MAX(0, (int)floorf(min_y - padding));
211 const int right = MIN(layer_width, (int)ceilf(max_x + padding));
212 const int bottom = MIN(layer_height, (int)ceilf(max_y + padding));
213 view->patch.width = MAX(0, right - view->patch.x);
214 view->patch.height = MAX(0, bottom - view->patch.y);
215 return view->patch.width > 0 && view->patch.height > 0;
216}
#define TRUE
Definition ashift_lsd.c:162
#define FALSE
Definition ashift_lsd.c:158
const float i
Definition colorspaces_inline_conversions.h:440
const float top
Definition colorspaces_inline_conversions.h:443
gboolean dt_drawlayer_compute_view_patch(dt_iop_module_t *self, const float padding, drawlayer_view_patch_info_t *view)
Definition coordinates.c:163
gboolean dt_drawlayer_widget_points_to_layer_coords(dt_iop_module_t *self, float *pts, const int count)
Definition coordinates.c:50
static gboolean _virtual_piece_layer_geometry(dt_iop_module_t *self, int *layer_width, int *layer_height)
Definition coordinates.c:21
float dt_drawlayer_widget_brush_radius(dt_iop_module_t *self, const dt_drawlayer_brush_dab_t *dab, const float fallback)
Definition coordinates.c:136
gboolean dt_drawlayer_layer_points_to_widget_coords(dt_iop_module_t *self, float *pts, const int count)
Definition coordinates.c:66
gboolean dt_drawlayer_layer_bounds_to_widget_bounds(dt_iop_module_t *self, const float x0, const float y0, const float x1, const float y1, float *left, float *top, float *right, float *bottom)
Definition coordinates.c:106
float dt_drawlayer_current_live_padding(dt_iop_module_t *self)
Definition coordinates.c:153
gboolean dt_drawlayer_widget_to_layer_coords(dt_iop_module_t *self, const double wx, const double wy, float *lx, float *ly)
Definition coordinates.c:81
gboolean dt_drawlayer_layer_to_widget_coords(dt_iop_module_t *self, const float x, const float y, float *wx, float *wy)
Definition coordinates.c:94
Shared coordinate transforms and geometry computations for drawlayer.
uint32_t view(const dt_view_t *self)
Definition darkroom.c:191
darktable_t darktable
Definition darktable.c:173
#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:281
void dt_dev_coordinates_image_abs_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
Definition develop.c:952
void dt_dev_coordinates_preview_abs_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
Definition develop.c:1022
int dt_dev_distort_transform_plus(const dt_dev_pixelpipe_t *pipe, const double iop_order, const int transf_direction, float *points, size_t points_count)
Definition develop.c:1419
float dt_dev_get_overlay_scale(dt_develop_t *dev)
Get the overlay scale factor in GUI logical coordinates.
Definition develop.c:1574
void dt_dev_coordinates_image_norm_to_preview_abs(dt_develop_t *dev, float *points, size_t num_points)
Definition develop.c:1007
void dt_dev_coordinates_image_norm_to_widget(dt_develop_t *dev, float *points, size_t num_points)
Definition develop.c:908
void dt_dev_coordinates_image_norm_to_image_abs(dt_develop_t *dev, float *points, size_t num_points)
Definition develop.c:937
void dt_dev_coordinates_widget_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
Coordinate conversion helpers between widget, normalized image, and absolute image spaces.
Definition develop.c:880
int dt_dev_distort_backtransform_plus(const dt_dev_pixelpipe_t *pipe, const double iop_order, const int transf_direction, float *points, size_t points_count)
Definition develop.c:1448
@ DT_DEV_TRANSFORM_DIR_FORW_EXCL
Definition develop.h:104
static float _conf_hardness(void)
Derive hardness as complementary value of softness.
Definition iop/drawlayer/conf.c:191
static float _conf_size(void)
Read and clamp configured brush size (px).
Definition iop/drawlayer/conf.c:137
static dt_iop_drawlayer_brush_shape_t _conf_brush_shape(void)
Read and clamp configured brush shape.
Definition iop/drawlayer/conf.c:123
static const float x
Definition iop_profile.h:235
struct dt_develop_t * develop
Definition darktable.h:769
Definition coordinates.h:19
int processed_width
Definition pixelpipe_hb.h:235
int processed_height
Definition pixelpipe_hb.h:235
int32_t orig_height
Definition develop.h:194
int32_t border_size
Definition develop.h:189
int32_t preview_height
Definition develop.h:202
int32_t processed_width
Definition develop.h:222
int32_t orig_width
Definition develop.h:194
struct dt_dev_pixelpipe_t * virtual_pipe
Definition develop.h:240
int32_t processed_height
Definition develop.h:222
int32_t preview_width
Definition develop.h:202
struct dt_develop_t::@18 roi
Fully resolved input dab descriptor.
Definition brush.h:64
float x
Definition brush.h:65
float radius
Definition brush.h:69
float y
Definition brush.h:66
Definition imageop.h:246
struct dt_develop_t * dev
Definition imageop.h:298
int iop_order
Definition imageop.h:260
#define MIN(a, b)
Definition thinplate.c:32
#define MAX(a, b)
Definition thinplate.c:29