56#include <glib/gstdio.h>
58#define DT_MASKS_SHAPE_BUTTON_COUNT 5
184 for(
size_t i = 0;
i < count;
i++)
205 paint(cr, pad, pad,
alloc.width - 2 * pad,
alloc.height - 2 * pad, 0,
NULL);
327 if(!(config->
flags & def->
flag))
continue;
444 double x = 0.0, y = 0.0;
520 const int group_id,
const int formid,
522 float min,
float max,
float step,
float value,
int digits,
523 const char *format,
float factor,
554 data->module =
module;
588 _(
"will no longer be used."),
589 _(
"Do you want to permanently delete it, or keep it unused for potential reuse?"));
611 _(
"Permanently delete the shape '%s' ?"), form_name);
614 _(
"It will be removed from every mask using it and from the list of available shapes."));
619 _(
"when unchecked, mask shapes will be deleted silently from now on without this confirmation.\n"
620 "you can turn it back on from preferences."));
650 *parentid =
fpt->parentid;
661 int parentid = 0, formid = 0;
673 int parentid = 0, formid = 0;
768 dt_control_log(
_(
"Applying a boolean operation has no effect on the first shape of a group.\n"
769 "Move it to at least the 2nd position if you need to use boolean operations"));
780#define masks_gtk_menu_item_new_bold(label, selected, state, icon) \
782 gchar *op_label = g_strdup(label); \
783 menu_item = ctx_gtk_check_menu_item_new_with_markup_and_pixbuf(op_label, icon, \
785 _masks_operation_callback, gui, \
787 ((state) == DT_MASKS_STATE_INVERSE)); \
790 g_object_set_data(G_OBJECT(menu_item), "state_op", GINT_TO_POINTER(state)); \
791 g_object_set_data(G_OBJECT(menu_item), "op_form", op_form); \
792 g_object_set_data(G_OBJECT(menu_item), "form_pos", GINT_TO_POINTER(form_pos)); \
818 if(!
isfinite(rotation)) rotation = 0.0f;
819 if(rotation > 180.0f) rotation -= 360.0f;
823 isfinite(curvature) ? curvature : 0.0f, 3,
"%", 50.0f,
831 rotation, 1,
"\302\260", 1.0f,
843 isfinite(fading) ? fading : 1.0f, 3,
"%", 100.0f,
849 if(!
isfinite(rotation)) rotation = 0.0f;
850 if(rotation > 180.0f) rotation -= 360.0f;
854 rotation, 1,
"\302\260", 1.0f,
861 isfinite(opacity) ? opacity : 1.0f, 3,
"%", 100.0f,
866 const float pzx,
const float pzy)
919 gchar *form_name =
NULL;
948 form_name =
g_strdup(
_(
"Unknown shape"));
1100 const int node_index,
1101 float node[2],
float ctrl1[2],
float ctrl2[2],
1114 ctrl1[0] = ctrl2[0] = node[0];
1115 ctrl1[1] = ctrl2[1] = node[1];
1128 const int node_index,
1158 const float center_x,
const float center_y,
1216 mask_gui->handle_border_hovered = -1;
1228 if(
mask_gui->handle_border_dragging >= 0)
1252 float handle_x =
NAN;
1253 float handle_y =
NAN;
1295 for(
int node_index =
first_node_index; node_index < node_count; node_index++)
1311 mask_gui->node_hovered = node_index;
1700 return mask_gui->group_selected >= 0;
1765 if(button != 1)
return FALSE;
1798 char message[512] =
"";
1817 "[masks] hint begin: form=%p type=%d gui=%p group_selected=%d form_selected=%d node_hovered=%d seg_hovered=%d selected_formid=%d\n",
1840 "[masks] hint end: sel=%p has_set_hint=%d msg_len=%" G_GSIZE_FORMAT " msg='%s'\n",
1843 strlen(message), message);
1844 return message[0] !=
'\0';
1861 mask_gui->handle_border_hovered = -1;
1884 mask_gui->handle_border_hovered = -1;
1905 mask_gui->outline_step = (span > 1.0) ? (
int)span : 1;
1952 "[masks] outline build FAILED for %s (index %d, %d nodes): the cache key stays unset,"
1953 " so every later expose rebuilds this whole group\n",
2064 const int edit_mode =
mask_gui->edit_mode;
2110 if(count > 1)
goto done;
2172 const int edit_mode =
mask_gui->edit_mode;
2223 && ((
module->flags() & IOP_FLAGS_INTERNAL_MASKS) == IOP_FLAGS_INTERNAL_MASKS);
2302 mask_gui->creation_last_formid = 0;
2410 for(
int i = 0;
i < count;
i++)
2412 const float x = samples[2 *
i];
2413 const float y = samples[2 *
i + 1];
2467 const char *
verdict =
"reuse";
2468 if(
mask_gui->geometry_generation == 0)
verdict =
"REBUILD (nothing cached)";
2469 else if(
stale)
verdict =
"REBUILD (geometry or density moved)";
2470 dt_print(
DT_DEBUG_MASKS,
"[masks] outline cache: held for geometry %lu at step %d, live %lu at step %d -> %s\n",
2471 (
unsigned long)
mask_gui->geometry_generation,
mask_gui->outline_step_built,
2484 if(
mask_gui->geometry_generation == 0)
2665 ||
mask_gui->handle_border_selected;
2672 ||
mask_gui->handle_border_hovered >= 0
2700 else if(
mask_gui->creation_closing_form)
2716 const uint32_t
state,
2720 if(button != 1 && button != 3)
return;
2749 else if(
mask_gui->handle_hovered >= 0)
2758 else if(
mask_gui->handle_border_hovered >= 0)
2767 else if(
mask_gui->seg_hovered >= 0)
2779 if(button != 1)
return;
2800 float point[2] = { (float)
x, (
float)y };
2815 double y,
double pressure,
int which);
3073 else if(
mask_form->functions->key_pressed)
3111 = {
"plugins/darkroom/masks/scroll/plain",
3112 "plugins/darkroom/masks/scroll/shift",
3113 "plugins/darkroom/masks/scroll/primary",
3114 "plugins/darkroom/masks/scroll/primary_shift" };
3120 = {
"none",
"size",
"fading",
"opacity",
"rotation" };
3154 return N_(
"Shift+Scroll");
3156 return N_(
"Ctrl+Scroll");
3158 return N_(
"Ctrl+Shift+Scroll");
3161 return N_(
"Scroll");
3172 return N_(
"Fading");
3174 return N_(
"Opacity");
3176 return N_(
"Rotation");
3179 return N_(
"Nothing");
3188 return N_(
"Curvature");
3273 "[masks] scroll: ret=%d hinted=%d form=%p type=%d gui=%p group_selected=%d flow=%d state=0x%x\n",
3308 const float *points,
const int points_count,
const float zoom_scale,
3315 result[0] =
ray_1[0];
3316 result[1] =
ray_1[1];
3339 const int j = (
i + 1 < points_count) ? (
i + 1) :
first_pt;
3340 const float x3 = points[
i * 2];
3341 const float y3 = points[
i * 2 + 1];
3342 const float x4 = points[
j * 2];
3343 const float y4 = points[
j * 2 + 1];
3346 const float dx =
x4 -
x3;
3347 const float dy =
y4 -
y3;
3348 const float det = dx * (-dir_y) + dy * dir_x;
3349 if(
det > -1e-8f &&
det < 1e-8f)
continue;
3369 const int node_count,
const float zoom_scale,
3399 float head[2] = { 0.0f, 0.0f };
3400 float tail[2] = { 0.0f, 0.0f };
3421 const float pts[4] = {
tail[0],
tail[1], source[0], source[1] };
3435 head[0] = 0.5f * (
main[0] + source[0]);
3436 head[1] = 0.5f * (
main[1] + source[1]);
3484 const float *points,
const int points_count,
const int node_count,
3488 if(node_count <= 0 || points_count <= node_count * 3 + 6)
return;
3523 const double start_x = points[2];
3524 const double start_y = points[3];
3525 const double end_x = points[(node_count - 1) * 6 + 2];
3526 const double end_y = points[(node_count - 1) * 6 + 3];
3539 cairo_move_to(cr, points[node_count * 6], points[node_count * 6 + 1]);
3555 double last_x = points[node_count * 6];
3556 double last_y = points[node_count * 6 + 1];
3733 out[
taken].last[1] =
pts->points[2 * (
pts->points_count - 1) + 1];
3746 for(
int i = 0;
i < count;
i++)
3748 const double x = array[2 *
i];
3749 const double y = array[2 *
i + 1];
3771 gboolean any =
FALSE;
3812 const uint64_t generation,
const int count)
3930 "[masks] session re-render: rebuild=%d moved=%d generation %lu->%lu count %d->%d"
3931 " matrix (%.4f %.4f %.4f %.4f %.2f %.2f)\n",
4076 if(x1 <= x0 || y1 <= y0)
return;
4077 for(
int y = y0; y < y1; y++)
memset(data + (
size_t)y * stride + (
size_t)x0 * 4, 0, (
size_t)(x1 - x0) * 4);
4084 const int x0 = (int)
floor(
x) - margin;
4085 const int y0 = (int)
floor(y) - margin;
4086 const int x1 = (int)
ceil(
x) + margin + 1;
4087 const int y1 = (int)
ceil(y) + margin + 1;
4093 rect->height = y1 - y0;
4134 return nodes > 0 && points_count >= nodes * 3;
4140 double scale_x = 1.0;
4141 double scale_y = 1.0;
4143 return (scale_x > 0.0) ? scale_x : 1.0;
4153 double x = array[2 *
i];
4154 double y = array[2 *
i + 1];
4165 const float *
const arrays[3] = {
pts->points,
pts->border,
pts->source };
4166 const int counts[3] = {
pts->points_count,
pts->border_count,
pts->source_count };
4167 for(
int a = 0; a < 3; a++)
4170 const int header =
MIN(nodes * 3,
counts[a]);
4183 for(
int k = 0;
k < nodes;
k++)
4185 double nx =
pts->points[
k * 6 + 2];
4186 double ny =
pts->points[
k * 6 + 3];
4188 for(
int c = 0; c < 2; c++)
4190 double cx =
pts->points[
k * 6 + (c ? 4 : 0)];
4191 double cy =
pts->points[
k * 6 + (c ? 5 : 1)];
4238 rect->height += 2 * margin;
4251 for(
int c = 0; c < 4; c++)
4253 double x = xs[c & 1];
4254 double y = ys[c >> 1];
4282 gboolean bounded =
FALSE;
4284 if(!bounded)
return FALSE;
4354 const int y0,
const int x1,
const int y1)
4357 double offset_x = 0.0;
4358 double offset_y = 0.0;
4364 cairo_rectangle(cr, (frame->
x + x0 - offset_x) / s, (frame->
y + y0 - offset_y) / s, (x1 - x0) / s,
4374 const int x0 =
CLAMP(dirty->x, 0, frame->
width);
4376 const int x1 =
CLAMP(dirty->x + dirty->width, 0, frame->
width);
4377 const int y1 =
CLAMP(dirty->y + dirty->height, 0, frame->
height);
4378 if(x1 <= x0 || y1 <= y0)
return;
4406 for(
int i = 0;
i < count;
i += 32)
hash =
dt_hash(
hash, (
const char *)&array[2 *
i], 2 *
sizeof(
float));
4407 hash =
dt_hash(
hash, (
const char *)&array[2 * (count - 1)], 2 *
sizeof(
float));
4492 for(
int k = 0;
k <
pts->border_skip_count;
k++)
4493 if(
i >=
pts->border_skips[
k].jump_from &&
i < pts->border_skips[
k].resume_at)
return k;
4502 const int count =
MIN(
pts->points_count,
pts->border_count);
4503 for(
int i = 0;
i < count;
i++)
4505 pts->points[2 *
i],
pts->points[2 *
i + 1]);
4516 const char *dir =
g_getenv(
"MASKS_DUMP_OVERLAY");
4527 fprintf(info,
"canvas %d %d %dx%d device_scale %.3f dirty %d %d %dx%d\n", frame->
x, frame->
y, frame->
width,
4528 frame->
height, frame->
device_scale, dirty->x, dirty->y, dirty->width, dirty->height);
4579 (int)
ceil((dirty->x + dirty->width) / s) - (
int)
floor(dirty->x / s),
4580 (int)
ceil((dirty->y + dirty->height) / s) - (
int)
floor(dirty->y / s) };
4658 dirty->width = x1 - dirty->x;
4659 dirty->height = y1 - dirty->y;
4767 dirty.width = frame.
width;
4768 dirty.height = frame.
height;
4773 any ? dirty.width : 0, any ? dirty.height : 0, frame.
width, frame.
height,
4916 && !IS_NULL_PTR(module->gui) && !IS_NULL_PTR(module->gui->blend_data))
4918 dt_iop_gui_blend_data_t *blend_data = (dt_iop_gui_blend_data_t *)module->gui->blend_data;
4934 module->blend_params->mask_id = 0;
5181 float center[2] = { 0.0f, 0.0f };
5251 return current *
powf(amount, (
float)flow);
5253 return current + amount * (float)flow;
5286 if(!
g_strcmp0(
feature,
"rotation")) flow = (flow > 1) ? (flow - 1) * 5 : flow;
5437 "[masks] point_in_form walk trapped after %d visits of %d points -- corrupt"
5438 " outline or skip ranges; hit-test result is unreliable\n",
5457 if(next !=
skips[s].jump_from)
continue;
5463 "[masks] skip range [%d -> %d] does not move forward within %d points --"
5464 " ignoring it; the producer is broken\n",
5471 next =
skips[s].resume_at;
5495 "[masks] non-finite outline sample at %d of %d (y %s) -- the buffer should"
5496 " hold geometry only; treating the outline as ended\n", next,
form_points_count,
5497 isnan(y2) ?
"also NaN" :
"finite, i.e. the old in-band jump encoding");
5532 module = dev->gui_module;
5535 module->masks_selection_changed(module, selected_formid);
5552 fprintf(
stderr,
"[dt_masks_set_source_pos_initial_state] unknown state for setting masks position type\n");
5574 const float raw_width =
geometry.raw_width;
5575 const float raw_height =
geometry.raw_height;
5588 mask_form->functions->initial_source_pos(dev, raw_width, raw_height,
5592 fprintf(
stderr,
"[dt_masks_set_source_pos_initial_value] unsupported masks type when calculating source position initial value\n");
5605 float source_points[2] = {
mask_gui->pos_source[0],
mask_gui->pos_source[1] };
5608 mask_form->source[0] = source_points[0];
5609 mask_form->source[1] = source_points[1];
5627 float source_points[2] = {
mask_gui->pos_source[0],
mask_gui->pos_source[1] };
5630 mask_form->source[0] = source_points[0];
5631 mask_form->source[1] = source_points[1];
5634 fprintf(
stderr,
"[dt_masks_set_source_pos_initial_value] unknown source position type\n");
5649 const float raw_width =
geometry.raw_width;
5650 const float raw_height =
geometry.raw_height;
5668 fprintf(
stderr,
"[dt_masks_calculate_source_pos_origin] unsupported masks type when calculating source position value\n");
5692 fprintf(
stderr,
"[dt_masks_calculate_source_pos_origin] unknown source position type for setting source position value\n");
5709 const float center_x = center[0];
5710 const float center_y = center[1];
5728 center_x + 10.0f, center_y, center_x, center_y + 10.0f };
5742 return angle /
M_PI * 180.0f;
5812 dt_iop_gui_blend_data_t *blend_data =
module->gui ? (dt_iop_gui_blend_data_t *)module->gui->blend_data : NULL;
5827 module->dev->form_gui->edit_mode = value;
5851 const float amount =
scroll_up ? 0.02f : -0.02f;
5892 for(
int y = 0; y <
height; y++)
5894 uint32_t *
const row = (uint32_t *)(pixels + (
size_t)y * stride);
5897 const float v = mask[(size_t)y *
width +
x];
5898 const uint32_t
g = (uint32_t)(
CLAMPF(
v, 0.0f, 1.0f) * 255.0f + 0.5f);
5899 row[
x] = (
g << 16) | (
g << 8) |
g;
5917 int32_t raw_width = 0;
5918 int32_t raw_height = 0;
5956 if(palette[
i].alpha <= 0.0) palette[
i] = (GdkRGBA){ 1.0, 1.0, 1.0, 1.0 };
5975 = { .
scale = (
double)
width / (
double)raw_width, .offset_x = 0.0, .offset_y = 0.0 };
6023static inline void _emit_run(
cairo_t *cr,
const float *
const points,
const int first,
const int last,
6026 double last_x = points[first * 2];
6027 double last_y = points[first * 2 + 1];
6030 for(
int i = first + 1;
i < last;
i++)
6032 const double x = points[
i * 2];
6033 const double y = points[
i * 2 + 1];
6034 const double dx =
x - last_x;
6035 const double dy = y - last_y;
6036 if((dx * dx + dy * dy) <
min_step2)
continue;
6044 const double x = points[(last - 1) * 2];
6045 const double y = points[(last - 1) * 2 + 1];
6052 if(!cr || !points || first >= last)
return;
6066 while(next < count &&
skips[next].resume_at <= at) next++;
6069 if(next < count &&
skips[next].jump_from < last) run_end =
MAX(
skips[next].jump_from, at);
6073 if(next < count &&
skips[next].jump_from < last)
6075 at =
MAX(
skips[next].resume_at, at + 1);
6093 for(
int i = 0;
i <
preview->points_count;
i++)
6104 float **points,
int *points_count,
6109 *points, *points_count))
6113 float pts[2] = { xs, ys };
6119 const float dx =
pts[0] - (*points)[0];
6120 const float dy =
pts[1] - (*points)[1];
6126 (*points)[0] =
pts[0];
6127 (*points)[1] =
pts[1];
6133 (*points)[
i * 2] += dx;
6134 (*points)[
i * 2 + 1] += dy;
6140 *points, *points_count))
Handle default and user-set shortcuts (accelerators)
GtkWidget * dt_gui_main_window(void)
struct dt_ui_t * dt_gui_get_ui(void)
GtkWidget * dt_gui_center_widget(void)
static double dist(double x1, double y1, double x2, double y2)
static void error(char *msg)
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
float dt_bauhaus_slider_get(GtkWidget *widget)
int dt_bauhaus_combobox_get(GtkWidget *widget)
int dt_bauhaus_combobox_length(GtkWidget *widget)
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
GtkWidget * dt_bauhaus_slider_new_with_range(dt_bauhaus_t *bh, dt_gui_module_t *self, float min, float max, float step, float defval, int digits)
void dt_bauhaus_combobox_remove_at(GtkWidget *widget, int pos)
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
void dt_bauhaus_slider_set_factor(GtkWidget *widget, float factor)
#define DT_BAUHAUS_WIDGET(obj)
void dt_iop_gui_blend_masks_update(dt_iop_module_t *module)
The blending panel's GUI state and API, cut out of develop/blend.h.
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
static void transform(float *x, float *o, const float *m, const float t_h, const float t_v)
struct _GtkWidget GtkWidget
GtkWidget, opaque, spelled exactly as GTK spells it.
static const float const float const float min
const dt_colormatrix_t dt_aligned_pixel_t out
const dt_colormatrix_t matrix
void dt_conf_set_bool(const char *name, int val)
int dt_conf_get_bool(const char *name)
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_string(const char *name, const char *val)
const char * dt_conf_get_string_const(const char *name)
Borrow the stored string for name without copying it.
void dt_control_mouse_is_dragging(gboolean state)
void dt_toast_log(const char *msg,...)
void dt_control_log(const char *msg,...)
void dt_control_queue_redraw_center()
Request a redraw of the centre view.
void dt_control_hinter_message(const struct dt_control_t *s, const char *message)
void dt_control_queue_cursor_by_name(const char *curs_str)
Queue a GTK named cursor for the next cursor commit.
#define dt_control_queue_cursor(cursor)
#define dt_control_set_cursor_visible(visible)
struct dt_control_t * dt_control_get_global(void)
void * dt_alloc_align(size_t size)
Allocate cacheline-aligned memory.
struct dt_gui_gtk_t * dt_gui_get_global(void)
struct dt_bauhaus_t * dt_bauhaus_get_global(void)
gboolean dt_dev_geometry_get_raw_size(const dt_develop_t *dev, int32_t *width, int32_t *height)
void dt_dev_geometry_set_processed_size(dt_develop_t *dev, const int32_t width, const int32_t height)
dt_dev_image_geometry_t dt_dev_geometry_snapshot(const dt_develop_t *dev)
#define dt_dev_add_history_item(dev, module, enable, redraw)
void dt_dev_pixelpipe_change_zoom_main(dt_develop_t *dev)
gboolean dt_dev_viewport_set_center(dt_develop_t *dev, const float center_x, const float center_y)
void dt_dev_coordinates_image_abs_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
void dt_dev_get_processed_size(const dt_develop_t *dev, int *procw, int *proch)
int dt_dev_coordinates_raw_abs_to_image_abs(dt_develop_t *dev, float *points, size_t points_count)
void dt_dev_coordinates_raw_norm_to_raw_abs(dt_develop_t *dev, float *points, size_t num_points)
float dt_dev_get_zoom_level(const dt_develop_t *dev)
void dt_dev_masks_selection_change(dt_develop_t *dev, struct dt_iop_module_t *module, const int selectid, const int throw_event)
gboolean dt_dev_clamp_viewport_center(dt_develop_t *dev)
Clamp the viewport centre against the box currently visible at this zoom.
gboolean dt_dev_rescale_roi_to_input(dt_develop_t *dev, cairo_t *cr, int32_t width, int32_t height)
Scale the ROI to fit the input size within given width/height, centered.
int dt_dev_distort_transform_gui(dt_develop_t *dev, const double iop_order, const int transf_direction, float *points, size_t points_count)
The GUI's bounded transform folds, composed by the geometry service.
int dt_dev_coordinates_image_abs_to_raw_abs(dt_develop_t *dev, float *points, size_t points_count)
void dt_dev_coordinates_image_norm_to_image_abs(dt_develop_t *dev, float *points, size_t num_points)
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.
void dt_dev_coordinates_raw_abs_to_raw_norm(dt_develop_t *dev, float *points, size_t num_points)
void dt_dev_coordinates_image_abs_to_raw_norm(dt_develop_t *dev, float *points, size_t num_points)
gchar * dt_history_item_get_name(const struct dt_iop_module_t *module)
@ DT_DEV_TRANSFORM_DIR_BACK_EXCL
@ DT_DEV_TRANSFORM_DIR_FORW_INCL
GtkWidget * geometry
its size, under the preview
GtkWidget * preview
what the selected row actually captures
GHashTable * selected
set of checked row labels, mirrored to conf on every change
#define DT_DRAW_RADIUS_NODE_SELECTED
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)
void(* shape_draw_function_t)(struct dt_develop_t *dev, cairo_t *cr, const float *points, const int points_count, const int nb, const gboolean border, const gboolean source, const struct dt_masks_skip_range_t *skips, const int skip_count)
static double dt_draw_min_emit_step(cairo_t *cr)
Stroke a line with style.
static void dt_draw_source_shape(struct dt_develop_t *dev, 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)
#define DT_DRAW_SCALE_ARROW
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...
static GdkPixbuf * dt_draw_get_pixbuf_from_cairo(DTGTKCairoPaintIconFunc paint, const int width, const int height)
static int dt_pthread_rwlock_wrlock(dt_pthread_rwlock_t *rwlock) ACQUIRE(rwlock) NO_THREAD_SAFETY_ANALYSIS
static int dt_pthread_rwlock_unlock(dt_pthread_rwlock_t *rwlock) RELEASE_GENERIC(rwlock) NO_THREAD_SAFETY_ANALYSIS
static int dt_pthread_rwlock_rdlock(dt_pthread_rwlock_t *rwlock) ACQUIRE_SHARED(rwlock) NO_THREAD_SAFETY_ANALYSIS
static guint dt_keys_mainpad_alternatives(const guint key_val)
Remap keypad keys to usual mainpad ones.
uint64_t dt_geometry_chain_generation(const dt_geometry_chain_t *chain)
How many times this chain has been rebuilt. A GUI cache key for anything derived from the composed ge...
Where things are on the image, answered without a pipeline.
static gboolean g_list_shorter_than(const GList *list, unsigned len)
void dt_group_events_post_expose_except(cairo_t *cr, float zoom_scale, dt_masks_form_t *form, dt_masks_form_gui_t *gui, const int except_pos)
void dt_group_events_post_expose_only(cairo_t *cr, float zoom_scale, dt_masks_form_t *form, dt_masks_form_gui_t *gui, const int pos)
void dt_group_events_post_expose(cairo_t *cr, float zoom_scale, dt_masks_form_t *form, dt_masks_form_gui_t *gui)
static uint64_t dt_hash(uint64_t hash, const char *str, size_t size)
void dt_iop_request_focus(dt_iop_module_t *module)
Move darkroom focus to module, or clear it with NULL.
@ IOP_FLAGS_SUPPORTS_BLENDING
GtkWidget * dt_iop_togglebutton_new_no_register(dt_iop_module_t *self, const char *section, const gchar *label, const gchar *ctrl_label, GCallback callback, gboolean local, guint accel_key, GdkModifierType mods, DTGTKCairoPaintIconFunc paint, GtkWidget *box)
GtkWidget * dt_iop_togglebutton_new(dt_iop_module_t *self, const char *section, const gchar *label, const gchar *ctrl_label, GCallback callback, gboolean local, guint accel_key, GdkModifierType mods, DTGTKCairoPaintIconFunc paint, GtkWidget *box)
gboolean dt_mask_scroll_increases(int up)
_lib_location_type_t type
int32_t dt_get_debug_flags(void)
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.
float *const restrict const size_t k
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
dt_masks_result_t dt_masks_group_get_member(dt_develop_t *dev, const int group_id, const int formid, dt_masks_member_t *out)
Read one group member by identity.
dt_masks_form_t * _group_create(dt_develop_t *develop, dt_iop_module_t *module, dt_masks_type_t group_type)
dt_masks_raster_result_t dt_masks_get_points_border(dt_develop_t *develop, dt_masks_form_t *mask_form, float **point_buffer, int *point_count, float **border_buffer, int *border_count, dt_masks_skip_range_t **border_skips, int *border_skip_count, int source, dt_iop_module_t *module)
void _check_id(dt_develop_t *dev, dt_masks_form_t *mask_form)
dt_masks_result_t dt_masks_group_set_name_from_module(dt_develop_t *dev, const int group_id, dt_iop_module_t *module)
Name a group after the module that renders it, by id.
dt_masks_result_t dt_masks_group_set_member_opacity(dt_develop_t *dev, const int group_id, const int formid, const float opacity, dt_masks_member_t *out)
Set a group member's opacity.
int _find_in_group(dt_develop_t *dev, dt_masks_form_t *group_form, int form_id)
void dt_masks_form_update_gravity_center(dt_develop_t *dev, dt_masks_form_t *mask_form)
dt_masks_form_t * _group_from_module(dt_develop_t *develop, dt_iop_module_t *module)
const char * dt_masks_type_name(const dt_masks_type_t type)
The stable, untranslated token for a shape kind: circle, ellipse, polygon, brush, gradient,...
void dt_masks_form_gui_points_free(gpointer data)
void dt_masks_free_form(dt_masks_form_t *form)
void dt_masks_iop_use_same_as(struct dt_iop_module_t *module, struct dt_iop_module_t *src)
dt_masks_raster_result_t
What a rasterisation attempt produced.
dt_masks_form_t * dt_masks_create_ext(dt_develop_t *dev, dt_masks_type_t type)
@ DT_MASKS_SOURCE_POS_RELATIVE_TEMP
@ DT_MASKS_SOURCE_POS_RELATIVE
@ DT_MASKS_SOURCE_POS_ABSOLUTE
dt_masks_form_t * dt_masks_create(dt_masks_type_t type)
void dt_masks_form_move(dt_masks_form_t *grp, int formid, int up)
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)
dt_masks_form_t * dt_masks_get_from_id(dt_develop_t *dev, int id)
@ DT_MASKS_POINT_STATE_NORMAL
@ DT_MASKS_POINT_STATE_USER
static void dt_masks_dynbuf_free(dt_masks_dynbuf_t *a)
float * dt_masks_debug_rasterise(dt_develop_t *dev, dt_masks_form_t *form, const int width, const int height)
Rasterise form into a freshly allocated width*height float buffer, 0..1.
Render a mask's rasterisation and its GUI overlay to an image file, headlessly.
@ DT_MASKS_DEBUG_BACKDROP_TRANSPARENT
@ DT_MASKS_DEBUG_BACKDROP_RASTER
What a mask outline needs in order to place itself, and who supplies it.
The per-shape function table, private to the masks implementation.
Ask the masks module about a shape or a group, instead of reading its structs.
static void _masks_gui_menu_item_block_activate(GtkWidget *widget, gpointer user_data)
void dt_masks_group_ungroup(dt_develop_t *dev, dt_masks_form_t *dest_group, dt_masks_form_t *group_form)
int dt_masks_preview_add_clone_source(dt_masks_form_gui_t *gui, dt_masks_preview_buffers_t *preview)
static gboolean _canvas_begin(cairo_t *cr, const int width, const int height, _canvas_frame_t *frame)
gboolean dt_masks_remove_or_delete(struct dt_iop_module_t *module, dt_masks_form_t *sel, int parent_id, dt_masks_form_gui_t *mask_gui, int form_id)
If the form to remove is used once, ask to the user if he wants to delete it from the list or just re...
static uint64_t _static_layer_key_compute(cairo_t *canvas_cr, const float zoom_scale, const dt_masks_form_t *form, const dt_masks_form_gui_t *gui)
static void _bound_include_points(cairo_t *canvas_cr, const float *const array, const int limit, const double scale, cairo_rectangle_int_t *rect, gboolean *any)
static int _session_sigs_count
static gboolean _session_bbox_from_points(const dt_masks_form_gui_t *gui, double bbox[4])
static void _bbox_include_array(const float *const array, const int count, double bbox[4], gboolean *any)
Union of the cached outlines, or FALSE when there is nothing to bound.
static void _session_bbox_invalidate(void)
static void _session_sigs_reset(void)
void dt_masks_draw_source(cairo_t *cr, dt_masks_form_gui_t *mask_gui, const int form_index, const int node_count, const float zoom_scale, struct dt_masks_gui_center_point_t *center_point, const shape_draw_function_t *draw_shape_func)
Draw the source for a correction mask.
static void _overlay_dump_outline(const dt_masks_form_gui_points_t *const pts, const char *path)
static gboolean _masks_gui_menu_item_forward_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
static void _canvas_composite(cairo_t *cr, const _canvas_frame_t *frame, cairo_surface_t *surface, const int x0, const int y0, const int x1, const int y1)
void dt_masks_gui_set_dragging(dt_masks_form_gui_t *gui)
GtkWidget * dt_masks_gui_add_interaction_slider(GtkWidget *menu, const char *label, dt_develop_t *dev, const int group_id, const int formid, dt_masks_interaction_t interaction, dt_masks_increment_t increment, float min, float max, float step, float value, int digits, const char *format, float factor, dt_masks_form_gui_t *gui, dt_iop_module_t *module)
Append a bauhaus-slider menu item to a mask context menu, bound to one shape interaction (size,...
static int _overlay_skip_of(const dt_masks_form_gui_points_t *const pts, const int i)
static int _canvas_height
static _session_outline_sig_t * _session_sigs
void dt_masks_clear_form_gui(dt_develop_t *develop)
static void _menu_add_exist(dt_iop_module_t *module, int form_id)
static gboolean _dt_masks_events_should_update_hover_on_move(dt_masks_form_gui_t *mask_gui)
void dt_masks_scroll_mapping_set(dt_masks_scroll_modifier_t modifier, dt_masks_interaction_t interaction)
static gboolean _overlay_apply_transform(cairo_t *mask_draw, dt_develop_t *develop, const dt_masks_overlay_transform_t *transform, const int width, const int height)
gboolean dt_masks_reset_bezier_ctrl_points(struct dt_iop_module_t *module, struct dt_masks_form_t *mask_form, struct dt_masks_form_gui_t *mask_gui, const int form_index, const struct dt_masks_form_gui_points_t *gui_points, const int node_index, dt_masks_points_states_t *state)
void dt_masks_remove_node(struct dt_iop_module_t *module, dt_masks_form_t *mask_form, int parent_id, dt_masks_form_gui_t *mask_gui, int form_index, int node_index)
void dt_masks_events_post_expose(dt_develop_t *dev, struct dt_iop_module_t *module, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery)
void dt_masks_gui_populate_interaction_sliders(GtkWidget *menu, dt_develop_t *dev, dt_masks_form_t *form, const int group_id, dt_masks_form_gui_t *gui, dt_iop_module_t *module)
Append the full set of shape-parameter sliders (size/fading/rotation or curvature/fade/rotation depen...
static uint64_t _session_pattern_key
GtkWidget * dt_masks_shape_menu_item_new(GtkWidget *menu, const dt_masks_type_t type, GCallback activate_callback, gpointer user_data)
Append a menu entry for one shape type: its toolbar icon, then its toolbar label.
static void _masks_move_up_down_callback(gpointer user_data, const int up)
gboolean dt_masks_point_is_within_radius(const float point_x, const float point_y, const float center_x, const float center_y, const float squared_radius)
Check whether a point lies within a squared radius of a center.
float dt_masks_get_set_conf_value(dt_masks_form_t *mask_form, char *feature, float new_value, float value_min, float value_max, dt_masks_increment_t increment, int flow)
Change a numerical property of a mask shape, either by in/de-crementing the current value or setting ...
static void _menu_no_masks(struct dt_iop_module_t *module)
gboolean dt_masks_toggle_bezier_node_type(struct dt_iop_module_t *module, struct dt_masks_form_t *mask_form, struct dt_masks_form_gui_t *mask_gui, const int form_index, const struct dt_masks_form_gui_points_t *gui_points, const int node_index, float node[2], float ctrl1[2], float ctrl2[2], dt_masks_points_states_t *state)
static gboolean _overlay_pointer_valid
int dt_masks_events_button_released(dt_develop_t *dev, struct dt_iop_module_t *module, double x, double y, int button, uint32_t state)
void dt_masks_gui_points_update_bbox(dt_masks_form_gui_points_t *gp)
int dt_masks_group_index_from_formid(const dt_masks_form_t *group_form, int form_id)
Find any group that currently references formid, searching every top-level group in dev->forms and th...
void dt_masks_gui_form_remove(dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui, int form_index)
void dt_masks_change_form_gui(dt_develop_t *dev, dt_masks_form_t *new_form)
static const char *const _interaction_conf_values[DT_MASKS_INTERACTION_LAST]
static void _set_cursor_shape(dt_masks_form_gui_t *mask_gui)
gboolean dt_masks_form_get_gravity_center(dt_develop_t *dev, const dt_masks_form_t *mask_form, float center[2], float *area)
static void _canvas_cairo_bound(cairo_t *canvas_cr, const dt_masks_form_gui_t *gui, cairo_rectangle_int_t *rect, gboolean *any)
static uint64_t _session_gui_generation
void dt_masks_gui_form_test_create(dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui, dt_iop_module_t *module)
static gboolean _masks_shape_button_pressed(GtkWidget *button, GdkEventButton *event, gpointer user_data)
static int _masks_shape_button_index(const dt_masks_shape_buttons_data_t *data, GtkWidget *button)
int dt_masks_gui_outline_step(const dt_develop_t *dev)
The density the dev's GUI shows its outlines at, in image pixels between consecutive samples: what th...
void dt_masks_gui_reset_dragging(dt_masks_form_gui_t *gui)
static void _apply_gui_button_pressed_state(dt_masks_form_gui_t *mask_gui, const int button, const uint32_t state, const gboolean shape_was_selected)
gboolean dt_masks_gui_form_create_throttled(dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui, int form_index, dt_iop_module_t *module, float posx, float posy)
int dt_masks_events_button_pressed(dt_develop_t *dev, struct dt_iop_module_t *module, double x, double y, double pressure, int button, int event_type, uint32_t state)
gboolean dt_masks_gui_confirm_permanent_delete(const char *form_name)
Ask the user to confirm a permanent shape deletion, gated by the "ask_before_delete_mask_shape" pref....
static uint64_t _session_pattern_hash(cairo_t *cr, const dt_masks_form_gui_t *creation_gui, const uint64_t generation, const int count)
What the cached rendering is a rendering OF.
static gboolean _session_gui_inited
static int _masks_gui_form_group_use_count(const dt_develop_t *dev, const int formid)
dt_masks_form_group_t * dt_masks_form_get_selected_group(const dt_masks_form_t *mask_form, const dt_masks_form_gui_t *mask_gui)
Get the selected group entry from the GUI selection index.
static gboolean _dt_masks_events_group_update_selection(dt_masks_form_t *group_form, dt_masks_form_gui_t *mask_gui)
Update group selection from the current cached cursor before leaf dispatch.
gboolean dt_masks_is_anything_selected(const dt_masks_form_gui_t *mask_gui)
void dt_masks_soft_reset_form_gui(dt_masks_form_gui_t *mask_gui)
static void _dt_masks_events_set_current_pos(const double x, const double y, dt_masks_form_gui_t *mask_gui)
Convert the GTK/Cairo widget cursor once for the full mask event chain.
const char * dt_masks_interaction_alias_name(dt_masks_interaction_t interaction)
The other word for a property, when a shape family spells it its own way.
static void _emit_run(cairo_t *cr, const float *const points, const int first, const int last, const double min_step2)
Append a shape's outline to cr as the COMPLEMENT of its exclusion list.
dt_masks_form_group_t * dt_masks_form_get_selected_group_live(const dt_masks_form_t *mask_form, const dt_masks_form_gui_t *mask_gui)
Resolve a "live" selected group entry, even if GUI selection is stale.
static void _session_bound_include(cairo_t *canvas_cr, const float zoom_scale, cairo_rectangle_int_t *rect, gboolean *any)
int dt_masks_events_mouse_moved(dt_develop_t *dev, struct dt_iop_module_t *module, double x, double y, double pressure, int which)
void dt_masks_gui_set_outline_density(dt_masks_form_gui_t *mask_gui, const double image_px_per_device_px)
static void _menu_add_shape(struct dt_iop_module_t *module, dt_masks_type_t type)
static void _masks_gui_interaction_apply_value(dt_masks_gui_interaction_slider_t *data, float value)
void dt_masks_append_form(dt_develop_t *develop, dt_masks_form_t *mask_form)
static dt_masks_form_t * _dt_masks_events_get_dispatch_form(dt_masks_form_t *visible_form, const dt_masks_form_gui_t *mask_gui, dt_masks_form_group_t **group_entry, int *parent_id, int *form_index)
Resolve the concrete form that should receive an event.
dt_masks_form_group_t * dt_masks_form_group_from_parentid(dt_develop_t *dev, int parent_id, int form_id)
Return the group entry for a (parent, form) pair.
const char * dt_masks_interaction_name(dt_masks_interaction_t interaction)
static gboolean _masks_remove_or_delete_finish(struct dt_iop_module_t *module, dt_masks_form_t *sel, int parent_id, dt_masks_form_gui_t *mask_gui, int form_id, gboolean keep_unused)
void dt_masks_events_post_expose_with(dt_develop_t *dev, struct dt_iop_module_t *module, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery, const dt_masks_overlay_transform_t *transform)
Draw the mask overlay with an explicit mapping; transform NULL means the viewport's.
void dt_masks_shape_buttons_deactivate_all(GtkWidget *active_button)
static void _masks_movedown_callback(GtkWidget *menu, gpointer user_data)
static gboolean _overlay_damage_valid
float dt_masks_rotate_with_anchor(dt_develop_t *develop, const float anchor[2], const float center[2], dt_masks_form_gui_t *mask_gui)
Compute rotation angle (degrees) around a center using an anchor point.
static void _masks_gui_interaction_slider_changed(GtkWidget *widget, gpointer user_data)
GtkWidget * dt_masks_shape_buttons_create(const dt_masks_shape_buttons_config_t *config)
Build a synchronized toolbar for creating masks shapes.
static void _canvas_clear(cairo_surface_t *canvas, const cairo_rectangle_int_t *rect)
static const dt_masks_shape_button_def_t _masks_shape_button_defs[]
static gboolean _dt_masks_events_cursor_over_form(const dt_masks_form_t *dispatch_form, dt_masks_form_gui_t *mask_gui, const int form_index)
static void _overlay_draw_form(cairo_t *cr, const float zoom_scale, dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui, const gboolean layered)
static gboolean _masks_shape_icon_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
static cairo_pattern_t * _session_pattern
static void _masks_moveup_callback(GtkWidget *menu, gpointer user_data)
static void _masks_shape_buttons_destroy(GtkWidget *widget, dt_masks_shape_buttons_data_t *data)
void _masks_gui_delete_node_callback(GtkWidget *menu, gpointer user_data)
gboolean dt_masks_node_is_cusp(const dt_masks_form_gui_points_t *gui_points, const int node_index)
returns wether a node is a corner or not. A node is a corner if its 2 control handles are at the same...
static void _session_pattern_reset(void)
Drop the session outlines. Safe to call when nothing is cached.
static cairo_surface_t * _static_layer
void dt_masks_group_entry_apply_operation(struct dt_masks_form_group_t *group_entry, const dt_masks_state_t apply_state)
Apply a mask state operation on a group entry.
dt_masks_form_group_t * dt_masks_group_add_form(dt_develop_t *dev, dt_masks_form_t *group_form, dt_masks_form_t *mask_form)
static const char *const _scroll_conf_keys[DT_MASKS_SCROLL_MODIFIER_LAST]
static double _overlay_pointer[2]
static gboolean _masks_remove_shape(struct dt_iop_module_t *module, dt_masks_form_t *mask_form, int parent_id, dt_masks_form_gui_t *mask_gui, int form_index)
Remove a shape from the GUI and free its resources.
static gboolean _session_clip(cairo_t *cr, const float zoom_scale)
Clip to the session's area, with room for the stroke's own width.
#define masks_gtk_menu_item_new_bold(label, selected, state, icon)
static gboolean _masks_gui_resolve_selected_shape(dt_masks_form_gui_t *gui, dt_iop_module_t **module, dt_masks_form_t **sel, int *parentid, int *formid)
static gboolean _masks_shape_button_is_current_creation(dt_develop_t *dev, const dt_masks_shape_buttons_data_t *data, const int button_index)
dt_masks_form_t * dt_masks_get_visible_form(const dt_develop_t *dev)
Return the currently visible form used by the masks GUI.
int dt_masks_events_mouse_leave(struct dt_iop_module_t *module)
static cairo_surface_t * _canvas_acquire(const int width, const int height, const double device_scale)
gboolean dt_masks_gui_remove(struct dt_iop_module_t *module, dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui, const int parent_id)
remove a mask shape or node form from the GUI. This function is used with a popupmenu "Delete" action...
void dt_masks_draw_path_seg_by_seg(cairo_t *cr, dt_masks_form_gui_t *mask_gui, const int form_index, const float *points, const int points_count, const int node_count, const float zoom_scale, const gboolean round_ends)
static gboolean _set_hinter_message(dt_masks_form_gui_t *mask_gui, const dt_masks_form_t *mask_form)
Build and display the on-canvas hint message for masks interactions.
gboolean dt_masks_gui_is_dragging(const dt_masks_form_gui_t *gui)
gboolean dt_masks_remove_shape_from_group(struct dt_iop_module_t *module, dt_masks_form_t *sel, int parent_id, dt_masks_form_gui_t *mask_gui, int form_id)
Remove the form from its current group only, keeping it around unused for potential reuse....
static void _overlay_dump(const _canvas_frame_t *const frame, const dt_masks_form_gui_t *const gui, const cairo_rectangle_int_t *const dirty)
void dt_masks_reset_show_masks_icons(dt_develop_t *dev)
static gboolean _static_layer_ensure(const _canvas_frame_t *frame, cairo_t *canvas_cr, const float zoom_scale, dt_masks_form_t *form, dt_masks_form_gui_t *gui, gboolean *rebuilt)
static void _dt_masks_find_best_attachment_point(const float ray_1[2], const float ray_2[2], const float *points, const int points_count, const float zoom_scale, const int first_pt, const gboolean is_closed_shape, const float offset_factor, float result[2])
Find the best attachment point on the shape contour for a ray crossing the form.
static gboolean _static_layer_applies(const dt_masks_form_t *form, const dt_masks_form_gui_t *gui)
static cairo_surface_t * _canvas
static gboolean header_reach_wanted(const int nodes, const int points_count)
int dt_masks_gui_confirm_delete_form_dialog(const char *form_name)
void dt_masks_shape_buttons_sync_all(void)
Make every shape toolbar show the shape currently being created, if any.
void dt_masks_iop_combo_populate(GtkWidget *widget, void *data)
static void _overlay_damage_record(cairo_t *cr, const _canvas_frame_t *const frame, const cairo_rectangle_int_t *dirty)
void dt_masks_calculate_source_pos_origin(dt_masks_form_gui_t *mask_gui, const float initial_xpos, const float initial_ypos, const float xpos, const float ypos, float *pos_x, float *pos_y, const int adding)
Compute preview-space source position for drawing the clone indicator.
const char * dt_masks_scroll_modifier_name(dt_masks_scroll_modifier_t modifier)
gboolean dt_masks_debug_write_png(dt_develop_t *dev, dt_masks_form_t *form, const dt_masks_debug_request_t *request, const char *path)
Render form per request and write it to path as a PNG.
static void _masks_gui_remove_from_group_callback(GtkWidget *menu, gpointer user_data)
const char * _get_mask_plugin(dt_masks_form_t *mask_form)
float dt_masks_apply_increment(float current, float amount, dt_masks_increment_t increment, int flow)
Apply a scroll increment to a scalar value.
int dt_masks_events_mouse_enter(struct dt_iop_module_t *module)
static double _overlay_pointer_delta[2]
static int _dt_masks_events_mouse_moved(dt_develop_t *dev, struct dt_iop_module_t *module, double x, double y, double pressure, int which)
float dt_masks_apply_increment_precomputed(float current, float amount, float scale_amount, float offset_amount, dt_masks_increment_t increment)
Apply a scroll increment using precomputed scale/offset factors.
static int _dt_masks_events_update_hover(dt_masks_form_t *dispatch_form, dt_masks_form_gui_t *mask_gui, const int form_index)
static void _masks_shape_buttons_deactivate(GtkWidget *active_button, dt_masks_shape_buttons_data_t *data)
static void _bound_include_headers(cairo_t *canvas_cr, const dt_masks_form_gui_points_t *const pts, const int nodes, const double scale, cairo_rectangle_int_t *rect, gboolean *any)
void dt_masks_draw_outline_runs(cairo_t *cr, const float *const points, const int first, const int last, const dt_masks_skip_range_t *skips, const int skip_count)
static const dt_masks_shape_button_def_t * _masks_shape_button_def(const dt_masks_type_t type)
static gboolean _dt_masks_events_group_blocks_motion(dt_masks_form_gui_t *mask_gui)
Consume the initial drag motion used to disambiguate scrolling vs dragging in groups.
void dt_masks_gui_cleanup(dt_develop_t *dev)
static double _session_bbox[4]
static cairo_rectangle_int_t _overlay_damage
gboolean dt_masks_delete_shape(struct dt_iop_module_t *module, dt_masks_form_t *sel, int parent_id, dt_masks_form_gui_t *mask_gui, int form_id)
Permanently delete the form from every group and from dev->forms. Gated by dt_masks_gui_confirm_perma...
void dt_masks_set_source_pos_initial_value(dt_masks_form_gui_t *mask_gui, dt_masks_form_t *mask_form)
Initialize the clone source position based on current GUI state.
static void _masks_shape_buttons_deactivate_signal(gpointer instance, GtkWidget *active_button, dt_masks_shape_buttons_data_t *data)
void dt_masks_reset_form_gui(dt_develop_t *dev)
GtkWidget * dt_masks_create_menu(dt_masks_form_gui_t *gui, dt_masks_form_t *form, const dt_masks_form_group_t *formgroup, const float pzx, const float pzy)
#define DT_MASKS_SHAPE_BUTTON_COUNT
static void _paint_mask_backdrop(cairo_t *cr, dt_develop_t *dev, dt_masks_form_t *form, const int width, const int height)
void dt_masks_set_visible_form(dt_develop_t *dev, dt_masks_form_t *form)
static void _masks_gui_full_delete_callback(GtkWidget *menu, gpointer user_data)
static void _session_gui_reset(void)
static gboolean _dt_masks_events_flush_rebuild_if_needed(struct dt_iop_module_t *module, dt_masks_form_t *dispatch_form, dt_masks_form_gui_t *mask_gui, const int form_index, const int button)
Flush a deferred throttled rebuild before drag state is reset.
int dt_masks_events_key_pressed(dt_develop_t *dev, struct dt_iop_module_t *module, GdkEventKey *event)
static void _masks_operation_callback(GtkWidget *menu, gpointer user_data)
void dt_masks_iop_value_changed_callback(GtkWidget *widget, struct dt_iop_module_t *module)
int dt_masks_center_view_on_form(dt_develop_t *dev, const dt_masks_form_t *mask_form)
Center the darkroom ROI on a mask form gravity center.
void dt_masks_overlay_queue_redraw(GtkWidget *widget)
void dt_masks_remove_form(dt_develop_t *develop, dt_masks_form_t *mask_form)
dt_masks_interaction_t dt_masks_scroll_get_interaction(uint32_t key_state)
Resolve a wheel event's key state into the property it edits.
static gboolean _session_bbox_valid
gboolean dt_masks_creation_mode_enter(dt_develop_t *dev, dt_iop_module_t *module, const dt_masks_type_t type)
Enter mask creation mode for a given shape type.
dt_masks_form_group_t * dt_masks_form_group_find_entry(dt_masks_form_t *group_form, const int form_id, int *out_index)
Find the group-membership entry for form_id inside group_form's own points list (not recursive into s...
static void _masks_gui_exit_creation_callback(GtkWidget *menu, gpointer user_data)
static int _outline_nodes(dt_develop_t *dev, const dt_masks_form_t *form, const int index)
int dt_masks_point_in_form_exact(const float *test_points, int test_point_count, const float *form_points, int form_points_start, int form_points_count, const dt_masks_skip_range_t *skips, int skip_count)
Check whether any 2D point in pts[] lies inside the form points[].
static void _masks_shape_buttons_sync(dt_masks_shape_buttons_data_t *data)
static int _session_gui_count
static void _masks_gui_interaction_commit(dt_masks_gui_interaction_slider_t *data)
static int _session_sigs_take(const dt_masks_form_gui_t *gui, _session_outline_sig_t *out, const int max)
Take the signature of every cached outline.
static void _masks_shape_buttons_sync_signal(gpointer instance __attribute__((unused)), dt_masks_shape_buttons_data_t *data)
static void _masks_draw_creation_session_forms(dt_develop_t *develop, dt_iop_module_t *module, cairo_t *cr, const float zoom_scale, const dt_masks_form_gui_t *creation_gui)
static int _static_layer_width
static gboolean _overlay_dirty(const _canvas_frame_t *frame, const cairo_rectangle_int_t *cairo_bound, const gboolean cairo_bounded, cairo_rectangle_int_t *dirty)
int dt_masks_events_mouse_scrolled(dt_develop_t *dev, struct dt_iop_module_t *module, double x, double y, int scroll_up, uint32_t key_state, int scrolling_delta)
static int _static_layer_height
static dt_masks_form_gui_t _session_gui
Draw completed shapes from the current creation session.
gboolean dt_masks_is_anything_hovered(const dt_masks_form_gui_t *mask_gui)
int dt_masks_find_closest_handle_common(dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui, int form_index, int node_count_override, dt_masks_border_handle_fn border_handle_cb, dt_masks_curve_handle_fn curve_handle_cb, dt_masks_node_position_fn node_position_cb, dt_masks_distance_fn distance_cb, dt_masks_post_select_fn post_select_cb, void *user_data)
Centralized hit-testing for node/handle/segment selection across shapes.
void dt_masks_init_form_gui(dt_develop_t *dev, dt_masks_form_gui_t *mask_gui)
static void _overlay_finish(cairo_t *cr, const _canvas_frame_t *const frame, const cairo_rectangle_int_t *dirty, const gboolean darkroom_frame, const gboolean layered)
void dt_masks_gui_init(dt_develop_t *dev)
void dt_masks_creation_mode_quit(dt_masks_form_gui_t *mask_gui)
Exit mask creation mode, restoring cursor visibility and resetting GUI state.
void dt_masks_group_update_name(dt_iop_module_t *module)
void dt_masks_set_edit_mode(struct dt_iop_module_t *module, dt_masks_edit_mode_t value)
static uint64_t _static_layer_key
static uint64_t _static_layer_hash_samples(uint64_t hash, const float *const array, const int count)
dt_masks_interaction_t dt_masks_scroll_mapping_get(dt_masks_scroll_modifier_t modifier)
int dt_masks_form_change_opacity(dt_develop_t *dev, dt_masks_form_t *mask_form, int parent_id, int scroll_up, const int flow)
static void _canvas_end(cairo_t *cr, const _canvas_frame_t *frame, const cairo_rectangle_int_t *dirty)
static double _canvas_device_scale(cairo_t *cr)
float dt_masks_form_set_interaction_value(dt_develop_t *dev, const int group_id, const int formid, dt_masks_interaction_t interaction, float value, dt_masks_increment_t increment, int flow, dt_masks_form_gui_t *mask_gui, dt_iop_module_t *module)
int dt_masks_points_shift_to_source(dt_develop_t *dev, const dt_iop_module_t *module, float **points, int *points_count, const float xs, const float ys, const int first_shifted)
void dt_masks_set_source_pos_initial_state(dt_masks_form_gui_t *mask_gui, const uint32_t key_state)
Decide initial source positioning mode for clone masks.
static void _rect_include(cairo_rectangle_int_t *rect, gboolean *any, const double x, const double y, const int margin)
void dt_masks_gui_form_create(dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui, int form_index, dt_iop_module_t *module)
float dt_masks_form_get_interaction_value(dt_develop_t *dev, const int group_id, const int formid, dt_masks_interaction_t interaction)
float dt_masks_get_set_conf_value_with_toast(dt_masks_form_t *mask_form, const char *feature, float amount, float value_min, float value_max, dt_masks_increment_t increment, int flow, const char *toast_fmt, float toast_scale)
Update a mask configuration value and emit a toast message.
dt_masks_form_group_t * dt_masks_group_add_form_with_state(dt_develop_t *dev, dt_masks_form_t *group_form, dt_masks_form_t *mask_form, const int parentid, const dt_masks_state_t state, const float opacity)
void dt_masks_select_form(dt_develop_t *dev, struct dt_iop_module_t *module, dt_masks_form_t *selected_form)
Select or clear the current mask form, notifying the owning module if needed.
gboolean dt_masks_form_exit_creation(dt_iop_module_t *module, dt_masks_form_gui_t *mask_gui)
static void _gui_points_bbox_extend(float *const bbox, const float *const samples, const int count)
static double _bound_header_reach(cairo_t *canvas_cr, const dt_masks_form_gui_points_t *const pts, const int nodes, const double scale)
static gboolean _overlay_clip_to_bound(cairo_t *mask_draw, const dt_masks_form_gui_t *gui, const _canvas_frame_t *const frame, cairo_rectangle_int_t *bound, const float zoom_scale)
void dt_masks_gui_form_save_creation(dt_develop_t *develop, dt_iop_module_t *module, dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui)
Save the form creation right after a shape has been finished drawing.
The interactive half of the masks subsystem: the editing state (dt_masks_form_gui_t),...
static int dt_masks_gui_selected_segment_index(const dt_masks_form_gui_t *gui)
static int dt_masks_gui_selected_node_index(const dt_masks_form_gui_t *gui)
@ DT_MASKS_SHAPE_INDEX_BRUSH
@ DT_MASKS_SHAPE_INDEX_ELLIPSE
@ DT_MASKS_SHAPE_INDEX_CIRCLE
@ DT_MASKS_SHAPE_INDEX_GRADIENT
@ DT_MASKS_SHAPE_INDEX_POLYGON
void(* dt_masks_post_select_fn)(dt_masks_form_gui_t *mask_gui, int inside, int inside_border, int inside_source, void *user_data)
Optional hook to customize selection flags after inside/border/source resolution.
void(* dt_masks_distance_fn)(float pointer_x, float pointer_y, float cursor_radius, dt_masks_form_gui_t *mask_gui, int form_index, int node_count, int *inside, int *inside_border, int *near_handle, int *inside_source, float *dist, void *user_data)
Shape-specific callback for inside/border/segment hit testing.
dt_masks_scroll_modifier_t
@ DT_MASKS_SCROLL_PRIMARY
@ DT_MASKS_SCROLL_PRIMARY_SHIFT
@ DT_MASKS_SCROLL_MODIFIER_LAST
gboolean(* dt_masks_border_handle_fn)(const dt_masks_form_gui_points_t *gui_points, int node_count, int node_index, float *handle_x, float *handle_y, void *user_data)
Shape-specific callback to fetch a node's border handle in GUI space.
#define menu_item_set_fake_accel(menu_item, keyval, mods)
static gboolean dt_masks_gui_was_anything_selected(const dt_masks_form_gui_t *gui)
static gboolean dt_masks_gui_should_hit_test(dt_masks_form_gui_t *gui)
@ DT_MASKS_SHAPE_BUTTONS_GRADIENT
@ DT_MASKS_SHAPE_BUTTONS_CIRCLE
@ DT_MASKS_SHAPE_BUTTONS_BRUSH
@ DT_MASKS_SHAPE_BUTTONS_ELLIPSE
@ DT_MASKS_SHAPE_BUTTONS_POLYGON
void(* dt_masks_node_position_fn)(const dt_masks_form_gui_points_t *gui_points, int node_index, float *node_x, float *node_y, void *user_data)
Shape-specific callback to fetch a node's position in GUI space.
void(* dt_masks_curve_handle_fn)(const dt_masks_form_gui_points_t *gui_points, int node_index, float *handle_x, float *handle_y, void *user_data)
Shape-specific callback to fetch a node's curve handle in GUI space.
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)
@ DT_MASKS_STATE_DIFFERENCE
@ DT_MASKS_STATE_INTERSECTION
@ DT_MASKS_STATE_IS_COMBINE_OP
@ DT_MASKS_STATE_EXCLUSION
@ DT_MASKS_IS_PRIMITIVE_SHAPE
@ DT_MASKS_IS_CLOSED_SHAPE
@ DT_MASKS_INTERACTION_OPACITY
@ DT_MASKS_INTERACTION_SIZE
@ DT_MASKS_INTERACTION_FADING
@ DT_MASKS_INTERACTION_LAST
@ DT_MASKS_INTERACTION_UNDEF
@ DT_MASKS_INTERACTION_ROTATION
dt_masks_result_t
What a request that may change the masks model did.
@ DT_MASKS_INCREMENT_SCALE
@ DT_MASKS_INCREMENT_OFFSET
@ DT_MASKS_INCREMENT_ABSOLUTE
static float f_inv_sqrtf(const float x)
#define CLAMPF(a, mn, mx)
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
#define __OMP_PARALLEL_FOR_SIMD__(...)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
void copy(TYPE *dest, TYPE *source, size_t num_el)
Copy a flat buffer used to initialize test matrices.
#define DT_DEBUG_CONTROL_SIGNAL_DISCONNECT(ctlsig, cb, user_data)
#define DT_DEBUG_CONTROL_SIGNAL_RAISE(ctlsig, signal,...)
struct dt_control_signal_t * dt_control_signal_get_global(void)
@ DT_SIGNAL_MASK_SHAPE_BUTTONS_SYNC
@ DT_SIGNAL_MASK_SHAPE_BUTTONS_DEACTIVATE
#define DT_DEBUG_CONTROL_SIGNAL_CONNECT(ctlsig, signal, cb, user_data)
float dt_aligned_pixel_simd_t __attribute__((vector_size(16), aligned(16)))
Apply one channel's tone curve to each of the three colour channels, or pass the channel through unto...
static const dt_aligned_pixel_simd_t value
const float uint32_t state[4]
void dt_stroke_raster_touched_reset(cairo_surface_t *surface)
gboolean dt_stroke_raster_touched(cairo_surface_t *surface, cairo_rectangle_int_t *touched)
unsigned __int64 uint64_t
Objective facts about the image a dev is working on.
struct dt_iop_module_t * gui_module
gboolean darkroom_skip_mouse_events
struct dt_masks_form_gui_t * form_gui
dt_pthread_rwlock_t masks_mutex
struct dt_geometry_chain_t * geometry_chain
struct dt_iop_module_gui_t * gui
struct dt_develop_t * dev
What to render. Zeroed means: raster only, at full image resolution, on black.
dt_masks_debug_backdrop_t backdrop
int(* populate_context_menu)(GtkWidget *menu, struct dt_masks_form_t *form, struct dt_masks_form_gui_t *gui, const float pzx, const float pzy)
void(* get_distance)(float x, float y, float as, struct dt_masks_form_gui_t *gui, int index, int num_points, int *inside, int *inside_border, int *near_handle, int *inside_source, float *dist)
dt_iop_module_t *dt_masks_interaction_t interaction
dt_masks_form_gui_t * gui
dt_masks_increment_t increment
One shape's membership of one group, BY VALUE.
One cut in a shape's border outline: while walking the border buffer forward, on reaching index jump_...
typedef double((*spd)(unsigned long int wavelength, double TempK))
void dt_show_times(const dt_times_t *start, const char *prefix)
static void dt_get_times(dt_times_t *t)
static double dt_get_wtime(void)