Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
masks.c File Reference
#include "system/macros.h"
#include "database/history_repository.h"
#include "system/target_clones.h"
#include "system/openmp.h"
#include "system/mem_alloc.h"
#include "common/hash.h"
#include "common/logging.h"
#include "common/times.h"
#include "common/glib_utils.h"
#include "system/dtpthread.h"
#include "caches/pixelpipe_cache_alloc.h"
#include "develop/masks.h"
#include "history/notify.h"
#include "develop/blend_gui.h"
#include "develop/masks_group.h"
#include "develop/masks/masks_functions.h"
#include "develop/masks/masks_touched.h"
#include "develop/develop.h"
#include "develop/supervisor.h"
#include "math/math.h"
#include "common/conf.h"
#include "develop/blend.h"
#include "develop/dev_pixelpipe.h"
#include "develop/imageop.h"
#include <stdint.h>
#include "detail.c"
+ Include dependency graph for masks.c:

Go to the source code of this file.

Data Structures

struct  _masks_read_ctx_t
 

Macros

#define MASKS_XSECT_BUCKET   4 /* px */
 

Typedefs

typedef struct _masks_read_ctx_t _masks_read_ctx_t
 

Functions

dt_masks_form_tdt_masks_dup_masks_form (const dt_masks_form_t *mask_form)
 Deep-copy a mask form, including its points list.
 
void dt_masks_form_gui_points_free (gpointer data)
 
void _check_id (dt_develop_t *dev, dt_masks_form_t *mask_form)
 
gchar * dt_masks_group_name_for_module (const dt_iop_module_t *module)
 
void _set_group_name_from_module (dt_iop_module_t *module, dt_masks_form_t *group_form)
 
dt_masks_form_t_group_create (dt_develop_t *develop, dt_iop_module_t *module, dt_masks_type_t group_type)
 
dt_masks_form_t_group_from_module (dt_develop_t *develop, dt_iop_module_t *module)
 
int dt_masks_form_duplicate (dt_develop_t *develop, int form_id)
 
int dt_masks_form_duplicate_in_group (dt_develop_t *develop, int group_id, int form_id)
 Duplicate a shape (dt_masks_form_duplicate) and, if group_id names a valid group, attach the duplicate as a new member of that group right away, inheriting the source form's group-entry state (operation) and opacity. If group_id is not a group (e.g. <= 0), the duplicate is left unattached in dev->forms, same as dt_masks_form_duplicate alone. Shared by every "Duplicate shape" UI entry point so the attach-and-inherit behavior does not get re-implemented per caller.
 
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)
 
gboolean dt_masks_skip_contains (const dt_masks_skip_range_t *skips, const int skip_count, const int index)
 
void dt_masks_points_bounding_box (const float *const points, const int num_points, int *width, int *height, int *posx, int *posy)
 
float * dt_masks_sample_grid_backtransform (struct dt_dev_pixelpipe_t *pipe, const double iop_order, const dt_masks_sample_grid_t *const grid, const char *const shape, const char *const form_name)
 
void dt_masks_sample_grid_interpolate (const float *const points, const dt_masks_sample_grid_t *const grid, float *const buffer, const int buf_width, const int buf_height, int *const endx, int *const endy)
 
dt_masks_raster_result_t dt_masks_get_area (dt_iop_module_t *module, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece, dt_masks_form_t *mask_form, int *area_width, int *area_height, int *area_pos_x, int *area_pos_y)
 
dt_masks_raster_result_t 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 *mask_form, int *area_width, int *area_height, int *area_pos_x, int *area_pos_y)
 
int dt_masks_version (void)
 
static int dt_masks_legacy_params_v1_to_v2 (dt_develop_t *develop, void *params)
 
static void dt_masks_legacy_params_v2_to_v3_transform (const dt_image_t *image, float *coords)
 
static void dt_masks_legacy_params_v2_to_v3_transform_only_rescale (const dt_image_t *image, float *coords, size_t coords_count)
 
static int dt_masks_legacy_params_v2_to_v3 (dt_develop_t *develop, void *params)
 
static int dt_masks_legacy_params_v3_to_v4 (dt_develop_t *develop, void *params)
 
static int dt_masks_legacy_params_v4_to_v5 (dt_develop_t *develop, void *params)
 
static int dt_masks_legacy_params_v5_to_v6 (dt_develop_t *develop, void *params)
 
int dt_masks_legacy_params (dt_develop_t *develop, void *params, const int old_version, const int new_version)
 
dt_masks_form_tdt_masks_create (dt_masks_type_t type)
 
dt_masks_form_tdt_masks_create_ext (dt_develop_t *dev, dt_masks_type_t type)
 
dt_masks_form_tdt_masks_get_from_id_ext (GList *form_list, int form_id)
 
dt_masks_form_tdt_masks_get_from_id (dt_develop_t *develop, int form_id)
 
dt_iop_module_tdt_masks_get_mask_manager (dt_develop_t *develop)
 
static void _masks_fill_used_forms (GList *forms_list, const int form_id, int *used_form_ids, const int used_count)
 
int dt_masks_copy_used_forms_for_module (dt_develop_t *develop_dest, dt_develop_t *develop_src, const dt_iop_module_t *source_module)
 
