126#define DEVELOP_MASKS_VERSION (6)
320 const int opacity,
char *
const __restrict__ msgbuf,
const size_t msgbuf_len);
325 int *inside,
int *inside_border,
int *near,
int *inside_source,
float *
dist);
327 float **points,
int *points_count);
329 float **border,
int *border_count,
int source,
const dt_iop_module_t *
const module);
333 float **buffer,
int *
width,
int *
height,
int *posx,
int *posy);
361 double pressure,
int which,
int type, uint32_t
state,
370 void (*
draw_shape)(cairo_t *cr,
const float *points,
const int points_count,
const int nb,
const gboolean border,
const gboolean source);
574 return selected_node < 0 || selected_node == index;
582 const float *first = (
const float *)points->data;
583 float min_x = first[0];
584 float max_x = first[0];
585 float min_y = first[1];
586 float max_y = first[1];
588 for(
const GList *point_node = points; point_node; point_node = g_list_next(point_node))
590 const float *node = (
const float *)point_node->data;
592 min_x = fminf(min_x, node[0]);
593 max_x = fmaxf(max_x, node[0]);
594 min_y = fminf(min_y, node[1]);
595 max_y = fmaxf(max_y, node[1]);
598 return fmaxf(max_x - min_x, max_y - min_y);
606 if(gui->
last_hit_test_pos[0] < 0.0f || (dx * dx + dy * dy) > (hit_thresh * hit_thresh))
641 const float anchor[2],
float *delta_x,
float *delta_y)
645 *delta_x =
point[0] - anchor[0];
646 *delta_y =
point[1] - anchor[1];
668 form->
source[0] += delta_x;
669 form->
source[1] += delta_y;
673 const float delta_x,
const float delta_y)
685 ctrl1[0] = control_points[0];
686 ctrl1[1] = control_points[1];
687 ctrl2[0] = control_points[2];
688 ctrl2[1] = control_points[3];
699 const int form_index,
701 const int node_index,
702 float node[2],
float ctrl1[2],
float ctrl2[2],
715 ctrl1[0] = ctrl2[0] = node[0];
716 ctrl1[1] = ctrl2[1] = node[1];
727 const int form_index,
729 const int node_index,
747 const float handle[2],
float point[2])
749 const float dx_line = handle[0] - node[0];
750 const float dy_line = handle[1] - node[1];
752 if(fabsf(dx_line) < 1e-6f)
755 point[1] = cursor[1];
759 const float a = dy_line / dx_line;
760 const float b = node[1] - a * node[0];
761 const float denom = a * a + 1.0f;
762 const float xproj = (a * cursor[1] + cursor[0] - b * a) / denom;
765 point[1] = a * xproj + b;
772 const float projected_image_pos[2],
773 const float scale_ref)
775 float projected_raw[2] = { projected_image_pos[0], projected_image_pos[1] };
776 float node_raw[2] = { node[0], node[1] };
780 const float delta_x = projected_raw[0] - node_raw[0];
781 const float delta_y = projected_raw[1] - node_raw[1];
782 return sqrtf(delta_x * delta_x + delta_y * delta_y) / scale_ref;
788 float *points,
const int points_count,
789 float *border,
const int border_count,
790 void (*
const *draw_shape)(cairo_t *cr,
const float *points,
791 const int points_count,
const int nb,
792 const gboolean border,
793 const gboolean source),
794 const cairo_line_cap_t shape_cap,
795 const cairo_line_cap_t border_cap,
796 const gboolean save_restore,
797 const gboolean source)
799 if(save_restore) cairo_save(cr);
800 if(points && points_count > 0)
802 draw_shape, shape_cap);
803 if(border && border_count > 0)
805 draw_shape, border_cap);
806 if(save_restore) cairo_restore(cr);
857 float **border,
int *border_count,
int source,
dt_iop_module_t *module);
870 float **buffer,
int *
width,
int *
height,
int *posx,
int *posy)
937#define DEVELOP_MASKS_NB_SHAPES 5
1032 const int points_count,
const int node_count,
const float zoom_scale);
1035 int32_t pointerx, int32_t pointery);
1139 const float initial_ypos,
const float xpos,
const float ypos,
float *px,
1140 float *py,
const int adding);
1142 const float initial_xpos,
const float initial_ypos,
1143 const float xpos,
const float ypos,
const int adding)
1145 float source_pos[2] = { 0.0f, 0.0f };
1147 &source_pos[0], &source_pos[1], adding);
1148 dt_draw_cross(cr, zoom_scale, source_pos[0], source_pos[1]);
1220 const char *toast_fmt,
float toast_scale);
1259 fprintf(stderr,
"critical: out of memory for dynbuf '%s' with size request %" G_GSIZE_FORMAT
"!\n", a->
tag,
size);
1264 memcpy(newbuf, a->
buffer, a->
size *
sizeof(
float));
1281 g_strlcpy(a->
tag, tag,
sizeof(a->
tag));
1298 if(__builtin_expect(a->
pos + 2 >= a->
size, 0))
1313 if(__builtin_expect(a->
pos +
n >= a->
size, 0))
1315 if(a->
size == 0)
return NULL;
1316 size_t newsize = a->
size;
1317 while(a->
pos +
n >= newsize) newsize *= 2;
1333 if(__builtin_expect(a->
pos +
n >= a->
size, 0))
1335 if(a->
size == 0)
return;
1336 size_t newsize = a->
size;
1337 while(a->
pos +
n >= newsize) newsize *= 2;
1344 memset(a->
buffer + a->
pos, 0,
n *
sizeof(
float));
1354 assert((
long)a->
pos + offset >= 0);
1363 assert((
long)a->
pos + offset >= 0);
1374 float center[2],
float *area)
1392 if(points_count >= 3)
1398 for(
int i = 0;
i < points_count;
i++)
1400 const int j = (
i + 1 < points_count) ? (
i + 1) : 0;
1401 const double x0 = points[
i * 2];
1402 const double y0 = points[
i * 2 + 1];
1403 const double x1 = points[j * 2];
1404 const double y1 = points[j * 2 + 1];
1406 const double cross = x0 * y1 - x1 * y0;
1408 cx += (x0 + x1) * cross;
1409 cy += (y0 + y1) * cross;
1412 if(fabs(area2) > 1e-12)
1414 const double inv = 1.0 / (3.0 * area2);
1415 center[0] = (float)(cx *
inv);
1416 center[1] = (float)(cy *
inv);
1418 *area = (float)(0.5 * fabs(area2));
1426 const float inv_count = 1.0f / (float)points_count;
1427 for(
int i = 0;
i < points_count;
i++)
1429 sum_x += points[
i * 2] * inv_count;
1430 sum_y += points[
i * 2 + 1] * inv_count;
1477 const int rem = num % mult;
1479 return (rem == 0) ? num : num + mult - rem;
1493 const float cx,
const float cy,
1494 const float radius);
1502 int node_index,
float *handle_x,
float *handle_y,
void *user_data);
1509 float *handle_x,
float *handle_y,
void *user_data);
1516 float *node_x,
float *node_y,
void *user_data);
1525 int *inside,
int *inside_border,
int *near,
int *inside_source,
float *
dist,
1531 int inside_source,
void *user_data);
1542 int form_index,
int node_count_override,
1556#define menu_item_set_fake_accel(menu_item, keyval, mods) \
1559 GtkWidget *child = gtk_bin_get_child(GTK_BIN(menu_item)); \
1560 if(GTK_IS_ACCEL_LABEL(child)) \
1561 gtk_accel_label_set_accel(GTK_ACCEL_LABEL(child), keyval, mods); \
1569 const float pzx,
const float pzy);
static double dist(double x1, double y1, double x2, double y2)
const dt_colormatrix_t dt_aligned_pixel_t out
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
static size_t dt_round_size_sse(const size_t size)
#define dt_pixelpipe_cache_free_align(mem)
static const dt_aligned_pixel_simd_t value
static double dt_get_wtime(void)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
void dt_dev_coordinates_raw_norm_to_raw_abs(dt_develop_t *dev, float *points, size_t num_points)
int dt_dev_coordinates_image_abs_to_raw_abs(dt_develop_t *dev, float *points, size_t points_count)
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)
static void dt_draw_cross(cairo_t *cr, const float zoom_scale, const float x, const float y)
static void dt_draw_shape_lines(const dt_draw_dash_type_t dash_type, const gboolean source, cairo_t *cr, const int nb, const gboolean selected, const float zoom_scale, const float *points, const int points_count, const shape_draw_function_t *draw_shape_func, const cairo_line_cap_t line_cap)
Draw the lines of a mask shape.
void(* shape_draw_function_t)(cairo_t *cr, const float *points, const int points_count, const int nb, const gboolean border, const gboolean source)
#define DT_GUI_MOUSE_EFFECT_RADIUS
GdkModifierType dt_masks_get_accel_mods(dt_masks_interaction_t interaction)
static void dt_masks_gui_delta_to_image_abs(const dt_masks_form_gui_t *gui, float point[2])
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...
void apply_operation(struct dt_masks_form_group_t *pt, const dt_masks_state_t apply_state)
Apply a mask state operation on a group entry.
int dt_masks_group_render_roi(dt_iop_module_t *module, 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)
void dt_masks_gui_form_remove(dt_masks_form_t *form, dt_masks_form_gui_t *gui, int index)
static int dt_masks_gui_selected_segment_index(const dt_masks_form_gui_t *gui)
void dt_masks_blur_9x9(float *const src, float *const out, const int width, const int height, const float sigma)
void dt_masks_events_post_expose(struct dt_iop_module_t *module, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery)
dt_masks_type_t(* dt_masks_shape_buttons_type_f)(dt_iop_module_t *module, dt_masks_type_t type, gpointer user_data)
gboolean(* dt_masks_shape_buttons_start_f)(GtkWidget *button, dt_iop_module_t *module, dt_masks_type_t type, gpointer user_data)
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, int *inside_source, float *dist, void *user_data)
Shape-specific callback for inside/border/segment hit testing.
static int dt_masks_gui_selected_node_index(const dt_masks_form_gui_t *gui)
void dt_masks_gui_set_dragging(dt_masks_form_gui_t *gui)
void dt_masks_iop_update(struct dt_iop_module_t *module)
static int dt_masks_gui_selected_handle_index(const dt_masks_form_gui_t *gui)
void dt_masks_calculate_source_pos_origin(dt_masks_form_gui_t *gui, const float initial_xpos, const float initial_ypos, const float xpos, const float ypos, float *px, float *py, const int adding)
Compute preview-space source position for drawing the clone indicator.
int dt_masks_legacy_params(dt_develop_t *dev, void *params, const int old_version, const int new_version)
static float * dt_masks_dynbuf_buffer(dt_masks_dynbuf_t *a)
dt_masks_form_group_t * dt_masks_group_add_form(dt_masks_form_t *grp, dt_masks_form_t *form)
void dt_masks_remove_form(dt_develop_t *dev, dt_masks_form_t *form)
dt_masks_shape_button_index_t
@ 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
static 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)
void dt_masks_gui_form_create(dt_masks_form_t *form, dt_masks_form_gui_t *gui, int index, struct dt_iop_module_t *module)
void dt_masks_change_form_gui(dt_masks_form_t *newform)
int dt_masks_events_key_pressed(struct dt_iop_module_t *module, GdkEventKey *event)
static void dt_masks_dynbuf_add_2(dt_masks_dynbuf_t *a, float value1, float value2)
void dt_masks_creation_mode_quit(dt_masks_form_gui_t *gui)
Exit mask creation mode, restoring cursor visibility and resetting GUI state.
@ DT_MASKS_EDIT_RESTRICTED
gboolean dt_masks_gui_remove(struct dt_iop_module_t *module, dt_masks_form_t *form, dt_masks_form_gui_t *gui, const int parentid)
remove a mask shape or node form from the GUI. This function is used with a popupmenu "Delete" action...
gboolean dt_masks_node_is_cusp(const dt_masks_form_gui_points_t *gpt, const int 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 dt_masks_draw_source_preview(cairo_t *cr, const float zoom_scale, dt_masks_form_gui_t *gui, const float initial_xpos, const float initial_ypos, const float xpos, const float ypos, const int adding)
struct dt_iop_module_t * dt_masks_get_mask_manager(struct dt_develop_t *dev)
int dt_masks_form_change_opacity(dt_masks_form_t *form, int parentid, int up, const int flow)
int dt_masks_point_in_form_exact(const float *pts, int num_pts, const float *points, int points_start, int points_count)
Check whether any 2D point in pts[] lies inside the form points[].
void dt_masks_free_form(dt_masks_form_t *form)
uint64_t dt_masks_form_get_own_hash(uint64_t hash, const dt_masks_form_t *form)
void dt_masks_gui_reset_dragging(dt_masks_form_gui_t *gui)
static dt_masks_dynbuf_t * dt_masks_dynbuf_init(size_t size, const char *tag)
static void dt_masks_translate_source(dt_masks_form_t *form, const float delta_x, const float delta_y)
void dt_masks_iop_use_same_as(struct dt_iop_module_t *module, struct dt_iop_module_t *src)
void dt_masks_reset_form_gui(void)
void dt_masks_read_masks_history(dt_develop_t *dev, const int32_t imgid)
void dt_masks_gui_init(struct dt_develop_t *dev)
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.
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....
int dt_masks_events_button_released(struct dt_iop_module_t *module, double x, double y, int which, uint32_t state)
int dt_masks_events_mouse_moved(struct dt_iop_module_t *module, double x, double y, double pressure, int which)
int dt_masks_events_mouse_scrolled(struct dt_iop_module_t *module, double x, double y, int up, uint32_t state, int delta_y)
static float dt_masks_dynbuf_get(dt_masks_dynbuf_t *a, int offset)
static void dt_masks_translate_ctrl_node(float node[2], float ctrl1[2], float ctrl2[2], const float delta_x, const float delta_y)
gboolean dt_masks_is_anything_selected(const dt_masks_form_gui_t *mask_gui)
const dt_masks_functions_t dt_masks_functions_group
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_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.
@ DT_MASKS_STATE_DIFFERENCE
@ DT_MASKS_STATE_INTERSECTION
@ DT_MASKS_STATE_IS_COMBINE_OP
@ DT_MASKS_STATE_EXCLUSION
static float dt_masks_get_form_size_from_nodes(const GList *points)
void dt_masks_write_masks_history_item(const int32_t imgid, const int num, dt_masks_form_t *form)
gboolean dt_masks_gui_form_create_throttled(dt_masks_form_t *form, dt_masks_form_gui_t *gui, int index, struct dt_iop_module_t *module, float posx, float posy)
static float * dt_masks_dynbuf_reserve_n(dt_masks_dynbuf_t *a, const int n)
void dt_masks_gui_form_save_creation(dt_develop_t *dev, struct dt_iop_module_t *module, dt_masks_form_t *form, dt_masks_form_gui_t *gui)
Save the form creation right after a shape has been finished drawing.
void dt_masks_shape_buttons_deactivate_all(GtkWidget *active_button)
void dt_masks_select_form(struct dt_iop_module_t *module, dt_masks_form_t *sel)
Select or clear the current mask form, notifying the owning module if needed.
void dt_masks_calc_detail_mask(float *const src, float *const out, float *const tmp, const int width, const int height, const float threshold, const gboolean detail)
static int dt_masks_gui_selected_handle_border_index(const dt_masks_form_gui_t *gui)
GtkWidget * dt_masks_shape_buttons_create(const dt_masks_shape_buttons_config_t *config)
Build a synchronized toolbar for creating masks shapes.
float dt_masks_get_set_conf_value(dt_masks_form_t *form, char *feature, float new_value, float v_min, float v_max, dt_masks_increment_t increment, const int flow)
Change a numerical property of a mask shape, either by in/de-crementing the current value or setting ...
float dt_masks_form_get_interaction_value(dt_masks_form_group_t *form_group, dt_masks_interaction_t interaction)
void dt_masks_clear_form_gui(dt_develop_t *dev)
gboolean dt_masks_form_exit_creation(dt_iop_module_t *module, dt_masks_form_gui_t *gui)
void dt_masks_draw_source(cairo_t *cr, dt_masks_form_gui_t *gui, const int index, const int nb, 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 gboolean _dt_masks_dynbuf_growto(dt_masks_dynbuf_t *a, size_t size)
void dt_masks_blur_9x9_coeff(float *coeffs, const float sigma)
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.
@ DT_MASKS_IS_PRIMITIVE_SHAPE
@ DT_MASKS_IS_CLOSED_SHAPE
@ DT_MASKS_INTERACTION_OPACITY
@ DT_MASKS_INTERACTION_HARDNESS
@ DT_MASKS_INTERACTION_SIZE
@ DT_MASKS_INTERACTION_LAST
@ DT_MASKS_INTERACTION_UNDEF
@ DT_MASKS_INTERACTION_ROTATION
int dt_masks_group_index_from_formid(const dt_masks_form_t *group_form, int formid)
void _masks_gui_delete_node_callback(GtkWidget *menu, gpointer user_data)
static void dt_masks_gui_cursor_to_raw_norm(dt_develop_t *dev, const dt_masks_form_gui_t *gui, float point[2])
int dt_masks_center_view_on_form(struct dt_develop_t *dev, const struct dt_masks_form_t *form)
int dt_masks_version(void)
dt_masks_form_group_t * dt_masks_form_get_selected_group(const struct dt_masks_form_t *form, const struct dt_masks_form_gui_t *gui)
static float dt_masks_border_from_projected_handle(dt_develop_t *dev, const float node[2], const float projected_image_pos[2], const float scale_ref)
static gboolean dt_masks_center_of_gravity_from_points(const float *points, const int points_count, float center[2], float *area)
@ DT_MASKS_ELLIPSE_PROPORTIONAL
@ DT_MASKS_ELLIPSE_EQUIDISTANT
int dt_masks_events_mouse_leave(struct dt_iop_module_t *module)
void dt_masks_form_invalidate_gravity_center(struct dt_masks_form_t *form)
void(* dt_masks_shape_buttons_notify_f)(GtkWidget *button, dt_iop_module_t *module, dt_masks_type_t type, gpointer user_data)
static size_t dt_masks_dynbuf_position(dt_masks_dynbuf_t *a)
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....
void dt_masks_calc_rawdetail_mask(float *const src, float *const out, float *const tmp, const int width, const int height, const dt_aligned_pixel_t wb)
gboolean dt_masks_point_is_within_radius(const float px, const float py, const float cx, const float cy, const float radius)
Check if a point (px,py) is inside a radius from a center point (cx,cy)
static void dt_masks_preview_buffers_cleanup(dt_masks_preview_buffers_t *buffers)
dt_masks_source_pos_type_t
@ DT_MASKS_SOURCE_POS_RELATIVE_TEMP
@ DT_MASKS_SOURCE_POS_RELATIVE
@ DT_MASKS_SOURCE_POS_ABSOLUTE
static gboolean dt_masks_gui_was_anything_selected(const dt_masks_form_gui_t *gui)
int dt_masks_gui_confirm_delete_form_dialog(const char *form_name)
const dt_masks_functions_t dt_masks_functions_polygon
static gboolean dt_masks_gui_change_affects_selected_node_or_all(const dt_masks_form_gui_t *gui, const int index)
void dt_masks_cleanup_unused(dt_develop_t *dev)
Cleanup unused masks and refresh the current forms snapshot.
void dt_masks_group_ungroup(dt_masks_form_t *dest_grp, dt_masks_form_t *grp)
dt_masks_form_t * dt_masks_create(dt_masks_type_t type)
static gboolean dt_masks_gui_should_hit_test(dt_masks_form_gui_t *gui)
int dt_masks_events_button_pressed(struct dt_iop_module_t *module, double x, double y, double pressure, int which, int type, uint32_t state)
static void dt_masks_gui_delta_from_raw_anchor(dt_develop_t *dev, const dt_masks_form_gui_t *gui, const float anchor[2], float *delta_x, float *delta_y)
float dt_masks_apply_increment(float current, float amount, dt_masks_increment_t increment, int flow)
Apply a scroll increment to a scalar value.
static gboolean dt_masks_form_is_clone(const dt_masks_form_t *form)
float dt_masks_get_set_conf_value_with_toast(dt_masks_form_t *form, const char *feature, float amount, float v_min, float v_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.
int dt_masks_events_mouse_enter(struct dt_iop_module_t *module)
float dt_masks_rotate_with_anchor(dt_develop_t *dev, const float anchor[2], const float center[2], dt_masks_form_gui_t *gui)
Rotate a mask shape around its center. WARNING: gui->delta will be updated with the new position afte...
dt_masks_shape_buttons_flags_t
@ DT_MASKS_SHAPE_BUTTONS_GRADIENT
@ DT_MASKS_SHAPE_BUTTONS_NONE
@ DT_MASKS_SHAPE_BUTTONS_CIRCLE
@ DT_MASKS_SHAPE_BUTTONS_BRUSH
@ DT_MASKS_SHAPE_BUTTONS_ALL
@ DT_MASKS_SHAPE_BUTTONS_ELLIPSE
@ DT_MASKS_SHAPE_BUTTONS_POLYGON
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 void dt_masks_dynbuf_add_zeros(dt_masks_dynbuf_t *a, const int n)
gboolean dt_masks_creation_mode_enter(dt_iop_module_t *module, const dt_masks_type_t type)
Enter mask creation mode for a given shape type.
void dt_masks_form_move(dt_masks_form_t *grp, int formid, int up)
@ DT_MASKS_INCREMENT_SCALE
@ DT_MASKS_INCREMENT_OFFSET
@ DT_MASKS_INCREMENT_ABSOLUTE
dt_masks_pressure_sensitivity_t
@ DT_MASKS_PRESSURE_OPACITY_REL
@ DT_MASKS_PRESSURE_OPACITY_ABS
@ DT_MASKS_PRESSURE_BRUSHSIZE_REL
@ DT_MASKS_PRESSURE_HARDNESS_REL
@ DT_MASKS_PRESSURE_HARDNESS_ABS
int dt_masks_get_points_border(struct dt_develop_t *dev, dt_masks_form_t *form, float **points, int *points_count, float **border, int *border_count, int source, dt_iop_module_t *module)
float dt_masks_form_set_interaction_value(dt_masks_form_group_t *form_group, dt_masks_interaction_t interaction, float value, dt_masks_increment_t increment, int flow, struct dt_masks_form_gui_t *gui, struct dt_iop_module_t *module)
dt_masks_form_t * dt_masks_get_from_id_ext(GList *forms, int id)
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...
const dt_masks_functions_t dt_masks_functions_ellipse
const dt_masks_functions_t dt_masks_functions_circle
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
void dt_masks_append_form(dt_develop_t *dev, dt_masks_form_t *form)
void dt_masks_soft_reset_form_gui(dt_masks_form_gui_t *gui)
dt_masks_form_group_t * dt_masks_form_get_selected_group_live(const struct dt_masks_form_t *form, const struct dt_masks_form_gui_t *gui)
Return the currently selected group entry, resolving to the live form group when the GUI is operating...
void dt_masks_set_source_pos_initial_value(dt_masks_form_gui_t *gui, dt_masks_form_t *form)
Initialize the clone source position based on current GUI state.
dt_masks_edit_mode_t dt_masks_get_edit_mode(struct dt_iop_module_t *module)
void dt_masks_form_delete(struct dt_iop_module_t *module, dt_masks_form_t *grp, dt_masks_form_t *form)
void dt_masks_iop_value_changed_callback(GtkWidget *widget, struct dt_iop_module_t *module)
static int dt_masks_get_mask(const dt_iop_module_t *const module, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *const piece, dt_masks_form_t *const form, float **buffer, int *width, int *height, int *posx, int *posy)
GtkWidget * dt_masks_create_menu(dt_masks_form_gui_t *gui, dt_masks_form_t *form, const dt_masks_form_group_t *fpt, const float pzx, const float pzy)
void dt_masks_gui_cleanup(struct dt_develop_t *dev)
void dt_masks_init_form_gui(dt_masks_form_gui_t *gui)
static int dt_masks_get_mask_roi(const dt_iop_module_t *const module, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *const piece, dt_masks_form_t *const form, const dt_iop_roi_t *roi, float *buffer)
static void dt_masks_project_on_line(const float cursor[2], const float node[2], const float handle[2], float point[2])
dt_masks_gradient_states_t
@ DT_MASKS_GRADIENT_STATE_SIGMOIDAL
@ DT_MASKS_GRADIENT_STATE_LINEAR
void dt_masks_reset_show_masks_icons(void)
void dt_masks_extend_border(float *const mask, const int width, const int height, const int border)
void dt_masks_gui_form_test_create(dt_masks_form_t *form, dt_masks_form_gui_t *gui, struct dt_iop_module_t *module)
static int dt_masks_roundup(int num, int mult)
const dt_masks_functions_t dt_masks_functions_brush
static float * dt_masks_dynbuf_harvest(dt_masks_dynbuf_t *a)
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.
gboolean dt_masks_is_anything_hovered(const dt_masks_form_gui_t *mask_gui)
static void dt_masks_draw_preview_shape(cairo_t *cr, const float zoom_scale, const int num_points, float *points, const int points_count, float *border, const int border_count, void(*const *draw_shape)(cairo_t *cr, const float *points, const int points_count, const int nb, const gboolean border, const gboolean source), const cairo_line_cap_t shape_cap, const cairo_line_cap_t border_cap, const gboolean save_restore, const gboolean source)
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)
Shared selection logic for node/handle/segment hit testing.
int dt_masks_get_source_area(dt_iop_module_t *module, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, int *width, int *height, int *posx, int *posy)
void dt_masks_group_update_name(dt_iop_module_t *module)
dt_masks_form_t * dt_masks_get_visible_form(const struct dt_develop_t *dev)
void dt_masks_remove_node(struct dt_iop_module_t *module, dt_masks_form_t *form, int parentid, dt_masks_form_gui_t *gui, int index, int node_index)
uint64_t dt_masks_group_get_hash(uint64_t hash, dt_masks_form_t *form)
void dt_masks_set_edit_mode(struct dt_iop_module_t *module, dt_masks_edit_mode_t value)
void dt_group_events_post_expose(cairo_t *cr, float zoom_scale, dt_masks_form_t *form, dt_masks_form_gui_t *gui)
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.
int dt_masks_get_area(dt_iop_module_t *module, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *form, int *width, int *height, int *posx, int *posy)
static void dt_masks_dynbuf_set(dt_masks_dynbuf_t *a, int offset, float value)
dt_masks_form_group_t * dt_masks_form_group_from_parentid(int parentid, int formid)
Return the group entry for a (parent, form) pair.
dt_masks_form_t * dt_masks_create_ext(dt_masks_type_t type)
static 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)
int dt_masks_form_duplicate(dt_develop_t *dev, int formid)
void dt_masks_draw_path_seg_by_seg(cairo_t *cr, dt_masks_form_gui_t *gui, const int index, const float *points, const int points_count, const int node_count, const float zoom_scale)
static void dt_masks_gui_delta_to_raw_norm(dt_develop_t *dev, const dt_masks_form_gui_t *gui, float point[2])
void dt_masks_set_source_pos_initial_state(dt_masks_form_gui_t *gui, const uint32_t state)
Decide initial source positioning mode for clone masks.
static gboolean dt_masks_form_uses_spot_defaults(const dt_masks_form_t *form)
const dt_masks_functions_t dt_masks_functions_gradient
static void dt_masks_dynbuf_reset(dt_masks_dynbuf_t *a)
void dt_masks_iop_combo_populate(GtkWidget *w, void *module)
void dt_masks_form_update_gravity_center(struct dt_masks_form_t *form)
void dt_masks_set_visible_form(struct dt_develop_t *dev, dt_masks_form_t *form)
static void dt_masks_dynbuf_free(dt_masks_dynbuf_t *a)
static void dt_masks_reset_source(dt_masks_form_t *form)
static void dt_masks_set_ctrl_points(float ctrl1[2], float ctrl2[2], const float control_points[4])
gboolean dt_masks_form_get_gravity_center(const struct dt_masks_form_t *form, float center[2], float *area)
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)
float dt_aligned_pixel_t[4]
struct _GtkWidget GtkWidget
const float uint32_t state[4]
unsigned __int64 uint64_t
struct dt_develop_t * dev
Region of interest passed through the pixelpipe.
dt_masks_gradient_states_t state
float(* get_interaction_value)(const struct dt_masks_form_t *form, dt_masks_interaction_t interaction)
gboolean(* get_gravity_center)(const struct dt_masks_form_t *form, float center[2], float *area)
int(* button_pressed)(struct dt_iop_module_t *module, double x, double y, double pressure, int which, int type, uint32_t state, struct dt_masks_form_t *form, int parentid, struct dt_masks_form_gui_t *gui, int index)
int(* get_points)(struct dt_develop_t *dev, float x, float y, float radius_a, float radius_b, float rotation, float **points, int *points_count)
int(* button_released)(struct dt_iop_module_t *module, double x, double y, int which, uint32_t state, struct dt_masks_form_t *form, int parentid, struct dt_masks_form_gui_t *gui, int index)
int(* get_mask_roi)(const dt_iop_module_t *const fmodule, struct dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *const piece, struct dt_masks_form_t *const form, const dt_iop_roi_t *roi, float *buffer)
int(* get_source_area)(dt_iop_module_t *module, struct dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, struct dt_masks_form_t *form, int *width, int *height, int *posx, int *posy)
int(* key_pressed)(struct dt_iop_module_t *module, GdkEventKey *event, struct dt_masks_form_t *form, int parentid, struct dt_masks_form_gui_t *gui, int index)
int(* mouse_moved)(struct dt_iop_module_t *module, double x, double y, double pressure, int which, struct dt_masks_form_t *form, int parentid, struct dt_masks_form_gui_t *gui, int index)
void(* sanitize_config)(dt_masks_type_t type_flags)
void(* set_form_name)(struct dt_masks_form_t *const form, const size_t nb)
void(* duplicate_points)(struct dt_develop_t *const dev, struct dt_masks_form_t *base, struct dt_masks_form_t *dest)
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)
int(* update_hover)(struct dt_masks_form_t *form, struct dt_masks_form_gui_t *gui, int index)
float(* set_interaction_value)(struct dt_masks_form_t *form, dt_masks_interaction_t interaction, float value, dt_masks_increment_t increment, int flow, struct dt_masks_form_gui_t *gui, struct dt_iop_module_t *module)
int(* get_points_border)(struct dt_develop_t *dev, struct dt_masks_form_t *form, float **points, int *points_count, float **border, int *border_count, int source, const dt_iop_module_t *const module)
int(* get_area)(const dt_iop_module_t *const module, struct dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *const piece, struct dt_masks_form_t *const form, int *width, int *height, int *posx, int *posy)
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, int *inside_source, float *dist)
void(* draw_shape)(cairo_t *cr, const float *points, const int points_count, const int nb, const gboolean border, const gboolean source)
int(* mouse_scrolled)(struct dt_iop_module_t *module, double x, double y, int up, const int delta_y, uint32_t state, struct dt_masks_form_t *form, int parentid, struct dt_masks_form_gui_t *gui, int index, dt_masks_interaction_t interaction)
void(* initial_source_pos)(const float iwd, const float iht, float *x, float *y)
int(* get_mask)(const dt_iop_module_t *const module, struct dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *const piece, struct dt_masks_form_t *const form, float **buffer, int *width, int *height, int *posx, int *posy)
void(* post_expose)(cairo_t *cr, float zoom_scale, struct dt_masks_form_gui_t *gui, int index, int num_points)
void(* set_hint_message)(const struct dt_masks_form_gui_t *const gui, const struct dt_masks_form_t *const form, const int opacity, char *const __restrict__ msgbuf, const size_t msgbuf_len)
void(* init_ctrl_points)(struct dt_masks_form_t *form)
struct dt_masks_gui_center_point_t::@34 main
struct dt_masks_gui_center_point_t::@35 source
dt_masks_points_states_t state
dt_masks_ellipse_flags_t flags
dt_masks_points_states_t state