static void _read_mask_row (void *user_data, const int history_num, const int form_id, const int form, const char *name, const int version, const void *points, const int points_len, const int point_count, const void *source, const int source_len)
 
void dt_masks_read_masks_history (dt_develop_t *develop, const int32_t image_id)
 
void dt_masks_write_masks_history_item (const int32_t image_id, const int history_num, dt_masks_form_t *mask_form)
 
void dt_masks_free_form (dt_masks_form_t *mask_form)
 
dt_masks_edit_mode_t dt_masks_get_edit_mode (struct dt_iop_module_t *module)
 
void dt_masks_iop_use_same_as (dt_iop_module_t *module, dt_iop_module_t *source_module)
 
void dt_masks_form_delete (dt_develop_t *dev, struct dt_iop_module_t *module, dt_masks_form_t *group_form, dt_masks_form_t *mask_form)
 
void dt_masks_form_update_gravity_center (dt_develop_t *dev, dt_masks_form_t *mask_form)
 
void dt_masks_form_invalidate_gravity_center (dt_masks_form_t *mask_form)
 
void dt_masks_duplicate_points (const dt_masks_form_t *base_form, dt_masks_form_t *dest_form, size_t node_size)
 Duplicate a points list for a mask using a fixed node size.
 
void dt_masks_form_move (dt_masks_form_t *group_form, int form_id, int move_up)
 
int _find_in_group (dt_develop_t *dev, dt_masks_form_t *group_form, int form_id)
 
uint64_t dt_masks_group_get_hash_ext (uint64_t hash, GList *masks, dt_masks_form_t *mask_form)
 
uint64_t dt_masks_form_get_own_hash (uint64_t hash, GList *masks, const dt_masks_form_t *mask_form)
 
static void _cleanup_unused_recurs (GList *form_list, int form_id, GHashTable *used_form_ids)
 
static int _masks_cleanup_unused (dt_develop_t *dev, GList **forms_list, GList *history_list, const int history_end)
 
static void _masks_cleanup_unused_from_list (dt_develop_t *dev, GList *history_list)
 Remove unused mask forms from a history list, preserving undo safety.
 
void dt_masks_cleanup_unused (dt_develop_t *develop)
 Cleanup unused masks and refresh the current forms snapshot.
 
dt_masks_raster_result_t 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)
 
dt_masks_raster_result_t 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, dt_iop_roi_t *touched)
 
gboolean dt_masks_form_get_info (const dt_masks_form_t *form, dt_masks_form_info_t *out)
 
static void _member_from_entry (dt_masks_member_t *const out, const dt_masks_form_group_t *const entry, const guint index)
 
static dt_masks_form_group_t_resolve_member (dt_develop_t *dev, const int group_id, const int formid, const gboolean touch, guint *const out_index)
 
guint dt_masks_group_copy_members (const dt_masks_form_t *group, dt_masks_member_t *out, const guint out_max)
 
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, group, or "unknown".
 
dt_masks_result_t dt_masks_group_set_member_operation (dt_develop_t *dev, const int group_id, const int formid, const dt_masks_state_t operation, dt_masks_member_t *out)
 Set a group member's combination operator, or toggle its inversion.
 
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.
 
static dt_masks_form_t_find_holder (dt_develop_t *dev, dt_masks_form_t *grp, const int formid, const int max_depth)
 
int dt_masks_group_find_holder (dt_develop_t *dev, const int formid)
 Which group references formid, searching every group in dev->forms depth-first.
 
guint dt_masks_group_list (dt_develop_t *dev, dt_masks_form_info_t *out, const guint out_max)
 Describe every group of the live list, in dev->forms order, into caller storage.
 
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.
 
static gboolean _group_contains_recurs (dt_develop_t *dev, const int container_id, const int needle_id)
 
dt_masks_result_t dt_masks_group_contains (dt_develop_t *dev, const int container_id, const int needle_id)
 Whether container_id holds needle_id, at any depth (and trivially when they are the same id).
 
static gboolean _group_covers_recurs (dt_develop_t *dev, const int group_id, const int target_id, gboolean *has_shapes)
 
dt_masks_result_t dt_masks_group_covers_shapes (dt_develop_t *dev, const int group_id, const int target_id, gboolean *has_shapes)
 Whether every shape group_id ultimately holds is also held by target_id.
 
static gboolean _first_use_recurs (dt_develop_t *dev, const int group_id, const int formid, int *holder_id, guint *index, const dt_masks_form_t **holder)
 
dt_masks_result_t dt_masks_group_first_use (dt_develop_t *dev, const int root_id, const int formid, int *holder_id, guint *index, char *holder_name, const size_t holder_name_size)
 Where the mask rooted at root_id FIRST applies formid.
 
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.
 

Variables

static int form_id_seed = 0
 

Macro Definition Documentation

◆ MASKS_XSECT_BUCKET

#define MASKS_XSECT_BUCKET   4 /* px */

Definition at line 301 of file masks.c.

Typedef Documentation

◆ _masks_read_ctx_t

Function Documentation

◆ _check_id()

void _check_id ( dt_develop_t dev,
dt_masks_form_t mask_form 
)

◆ _cleanup_unused_recurs()

static void _cleanup_unused_recurs ( GList *  form_list,
int  form_id,
GHashTable *  used_form_ids 
)
static

◆ _find_holder()

static dt_masks_form_t * _find_holder ( dt_develop_t dev,
dt_masks_form_t grp,
const int  formid,
const int  max_depth 
)
static

◆ _find_in_group()

◆ _first_use_recurs()

static gboolean _first_use_recurs ( dt_develop_t dev,
const int  group_id,
const int  formid,
int *  holder_id,
guint *  index,
const dt_masks_form_t **  holder 
)
static

◆ _group_contains_recurs()

static gboolean _group_contains_recurs ( dt_develop_t dev,
const int  container_id,
const int  needle_id 
)
static

◆ _group_covers_recurs()

static gboolean _group_covers_recurs ( dt_develop_t dev,
const int  group_id,
const int  target_id,
gboolean *  has_shapes 
)
static

◆ _group_create()

◆ _group_from_module()

◆ _masks_cleanup_unused()

static int _masks_cleanup_unused ( dt_develop_t dev,
GList **  forms_list,
GList *  history_list,
const int  history_end 
)
static

◆ _masks_cleanup_unused_from_list()

static void _masks_cleanup_unused_from_list ( dt_develop_t dev,
GList *  history_list 
)
static

Remove unused mask forms from a history list, preserving undo safety.

Caveat: if multiple history entries reference masks, some unused masks may remain. This is intentional so users can still jump back in history.

Definition at line 1563 of file masks.c.

References _masks_cleanup_unused(), dt_dev_history_item_t::forms, and IS_NULL_PTR.

Referenced by dt_masks_cleanup_unused().

◆ _masks_fill_used_forms()

static void _masks_fill_used_forms ( GList *  forms_list,
const int  form_id,
int *  used_form_ids,
const int  used_count 
)
static

◆ _member_from_entry()

◆ _read_mask_row()

static void _read_mask_row ( void user_data,
const int  history_num,
const int  form_id,
const int  form,
const char *  name,
const int  version,
const void points,
const int  points_len,
const int  point_count,
const void source,
const int  source_len 
)
static

◆ _resolve_member()

static dt_masks_form_group_t * _resolve_member ( dt_develop_t dev,
const int  group_id,
const int  formid,
const gboolean  touch,
guint *const  out_index 
)
static

◆ _set_group_name_from_module()

void _set_group_name_from_module ( dt_iop_module_t module,
dt_masks_form_t group_form 
)

Definition at line 161 of file masks.c.

References dt_free, dt_masks_group_name_for_module(), IS_NULL_PTR, and dt_masks_form_t::name.

Referenced by _group_create().

◆ dt_masks_cleanup_unused()

void dt_masks_cleanup_unused ( dt_develop_t develop)

Cleanup unused masks and refresh the current forms snapshot.

Assumption: caller already decided to drop unused forms (non-reversible).

Definition at line 1587 of file masks.c.

References _masks_cleanup_unused_from_list(), dt_dev_get_history_end_ext(), dt_masks_change_form_gui(), dt_masks_replace_current_forms(), dt_pthread_rwlock_unlock(), dt_pthread_rwlock_wrlock(), dt_dev_history_item_t::forms, dt_develop_t::history, and dt_develop_t::history_mutex.

Referenced by _tree_delete_unused().

◆ dt_masks_copy_used_forms_for_module()

◆ dt_masks_create()

◆ dt_masks_create_ext()

dt_masks_form_t * dt_masks_create_ext ( dt_develop_t dev,
dt_masks_type_t  type 
)

◆ dt_masks_dup_masks_form()

dt_masks_form_t * dt_masks_dup_masks_form ( const dt_masks_form_t mask_form)

Deep-copy a mask form, including its points list.

Caveats:

  • The caller owns the returned form and must free it.
  • Point payloads are copied byte-for-byte using the type's point struct size.

Definition at line 77 of file masks.c.

References dt_atomic_set_int(), dt_masks_form_t::functions, IS_NULL_PTR, dt_masks_functions_t::point_struct_size, dt_masks_form_t::points, and dt_masks_form_t::refcount.

Referenced by dt_masks_copy_used_forms_for_module(), and dt_masks_cow_touch().

◆ dt_masks_duplicate_points()

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.

The destination list is appended to, mirroring the previous per-mask implementations.

Definition at line 1332 of file masks.c.

References IS_NULL_PTR, and dt_masks_form_t::points.

Referenced by _brush_duplicate_points(), _circle_duplicate_points(), _ellipse_duplicate_points(), _gradient_duplicate_points(), and _polygon_duplicate_points().

◆ dt_masks_form_delete()

◆ dt_masks_form_duplicate()

◆ dt_masks_form_duplicate_in_group()

int dt_masks_form_duplicate_in_group ( dt_develop_t dev,
int  group_id,
int  form_id 
)

Duplicate a shape (dt_masks_form_duplicate) and, if group_id names a valid group, attach the duplicate as a new member of that group right away, inheriting the source form's group-entry state (operation) and opacity. If group_id is not a group (e.g. <= 0), the duplicate is left unattached in dev->forms, same as dt_masks_form_duplicate alone. Shared by every "Duplicate shape" UI entry point so the attach-and-inherit behavior does not get re-implemented per caller.

Returns
the new form's id, or <= 0 on failure.

Definition at line 210 of file masks.c.

References dt_masks_cow_touch(), dt_masks_form_duplicate(), dt_masks_get_from_id(), DT_MASKS_GROUP, dt_masks_group_add_form(), dt_masks_form_group_t::formid, IS_NULL_PTR, dt_masks_form_group_t::opacity, dt_masks_form_t::points, dt_masks_form_group_t::state, and dt_masks_form_t::type.

Referenced by _blendop_masks_group_duplicate_callback(), and _tree_duplicate_shape().

◆ dt_masks_form_get_info()

◆ dt_masks_form_get_own_hash()

uint64_t dt_masks_form_get_own_hash ( uint64_t  hash,
GList *  masks,
const dt_masks_form_t form 
)

Same as dt_masks_group_get_hash_ext(), but hashes only the form's own content: for a group, member references (id/state/opacity) instead of recursing into each member's content. Meant for walking a flat list where every member already gets its own top-level call.

Definition at line 1439 of file masks.c.

References dt_hash(), dt_masks_get_from_id_ext(), DT_MASKS_GROUP, dt_masks_form_t::formid, dt_masks_form_group_t::formid, dt_masks_form_t::functions, IS_NULL_PTR, dt_masks_form_group_t::opacity, dt_masks_functions_t::point_struct_size, dt_masks_form_t::points, dt_masks_form_t::source, dt_masks_form_group_t::state, dt_masks_form_t::type, and dt_masks_form_t::version.

Referenced by _group_prefix_hash(), and dt_dev_masks_update_hash().

◆ dt_masks_form_gui_points_free()

◆ dt_masks_form_invalidate_gravity_center()

void dt_masks_form_invalidate_gravity_center ( struct dt_masks_form_t form)

Marks gravity_center/area stale instead of recomputing them right away. Use for bulk paths (loading history, undo/redo) that swap in many forms at once; the one GUI hit-testing read site recomputes lazily on first actual use.

Definition at line 1322 of file masks.c.

References FALSE, dt_masks_form_t::gravity_center_valid, and IS_NULL_PTR.

Referenced by dt_masks_replace_current_forms().

◆ dt_masks_form_move()

void dt_masks_form_move ( dt_masks_form_t group_form,
int  form_id,
int  move_up 
)

◆ dt_masks_form_update_gravity_center()

◆ dt_masks_free_form()

void dt_masks_free_form ( dt_masks_form_t mask_form)

◆ dt_masks_get_area()

dt_masks_raster_result_t 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 
)

get the rectangle which include the form and his border

Definition at line 450 of file masks.c.

References DT_MASKS_RASTER_ERROR, dt_masks_form_t::functions, and dt_masks_functions_t::get_area.

Referenced by __attribute__(), _area_and_mask_always_write_their_out_parameters(), rt_compute_roi_in(), and rt_masks_form_is_in_roi().

◆ dt_masks_get_edit_mode()

dt_masks_edit_mode_t dt_masks_get_edit_mode ( struct dt_iop_module_t module)

Definition at line 1148 of file masks.c.

References dt_iop_module_t::dev, DT_MASKS_EDIT_OFF, and IS_NULL_PTR.

Referenced by dt_dev_history_undo_end_record_locked().

◆ dt_masks_get_from_id()

dt_masks_form_t * dt_masks_get_from_id ( dt_develop_t dev,
int  id 
)

returns a form with formid == id from dev->forms

Definition at line 909 of file masks.c.

References dt_masks_get_from_id_ext(), dt_pthread_rwlock_rdlock(), dt_pthread_rwlock_unlock(), dt_develop_t::forms, and dt_develop_t::masks_mutex.

Referenced by _blendop_masks_all_delete(), _blendop_masks_all_name_edited(), _blendop_masks_all_selection_changed(), _blendop_masks_all_toggled(), _blendop_masks_group_button_pressed(), _blendop_masks_group_create(), _blendop_masks_group_ctx_menu(), _blendop_masks_group_delete(), _blendop_masks_group_from_module(), _blendop_masks_group_move_callback(), _blendop_masks_group_selection_changed(), _blendop_masks_group_tree_append(), _blendop_masks_group_unlink(), _blendop_masks_group_update_row(), _blendop_masks_is_group_with_shapes(), _blendop_masks_is_single_group_wrapper(), _blendop_masks_show_and_edit(), _brush_add_node_callback(), _brush_events_button_released(), _brush_reset_round_node_callback(), _brush_switch_node_callback(), _develop_blend_init_drawn_mask(), _dt_masks_events_get_dispatch_form(), _dt_masks_events_group_update_selection(), _edit_masks(), _find_holder(), _find_in_group(), _first_use_recurs(), _form_can_join_group(), _group_contains_recurs(), _group_covers_recurs(), _group_from_module(), _group_get_child_at(), _group_get_gravity_center(), _group_get_mask(), _groups_naming_form(), _gui_reset_callback(), _masks_draw_creation_session_forms(), _masks_gui_delete_node_callback(), _masks_gui_resolve_selected_shape(), _masks_move_up_down_callback(), _masks_remove_or_delete_finish(), _masks_remove_shape(), _menu_add_exist(), _modchooser_run(), _module_create_own_mask(), _outline_nodes(), _polygon_add_node_callback(), _polygon_events_post_expose(), _polygon_reset_round_node_callback(), _polygon_switch_node_callback(), _process(), _reset_form_creation(), _resolve_member(), _resynch_params(), _set_hinter_message(), _shape_is_being_added(), _shape_manager_handler_callback(), _shape_manager_list_recurs(), _shape_manager_update_item(), _time_hit_test(), _tooltip_add_text(), _tooltip_assign_text(), _tree_add_exist(), _tree_add_to_group(), _tree_apply_operation(), _tree_cell_edited(), _tree_context_menu(), _tree_delete_shape(), _tree_format_form_usage_label(), _tree_group(), _tree_movedown(), _tree_moveup(), _tree_row_action(), _tree_row_add_to_group(), _tree_row_assign_to_modules(), _tree_selection_change(), _tree_store_add_forms(), _update_foreach(), dt_dev_add_history_item_ext(), dt_develop_blend_get_mask_usage(), dt_iop_gui_blend_masks_update(), dt_iop_gui_blend_set_drawn_mask_group(), dt_masks_copy_used_forms_for_module(), dt_masks_create_menu(), dt_masks_events_key_pressed(), dt_masks_form_delete(), dt_masks_form_duplicate(), dt_masks_form_duplicate_in_group(), dt_masks_form_exit_creation(), dt_masks_form_get_interaction_value(), dt_masks_form_group_from_parentid(), dt_masks_form_set_interaction_value(), dt_masks_group_set_name_from_module(), dt_masks_group_ungroup(), dt_masks_gui_form_test_create(), dt_masks_iop_use_same_as(), dt_masks_set_edit_mode(), gui_focus(), gui_update(), modify_roi_in(), post_history_commit(), rt_compute_roi_in(), rt_display_selected_shapes_lbl(), rt_edit_masks_callback(), rt_extend_roi_in_for_clone(), rt_extend_roi_in_from_source_clones(), rt_get_mask_point_group(), rt_menu_select_algorithm_callback(), rt_shape_is_being_added(), rt_show_forms_for_current_scale(), and rt_show_hide_controls().

◆ dt_masks_get_from_id_ext()

◆ dt_masks_get_mask()

dt_masks_raster_result_t 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 
)

◆ dt_masks_get_mask_manager()

dt_iop_module_t * dt_masks_get_mask_manager ( struct dt_develop_t dev)

return the mask manager module instance if present

Definition at line 917 of file masks.c.

References dt_develop_t::iop.

◆ dt_masks_get_mask_roi()

◆ dt_masks_get_points_border()

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 
)

◆ dt_masks_get_source_area()

dt_masks_raster_result_t 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 mask_form,
int *  area_width,
int *  area_height,
int *  area_pos_x,
int *  area_pos_y 
)

◆ dt_masks_group_contains()

dt_masks_result_t dt_masks_group_contains ( struct dt_develop_t dev,
int  container_id,
int  needle_id 
)

Whether container_id holds needle_id, at any depth (and trivially when they are the same id).

The question every caller wiring one group into another has to ask first: closing a cycle in the membership graph makes every walk over it non-terminating, the tree builds included.

Returns
DT_MASKS_OK when it does, DT_MASKS_NOT_FOUND when it does not, DT_MASKS_INVALID for a NULL dev. A container_id that names no group, or names a shape, is NOT_FOUND.

Definition at line 1942 of file masks.c.

References _group_contains_recurs(), DT_MASKS_INVALID, DT_MASKS_NOT_FOUND, DT_MASKS_OK, and IS_NULL_PTR.

Referenced by _form_can_join_group(), _modchooser_run(), and _tooltip_add_text().

◆ dt_masks_group_copy_members()

◆ dt_masks_group_covers_shapes()

dt_masks_result_t dt_masks_group_covers_shapes ( struct dt_develop_t dev,
int  group_id,
int  target_id,
gboolean *  has_shapes 
)

Whether every shape group_id ultimately holds is also held by target_id.

Leaf by leaf and at any depth on both sides, so it answers for a group of groups too. What it means is that nesting group_id into target_id would add no shape the target does not already apply – NOT that it would change nothing, which is a different question the combine operators answer (a shape applied twice in difference or exclusion does change the mask).

Parameters
has_shapes(may be NULL) set to TRUE as soon as a leaf shape is met, so a caller can tell "all covered" from "there was nothing in it to cover".
Returns
DT_MASKS_OK when every leaf is covered, DT_MASKS_NOT_FOUND when one is not, DT_MASKS_INVALID for a NULL dev.

Definition at line 1973 of file masks.c.

References _group_covers_recurs(), DT_MASKS_INVALID, DT_MASKS_NOT_FOUND, DT_MASKS_OK, FALSE, and IS_NULL_PTR.

Referenced by _form_can_join_group().

◆ dt_masks_group_find_holder()

int dt_masks_group_find_holder ( struct dt_develop_t dev,
int  formid 
)

Which group references formid, searching every group in dev->forms depth-first.

A shape's own dt_masks_form_t does not record who holds it, and the row's parentid records where it was AUTHORED, not where it currently lives – so a caller holding only a shape id, as the shape manager's tree does when it lists shapes at top level, has to search. Returns the first holder found; a shape referenced by two groups has no single answer, and the caller wanting a specific one already knows which.

Returns
the holding group's formid, or 0 for none (and for a NULL dev or a zero formid).

Definition at line 1878 of file masks.c.

References _find_holder(), dt_masks_form_t::formid, and IS_NULL_PTR.

Referenced by _find_holder_names_the_group_that_references_a_shape(), and _tree_context_menu().

◆ dt_masks_group_first_use()

dt_masks_result_t dt_masks_group_first_use ( struct dt_develop_t dev,
int  root_id,
int  formid,
int *  holder_id,
guint *  index,
char *  holder_name,
size_t  holder_name_size 
)

Where the mask rooted at root_id FIRST applies formid.

Walked in compositing order: a group's members in their own order, descending into a member group at the position that group sits at. A shape can legitimately appear more than once in one mask – union and intersection are idempotent, difference and exclusion are not – so this answers which application the later ones are read against, not which ones are redundant.

Parameters
holder_id(may be NULL) the group directly holding that first use.
index(may be NULL) its position inside that group, i.e. its compositing rank.
holder_name(may be NULL) copied, not borrowed, like dt_masks_form_get_info()'s name.
Returns
DT_MASKS_OK when found, DT_MASKS_NOT_FOUND when the mask does not apply it at all, DT_MASKS_INVALID for a NULL dev.

Definition at line 2013 of file masks.c.

References _first_use_recurs(), DT_MASKS_INVALID, DT_MASKS_NOT_FOUND, DT_MASKS_OK, IS_NULL_PTR, and dt_masks_form_t::name.

Referenced by _modchooser_run(), and _tree_append_row().

◆ dt_masks_group_get_hash_ext()

uint64_t dt_masks_group_get_hash_ext ( uint64_t  hash,
GList *  masks,
dt_masks_form_t form 
)

Hash a group's full content (recursing into members). Children are resolved from the given forms list — pass the same list the group came from (live dev->forms or a snapshot), so the hash describes one coherent state instead of mixing the group with foreign children.

Definition at line 1401 of file masks.c.

References dt_hash(), dt_masks_get_from_id_ext(), DT_MASKS_GROUP, dt_masks_group_get_hash_ext(), dt_masks_form_t::formid, dt_masks_form_group_t::formid, dt_masks_form_t::functions, IS_NULL_PTR, dt_masks_form_group_t::opacity, dt_masks_functions_t::point_struct_size, dt_masks_form_t::points, dt_masks_form_t::source, dt_masks_form_group_t::state, dt_masks_form_t::type, and dt_masks_form_t::version.

Referenced by _hm_history_masks_match(), dt_iop_compute_blendop_hash(), and dt_masks_group_get_hash_ext().

◆ dt_masks_group_get_member()

dt_masks_result_t dt_masks_group_get_member ( struct dt_develop_t dev,
int  group_id,
int  formid,
dt_masks_member_t out 
)

Read one group member by identity.

The pointer-free counterpart to dt_masks_group_copy_members() when only one row is wanted, and the read half of the read-modify-write a caller needs when it can only express a change as an increment on the current value.

Deliberately does NOT copy-on-write. Touching a group on a plain read would clone a shared group every time the GUI asks what a shape's opacity is – copy-on-write is a writer's obligation.

Parameters
out(may be NULL, though then the call only answers "does this row exist") receives the row, including its index.
Returns
OK, or NOT_FOUND for no such group, a form that is not a group, or no such member.

Definition at line 1909 of file masks.c.

References _member_from_entry(), _resolve_member(), DT_MASKS_INVALID, DT_MASKS_NOT_FOUND, DT_MASKS_OK, FALSE, IS_NULL_PTR, and out.

Referenced by _a_shared_group_is_cloned_before_its_opacity_changes(), _get_member_reads_a_row_by_identity(), _modchooser_run(), dt_masks_form_change_opacity(), dt_masks_form_get_interaction_value(), dt_masks_form_set_interaction_value(), and dt_masks_gui_populate_interaction_sliders().

◆ dt_masks_group_list()

guint dt_masks_group_list ( struct dt_develop_t dev,
dt_masks_form_info_t out,
guint  out_max 
)

Describe every group of the live list, in dev->forms order, into caller storage.

The catalogue a caller offers a destination group from – the shape manager's "Attach to the group" – BY VALUE, so the caller neither walks dev->forms nor holds a pointer into a refcounted form. Retouch and spot groups come too; a caller that must not offer them filters on dt_masks_form_info_t.is_retouch.

Takes the masks lock for reading across the walk.

Parameters
outcaller storage, or NULL to query the count only.
out_maxcapacity of out in elements.
Returns
the TOTAL number of groups, which may exceed out_max; exactly MIN(total, out_max) elements are written. 0 for a NULL dev.

Definition at line 1887 of file masks.c.

References dt_masks_form_get_info(), DT_MASKS_GROUP, dt_pthread_rwlock_rdlock(), dt_pthread_rwlock_unlock(), dt_develop_t::forms, IS_NULL_PTR, dt_develop_t::masks_mutex, out, and dt_masks_form_t::type.

Referenced by _menu_append_join_group(), and _tree_group().

◆ dt_masks_group_name_for_module()

◆ dt_masks_group_set_member_opacity()

dt_masks_result_t dt_masks_group_set_member_opacity ( struct dt_develop_t dev,
int  group_id,
int  formid,
float  opacity,
dt_masks_member_t out 
)

Set a group member's opacity.

Same id-keyed contract as dt_masks_group_set_member_operation() above, and it exists for a failure this codebase actually shipped. Opacity used to be written through a resolved dt_masks_form_group_t*, which CANNOT copy-on-write: it has the row but not the group that owns it, so every caller had to touch the group itself. Callers compensated by touching the parent once, when a context menu was built, and then mutating the row in place for the whole interaction – but the opacity slider commits history on every step, and each commit re-snapshots dev->forms and shares the group again. The up-front touch was consumed by the first commit, so from the second step on, every drag rewrote the opacity inside history snapshots that were supposed to be frozen, and undo could not restore it. Taking ids instead of a row makes that arrangement unrepresentable.

Parameters
opacityclamped to [0;1]. NaN is INVALID rather than clamped – see the implementation.
out(may be NULL) receives the row AFTER the change, including the clamped opacity, so a caller driving a slider can show what was actually stored.
Returns
OK when the value changed, UNCHANGED when the row already held it (skip the history commit), NOT_FOUND for no such group or member, INVALID for a NULL dev or a NaN.

Definition at line 2029 of file masks.c.

References _member_from_entry(), _resolve_member(), CLAMPF, DT_MASKS_INVALID, DT_MASKS_NOT_FOUND, DT_MASKS_OK, DT_MASKS_UNCHANGED, IS_NULL_PTR, dt_masks_form_group_t::opacity, out, and TRUE.

Referenced by _a_shared_group_is_cloned_before_its_opacity_changes(), _set_opacity_clamps_and_reports_what_it_stored(), _set_opacity_refuses_a_nan_rather_than_clamping_it(), dt_masks_form_change_opacity(), dt_masks_form_set_interaction_value(), and rt_masks_form_change_opacity().

◆ dt_masks_group_set_member_operation()

dt_masks_result_t dt_masks_group_set_member_operation ( struct dt_develop_t dev,
int  group_id,
int  formid,
dt_masks_state_t  operation,
dt_masks_member_t out 
)

Set a group member's combination operator, or toggle its inversion.

Takes the live list, and owns the copy-on-write itself – which is the entire reason this exists. A group is refcounted and shared with every history snapshot that references it, so a caller must touch the group before mutating a row. Doing that correctly ALSO means the caller may not resolve the row first: cloning a group clones its membership blocks too, so an entry pointer taken before the touch belongs to the abandoned copy and the mutation lands nowhere. An id-keyed signature is the only shape that cannot get this wrong, which is why it takes ids and hands the result back rather than letting anyone hold a row.

Parameters
operationDT_MASKS_STATE_INVERSE toggles inversion; any of UNION / INTERSECTION / DIFFERENCE / EXCLUSION replaces the combination operator. Anything else is INVALID.
out(may be NULL) receives the row AFTER the change, including its index – the caller usually needs both to refresh its own view, and this is the only pointer-free way to get them.
Returns
OK when the row changed, UNCHANGED when it already held that state (the caller must then skip its history commit, or every no-op click writes an undo step), NOT_FOUND for no such group or no such member, INVALID for a bad operation.

Definition at line 1785 of file masks.c.

References _member_from_entry(), _resolve_member(), DT_MASKS_INVALID, DT_MASKS_NOT_FOUND, DT_MASKS_OK, DT_MASKS_STATE_INVERSE, DT_MASKS_STATE_IS_COMBINE_OP, DT_MASKS_UNCHANGED, IS_NULL_PTR, out, dt_masks_form_group_t::state, and TRUE.

Referenced by _blendop_masks_group_operation_callback(), _inverse_toggles_and_leaves_the_operator_alone(), _set_operation_rejects_what_it_cannot_do(), _set_operation_replaces_the_combine_op(), _setting_the_state_it_already_has_is_unchanged(), and _tree_apply_operation().

◆ dt_masks_group_set_name_from_module()

dt_masks_result_t dt_masks_group_set_name_from_module ( struct dt_develop_t dev,
int  group_id,
struct dt_iop_module_t module 
)

Name a group after the module that renders it, by id.

The write half of dt_masks_group_name_for_module(), and id-keyed for the reason the whole write API is: a group is refcounted and shared with every history snapshot referencing it, so a rename is a mutation that must copy on write. A caller holding the form cannot do that correctly – cloning replaces the object wholesale, and the pointer it wrote through belongs to the copy that was just abandoned.

Returns
OK when the name changed, UNCHANGED when the group already carried it, NOT_FOUND for no such group or an id naming a shape, INVALID for a NULL dev or module.

Definition at line 1808 of file masks.c.

References dt_free, dt_masks_cow_touch(), dt_masks_get_from_id(), DT_MASKS_GROUP, dt_masks_group_name_for_module(), DT_MASKS_INVALID, DT_MASKS_NOT_FOUND, DT_MASKS_OK, DT_MASKS_UNCHANGED, IS_NULL_PTR, name, dt_masks_form_t::name, and dt_masks_form_t::type.

Referenced by _blendop_masks_group_create(), _module_create_own_mask(), and dt_masks_group_update_name().

◆ dt_masks_iop_use_same_as()

◆ dt_masks_legacy_params()

int dt_masks_legacy_params ( dt_develop_t develop,
void params,
const int  old_version,
const int  new_version 
)

◆ dt_masks_legacy_params_v1_to_v2()

◆ dt_masks_legacy_params_v2_to_v3()

◆ dt_masks_legacy_params_v2_to_v3_transform()

static void dt_masks_legacy_params_v2_to_v3_transform ( const dt_image_t image,
float *  coords 
)
static

◆ dt_masks_legacy_params_v2_to_v3_transform_only_rescale()

static void dt_masks_legacy_params_v2_to_v3_transform_only_rescale ( const dt_image_t image,
float *  coords,
size_t  coords_count 
)
static

◆ dt_masks_legacy_params_v3_to_v4()

static int dt_masks_legacy_params_v3_to_v4 ( dt_develop_t develop,
void params 
)
static

◆ dt_masks_legacy_params_v4_to_v5()

static int dt_masks_legacy_params_v4_to_v5 ( dt_develop_t develop,
void params 
)
static

◆ dt_masks_legacy_params_v5_to_v6()

static int dt_masks_legacy_params_v5_to_v6 ( dt_develop_t develop,
void params 
)
static

◆ dt_masks_points_bounding_box()

void dt_masks_points_bounding_box ( const float *const  points,
const int  num_points,
int *  width,
int *  height,
int *  posx,
int *  posy 
)

Axis-aligned bounding box of an outline, in the outline's own coordinates.

points is the interleaved x/y array a shape's get_points_border produced, and point 0 is SKIPPED: every shape that uses this stores its centre there, not a point on the outline.

Definition at line 322 of file masks.c.

References height, i, and width.

Referenced by _circle_get_area(), _circle_get_source_area(), _ellipse_get_area(), and _ellipse_get_source_area().

◆ dt_masks_read_masks_history()

void dt_masks_read_masks_history ( dt_develop_t dev,
const int32_t  imgid 
)

◆ dt_masks_sample_grid_backtransform()

◆ dt_masks_sample_grid_interpolate()

void dt_masks_sample_grid_interpolate ( const float *const  points,
const dt_masks_sample_grid_t *const  grid,
float *const  buffer,
const int  buf_width,
const int  buf_height,
int *const  endx,
int *const  endy 
)

Bilinear expansion of a coarse grid of mask values back to full ROI resolution.

points is the buffer dt_masks_sample_grid_backtransform() returned, with each cell's mask value written over its x coordinate (that is, at points[index * 2]) – every shape evaluates in place like that, so the interpolator reads the same stride whatever the shape.

Writes into buffer over the rectangle the grid covers, clipped to the buffer, and reports the exclusive end of that rectangle through endx/endy for callers that go on to mark the touched box.

Definition at line 393 of file masks.c.

References __OMP_PARALLEL_FOR__, DT_MASKS_GRID_MAX_STEP, dt_masks_sample_grid_t::height, i, MIN, row, dt_masks_sample_grid_t::step, w1, dt_masks_sample_grid_t::width, dt_masks_sample_grid_t::x0, and dt_masks_sample_grid_t::y0.

Referenced by _circle_get_mask_roi(), _ellipse_get_mask_roi(), _gradient_get_mask(), and _gradient_get_mask_roi().

◆ dt_masks_skip_contains()

gboolean dt_masks_skip_contains ( const dt_masks_skip_range_t skips,
const int  skip_count,
const int  index 
)

Is index inside one of the excluded spans? For a consumer that SEARCHES the outline rather than walking it forward – a forward walk should use dt_masks_draw_outline_runs() or carry its own cursor. skips must be sorted and disjoint.

Definition at line 306 of file masks.c.

References FALSE, IS_NULL_PTR, and TRUE.

Referenced by _brush_get_border_handle_resampled(), and _outline_band_check().

◆ dt_masks_type_name()

const char * dt_masks_type_name ( dt_masks_type_t  type)

The stable, untranslated token for a shape kind: circle, ellipse, polygon, brush, gradient, group, or "unknown".

Takes a VALUE, not a form, so a caller can name a kind it recorded earlier, after the form it came from may be gone.

THESE TOKENS ARE PERSISTED. They build the conf keys plugins/darkroom/<plugin>/<type>/<feature> declared in data/anselconfig.xml.in (".../polygon/fading" and friends), so the polygon token is "polygon" and can never become "path": a shape reading a key that is not in confgen gets 0, which would silently reset the user's setting. dt_masks_type_t is a bit field, so first match wins and the order below is load-bearing.

Returns
a static string, never NULL, never translated. For display, use the translated label in develop/masks_gui.h instead.

Definition at line 1767 of file masks.c.

References DT_MASKS_BRUSH, DT_MASKS_CIRCLE, DT_MASKS_ELLIPSE, DT_MASKS_GRADIENT, DT_MASKS_GROUP, DT_MASKS_POLYGON, and type.

Referenced by _forms_json(), _type_tokens_are_the_persisted_conf_key_spellings(), dt_masks_get_set_conf_value(), dt_supervisor_describe(), and dt_supervisor_form().

◆ dt_masks_version()

int dt_masks_version ( void  )

Definition at line 486 of file masks.c.

References DEVELOP_MASKS_VERSION.

Referenced by _read_mask_row(), dt_masks_create(), and legacy_params().

◆ dt_masks_write_masks_history_item()

Variable Documentation

◆ form_id_seed

int form_id_seed = 0
static

Definition at line 849 of file masks.c.

Referenced by dt_masks_create().