89 GList *duplicated_points = NULL;
95 if(point_struct_size != 0)
97 for(GList *point_node = mask_form->
points; point_node; point_node = g_list_next(point_node))
99 void *point_copy = malloc(point_struct_size);
100 memcpy(point_copy, point_node->data, point_struct_size);
101 duplicated_points = g_list_prepend(duplicated_points, point_copy);
107 duplicate_form->
points = g_list_reverse(duplicated_points);
109 return duplicate_form;
127 int new_form_id = 100;
128 for(GList *form_node = dev->
forms; form_node; )
133 mask_form->
formid = new_form_id++;
134 form_node = dev->
forms;
138 form_node = g_list_next(form_node);
148 const gboolean has_multi_name = g_strcmp0(module_multi_name,
"") != 0;
151 gchar *group_name = g_strdup_printf(
"Group %s", module_label);
166 g_strlcpy(group_form->
name, group_name,
sizeof(group_form->
name));
176 module->blend_params->mask_id = group_form->formid;
198 snprintf(dest_form->
name,
sizeof(dest_form->
name), _(
"copy of %s"), base_form->
name);
213 if(nid <= 0)
return nid;
221 for(GList *pts = grp->
points; pts; pts = g_list_next(pts))
224 if(pt->
formid == form_id) { orig_entry = pt;
break; }
229 if(new_entry && orig_entry)
239 float **point_buffer,
int *point_count,
240 float **border_buffer,
int *border_count,
244 if(!
IS_NULL_PTR(border_skips)) *border_skips = NULL;
245 if(!
IS_NULL_PTR(border_skip_count)) *border_skip_count = 0;
253 border_buffer, border_count,
254 border_skips, border_skip_count, source, module);
301#define MASKS_XSECT_BUCKET 4
310 int lo = 0, hi = skip_count - 1;
313 const int mid = (lo + hi) / 2;
314 if(index < skips[mid].jump_from) hi = mid - 1;
315 else if(index >= skips[mid].resume_at) lo = mid + 1;
329 float xmin = FLT_MAX, xmax = -FLT_MAX, ymin = FLT_MAX, ymax = -FLT_MAX;
331 for(
int i = 1;
i < num_points;
i++)
333 xmin = fminf(points[
i * 2], xmin);
334 xmax = fmaxf(points[
i * 2], xmax);
335 ymin = fminf(points[
i * 2 + 1], ymin);
336 ymax = fmaxf(points[
i * 2 + 1], ymax);
341 *
width = (xmax - xmin);
347 const char *
const shape,
const char *
const form_name)
349 const int gw = grid->
width;
351 const int step = grid->
step;
352 const int px = grid->
px;
353 const int py = grid->
py;
355 const size_t count = (size_t)gw *
gh;
364 for(
int j = 0; j <
gh; j++)
365 for(
int i = 0;
i < gw;
i++)
367 const size_t index = (size_t)j * gw +
i;
368 points[index * 2] = (step * (
i + grid->
x0) + px) *
iscale;
369 points[index * 2 + 1] = (step * (j + grid->
y0) + py) *
iscale;
394 float *
const buffer,
const int buf_width,
const int buf_height,
395 int *
const endx,
int *
const endy)
397 const int step = grid->
step;
398 const int gw = grid->
width;
399 const int startx = grid->
x0 * step;
400 const int starty = grid->
y0 * step;
404 const int ex =
MIN(buf_width, (grid->
x0 + gw - 1) * step);
405 const int ey =
MIN(buf_height, (grid->
y0 + grid->
height - 1) * step);
409 for(
int i = 0;
i < step;
i++)
411 w0[
i] = (float)(step -
i);
414 const float inv_step2 = 1.0f / (step * step);
417 for(
int j = starty; j < ey; j++)
419 const int jj = j % step;
420 const int mj = j / step - grid->
y0;
421 const float wj0 = w0[jj];
422 const float wj1 =
w1[jj];
423 const size_t row_base = (size_t)mj * gw;
424 float *
const row = buffer + (size_t)j * buf_width;
428 for(
int i = startx;
i < ex;
i++)
430 const size_t mindex = row_base + mi;
431 const float wii0 = w0[ii];
432 const float wii1 =
w1[ii];
433 row[
i] = (points[mindex * 2] * wii0 * wj0
434 + points[(mindex + 1) * 2] * wii1 * wj0
435 + points[(mindex + gw) * 2] * wii0 * wj1
436 + points[(mindex + gw + 1) * 2] * wii1 * wj1) * inv_step2;
452 int *area_width,
int *area_height,
int *area_pos_x,
int *area_pos_y)
459 return mask_form->
functions->
get_area(module, pipe, piece, mask_form, area_width, area_height,
460 area_pos_x, area_pos_y);
466 int *area_width,
int *area_height,
467 int *area_pos_x,
int *area_pos_y)
479 area_pos_x, area_pos_y);
513 const char *opname =
"flip";
516 for(GList *module_node = develop->
iop; module_node; module_node = g_list_next(module_node))
519 if(!strcmp(iop_module->
op, opname))
530 module->init_pipe(module, NULL, &piece);
531 module->commit_params(module, module->default_params, NULL, &piece);
536 GList *point_node = mask_form->
points;
544 module->distort_backtransform(module, NULL, &piece, circle->center, 1);
548 for(; point_node; point_node = g_list_next(point_node))
552 module->distort_backtransform(module, NULL, &piece, polygon_node->node, 1);
553 module->distort_backtransform(module, NULL, &piece, polygon_node->ctrl1, 1);
554 module->distort_backtransform(module, NULL, &piece, polygon_node->ctrl2, 1);
561 module->distort_backtransform(module, NULL, &piece, gradient->center, 1);
573 module->distort_backtransform(module, NULL, &piece, ellipse->center, 1);
577 const float y = ellipse->
radius[0];
584 for(; point_node; point_node = g_list_next(point_node))
588 module->distort_backtransform(module, NULL, &piece, brush_node->node, 1);
589 module->distort_backtransform(module, NULL, &piece, brush_node->ctrl1, 1);
590 module->distort_backtransform(module, NULL, &piece, brush_node->ctrl2, 1);
597 module->distort_backtransform(module, NULL, &piece, mask_form->source, 1);
608 const float image_width = (float)image->
width;
609 const float image_height = (float)image->
height;
611 const float crop_x = (float)image->
crop_x;
612 const float crop_y = (float)image->
crop_y;
623 coords[0] = ((coords[0] * crop_width) + crop_x) / image_width;
624 coords[1] = ((coords[1] * crop_height) + crop_y) / image_height;
630 const float image_width = (float)image->
width;
631 const float image_height = (float)image->
height;
641 const float crop_min =
MIN(crop_width, crop_height);
642 const float image_min =
MIN(image_width, image_height);
643 for(
size_t coord_index = 0; coord_index < coords_count; coord_index++)
644 coords[coord_index] = ((coords[coord_index] * crop_min)) / image_min;
666 GList *point_node = mask_form->
points;
680 for(; point_node; point_node = g_list_next(point_node))
704 for(; point_node; point_node = g_list_next(point_node))
738 GList *point_node = mask_form->
points;
764 GList *point_node = mask_form->
points;
789 GList *point_node = mask_form->
points;
809 if(old_version == 1 && new_version == 2)
815 if(old_version == 1 && new_version == 6)
823 else if(old_version == 2 && new_version == 6)
830 else if(old_version == 3 && new_version == 6)
836 else if(old_version == 4 && new_version == 6)
841 else if(old_version == 5 && new_version == 6)
901 for(; form_list; form_list = g_list_next(form_list))
904 if(mask_form->
formid == form_id)
return mask_form;
919 for(GList *module_node = g_list_first(develop->
iop); module_node; module_node = g_list_next(module_node))
922 if(strcmp(module->op,
"mask_manager") == 0)
929 const int used_count)
931 for(
int used_index = 0; used_index < used_count; used_index++)
933 if(used_form_ids[used_index] == 0)
935 used_form_ids[used_index] = form_id;
938 if(used_form_ids[used_index] == form_id)
break;
944 for(GList *group_node = mask_form->
points; group_node; group_node = g_list_next(group_node))
958 const guint form_count = g_list_length(develop_src->
forms);
959 if(form_count == 0)
return 0;
965 used_form_ids, form_count);
967 for(
int form_index = 0; form_index < (int)form_count && used_form_ids[form_index] > 0; form_index++)
973 used_form_ids[form_index]);
976 develop_dest->
forms = g_list_remove(develop_dest->
forms, existing_form);
977 develop_dest->
allforms = g_list_append(develop_dest->
allforms, existing_form);
986 develop_dest->
forms = g_list_append(develop_dest->
forms, new_form);
990 fprintf(stderr,
"[dt_masks_copy_used_forms_for_module] form %i not found in source image\n",
991 used_form_ids[form_index]);
1009 const int form,
const char *
name,
const int version,
1010 const void *points,
const int points_len,
const int point_count,
1011 const void *source,
const int source_len)
1018 mask_form->
formid = form_id;
1019 g_strlcpy(mask_form->
name,
name,
sizeof(mask_form->
name));
1021 mask_form->
points = NULL;
1022 memcpy(mask_form->
source, source,
sizeof(
float) * 2);
1027 const char *
const point_buffer = (
const char *)points;
1029 for(
int point_index = 0; point_index < point_count; point_index++)
1031 char *point_data = (
char *)malloc(point_struct_size);
1032 memcpy(point_data, point_buffer + point_index * point_struct_size, point_struct_size);
1033 mask_form->
points = g_list_append(mask_form->
points, point_data);
1046 "[_dev_read_masks_history] %s (imgid `%i\'): mask version mismatch: history is %d, dt %d.\n",
1068 for(GList *history_node = g_list_first(develop->
history); history_node; history_node = g_list_next(history_node))
1071 if(history_entry->
num == history_num)
1091 "[_dev_read_masks_history] can't find history entry %i while adding mask %s(%i)\n",
1092 history_num, mask_form->
name, form_id);
1102 .last_history_item = NULL, .previous_num = -1 };
1114 mask_form->
name, mask_form->
type, image_id);
1118 const guint point_count = mask_form->
functions ? g_list_length(mask_form->
points) : 0;
1124 char *
const restrict point_buffer = (
char *)
dt_alloc_align(point_count * point_struct_size);
1125 int buffer_offset = 0;
1126 for(GList *point_node = mask_form->
points; point_node; point_node = g_list_next(point_node))
1128 memcpy(point_buffer + buffer_offset, point_node->data, point_struct_size);
1129 buffer_offset += point_struct_size;
1133 mask_form->
name, mask_form->
version, point_buffer,
1134 point_count * point_struct_size, point_count,
1135 mask_form->
source, 2 *
sizeof(
float));
1144 mask_form->
points = NULL;
1151 return module->dev->form_gui
1152 ? module->dev->form_gui->edit_mode
1153 : DT_MASKS_EDIT_OFF;
1177 for(GList *group_node = source_group->
points; group_node; group_node = g_list_next(group_node))
1200 int form_id = mask_form->
formid;
1208 for(GList *group_node = group_form->
points; group_node; group_node = g_list_next(group_node))
1211 if(group_entry->
formid == form_id)
1214 group_form->
points = g_list_remove(group_form->
points, group_entry);
1249 for(GList *iop_node = dev->
iop; iop_node; iop_node = g_list_next(iop_node))
1267 GList *shapes = iop_group->
points;
1271 if(group_entry->
formid == form_id)
1275 iop_group->
points = g_list_remove(iop_group->
points, group_entry);
1277 shapes = iop_group->
points;
1280 shapes = g_list_next(shapes);
1293 for(GList *form_node = dev->
forms; form_node; form_node = g_list_next(form_node))
1296 if(existing_form->
formid == form_id)
1308 float center_point[2];
1313 mask_form->
area = area;
1317 "[masks] gravity center updated: form=%p id=%d type=0x%x ok=%d center=(%f,%f), area=%f\n",
1318 (
void *)mask_form, mask_form->
formid, mask_form->
type, ok,
1337 for(
const GList *point_node = base_form->
points; point_node; point_node = g_list_next(point_node))
1339 const void *point_data = point_node->data;
1341 void *point_copy = malloc(node_size);
1343 memcpy(point_copy, point_data, node_size);
1344 dest_form->
points = g_list_append(dest_form->
points, point_copy);
1355 guint group_index = 0;
1356 for(GList *group_node = group_form->
points; group_node; group_node = g_list_next(group_node))
1359 if(entry->
formid == form_id)
1361 group_entry = entry;
1370 const guint group_length = g_list_length(group_form->
points);
1371 if(!move_up && group_index == 0)
return;
1372 if(move_up && group_index == group_length - 1)
return;
1374 group_form->
points = g_list_remove(group_form->
points, group_entry);
1379 group_form->
points = g_list_insert(group_form->
points, group_entry, group_index);
1387 if(group_form->
formid == form_id)
return 1;
1388 int nested_count = 0;
1389 for(GList *group_node = group_form->
points; group_node; group_node = g_list_next(group_node))
1398 return nested_count;
1407 hash =
dt_hash(hash, (
char *)&mask_form->
formid,
sizeof(
int));
1409 hash =
dt_hash(hash, (
char *)&mask_form->
source,
sizeof(
float) * 2);
1411 for(
const GList *point_node = mask_form->
points; point_node; point_node = g_list_next(point_node))
1424 hash =
dt_hash(hash, (
char *)&group_entry->
state,
sizeof(
int));
1425 hash =
dt_hash(hash, (
char *)&group_entry->
opacity,
sizeof(
float));
1445 hash =
dt_hash(hash, (
const char *)&mask_form->
formid,
sizeof(
int));
1446 hash =
dt_hash(hash, (
const char *)&mask_form->
version,
sizeof(
int));
1447 hash =
dt_hash(hash, (
const char *)&mask_form->
source,
sizeof(
float) * 2);
1449 for(
const GList *point_node = mask_form->
points; point_node; point_node = g_list_next(point_node))
1459 hash =
dt_hash(hash, (
const char *)&group_entry->
formid,
sizeof(
int));
1460 hash =
dt_hash(hash, (
const char *)&group_entry->
state,
sizeof(
int));
1461 hash =
dt_hash(hash, (
const char *)&group_entry->
opacity,
sizeof(
float));
1487 if(!g_hash_table_add(used_form_ids, GINT_TO_POINTER(form_id)))
return;
1493 for(GList *group_node = mask_form->
points; group_node; group_node = g_list_next(group_node))
1504 int masks_removed = 0;
1505 GList *forms = *forms_list;
1508 GHashTable *used_form_ids = g_hash_table_new(g_direct_hash, g_direct_equal);
1511 int history_index = 0;
1512 for(GList *history_node = history_list; history_node && history_index < history_end;
1513 history_node = g_list_next(history_node))
1529 GList *shape_node = forms;
1533 const gboolean is_used = g_hash_table_contains(used_form_ids, GINT_TO_POINTER(mask_form->
formid));
1535 shape_node = g_list_next(shape_node);
1539 forms = g_list_remove(forms, mask_form);
1549 g_hash_table_destroy(used_form_ids);
1551 *forms_list = forms;
1553 return masks_removed;
1567 int history_count = g_list_length(history_list);
1568 int history_end = history_count;
1569 for(
const GList *history_node = g_list_last(history_list); history_node;
1570 history_node = g_list_previous(history_node))
1576 history_end = history_count - 1;
1604 GList *forms = NULL;
1605 int history_index = 0;
1606 for(
const GList *history_node = g_list_first(develop->
history);
1608 history_node = g_list_next(history_node))
1612 if(history_item->
forms) forms = history_item->
forms;
1629 float **buffer,
int *
width,
int *
height,
int *posx,
int *posy)
1676 out->member_count =
out->is_group ? g_list_length(form->
points) : 0;
1677 g_strlcpy(
out->name, form->
name,
sizeof(
out->name));
1697 out->opacity = 0.0f;
1718 const gboolean touch, guint *
const out_index)
1729 for(GList *node = group->
points; node; node = g_list_next(node), index++)
1743 const guint out_max)
1751 for(
const GList *node = group->
points; node; node = g_list_next(node), total++)
1781 else return "unknown";
1797 const int before = entry->
state;
1801 entry->
state = (entry->
state & ~DT_MASKS_STATE_IS_COMBINE_OP) | operation;
1821 if(g_strcmp0(group->
name,
name) == 0)
1845 const int max_depth)
1847 if(max_depth <= 0)
return NULL;
1851 for(GList *forms = dev->
forms; forms; forms = g_list_next(forms))
1862 for(GList *points = grp->
points; points; points = g_list_next(points))
1866 if(
point->formid == formid)
return grp;
1895 for(
const GList *forms = dev->
forms; forms; forms = g_list_next(forms))
1928 if(container_id == needle_id)
return TRUE;
1933 for(
const GList *pts =
container->points; pts; pts = g_list_next(pts))
1949 gboolean *has_shapes)
1954 for(
const GList *pts = group->
points; pts; pts = g_list_next(pts))
1974 gboolean *has_shapes)
1988 for(
const GList *pts = group->
points; pts; pts = g_list_next(pts))
1994 if(!
IS_NULL_PTR(holder_id)) *holder_id = group_id;
2014 int *holder_id, guint *index,
2015 char *holder_name,
const size_t holder_name_size)
2023 if(!
IS_NULL_PTR(holder_name) && holder_name_size > 0)
2024 g_strlcpy(holder_name,
IS_NULL_PTR(holder) ?
"" : holder->
name, holder_name_size);
2043 const float before = entry->
opacity;
void dt_atomic_set_int(dt_atomic_int *var, int value)
uint32_t container(dt_lib_module_t *self)
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.
const dt_masks_functions_t dt_masks_functions_circle
const dt_colormatrix_t dt_aligned_pixel_t out
void * dt_alloc_align(size_t size)
Allocate cacheline-aligned memory.
int32_t dt_dev_get_history_end_ext(struct dt_develop_t *dev)
Get the current history end index (GUI perspective).
const dt_masks_functions_t dt_masks_functions_brush
int dt_dev_distort_backtransform_plus(const dt_dev_pixelpipe_t *pipe, const double iop_order, const int transf_direction, float *points, size_t points_count)
gchar * dt_dev_get_multi_name(const struct dt_iop_module_t *module)
gchar * dt_history_item_get_name(const struct dt_iop_module_t *module)
@ DT_DEV_TRANSFORM_DIR_BACK_INCL
GtkWidget * status
result of the last capture
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
const dt_masks_functions_t dt_masks_functions_ellipse
const dt_masks_functions_t dt_masks_functions_gradient
const dt_masks_functions_t dt_masks_functions_group
static uint64_t dt_hash(uint64_t hash, const char *str, size_t size)
void dt_history_message(const char *format,...)
Everything the history, styles and presets code says to the outside world: messages for the user,...
void dt_history_repository_foreach_mask_item(const int32_t imgid, dt_history_repository_mask_cb cb, void *user_data)
gboolean dt_history_repository_write_mask_item(const int32_t imgid, const int num, const int formid, const int form, const char *name, const int version, const void *points, const int points_len, const int points_count, const void *source, const int source_len)
@ ORIENTATION_ROTATE_CCW_90_DEG
@ ORIENTATION_ROTATE_CW_90_DEG
@ ORIENTATION_ROTATE_180_DEG
static dt_image_orientation_t dt_image_orientation(const dt_image_t *img)
@ IOP_FLAGS_SUPPORTS_BLENDING
_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.
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
static void dt_masks_legacy_params_v2_to_v3_transform(const dt_image_t *image, float *coords)
gchar * dt_masks_group_name_for_module(const dt_iop_module_t *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)
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_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_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)
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)
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 int _masks_cleanup_unused(dt_develop_t *dev, GList **forms_list, GList *history_list, const int history_end)
gboolean dt_masks_form_get_info(const dt_masks_form_t *form, dt_masks_form_info_t *out)
static int dt_masks_legacy_params_v3_to_v4(dt_develop_t *develop, void *params)
static void dt_masks_legacy_params_v2_to_v3_transform_only_rescale(const dt_image_t *image, float *coords, size_t coords_count)
void dt_masks_free_form(dt_masks_form_t *mask_form)
static void _member_from_entry(dt_masks_member_t *const out, const dt_masks_form_group_t *const entry, const guint index)
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.
static int dt_masks_legacy_params_v5_to_v6(dt_develop_t *develop, void *params)
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.
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)
void _check_id(dt_develop_t *dev, dt_masks_form_t *mask_form)
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 duplicat...
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.
uint64_t dt_masks_form_get_own_hash(uint64_t hash, GList *masks, const dt_masks_form_t *mask_form)
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)
dt_iop_module_t * dt_masks_get_mask_manager(dt_develop_t *develop)
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_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_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_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.
void dt_masks_read_masks_history(dt_develop_t *develop, const int32_t image_id)
static gboolean _group_contains_recurs(dt_develop_t *dev, const int container_id, const int needle_id)
int dt_masks_version(void)
dt_masks_form_t * dt_masks_get_from_id_ext(GList *form_list, int form_id)
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.
static dt_masks_form_t * _find_holder(dt_develop_t *dev, dt_masks_form_t *grp, const int formid, const int max_depth)
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)
int dt_masks_legacy_params(dt_develop_t *develop, void *params, const int old_version, const int new_version)
dt_masks_form_t * dt_masks_create_ext(dt_develop_t *dev, dt_masks_type_t type)
static int dt_masks_legacy_params_v2_to_v3(dt_develop_t *develop, void *params)
static int dt_masks_legacy_params_v1_to_v2(dt_develop_t *develop, void *params)
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).
dt_masks_form_t * dt_masks_create(dt_masks_type_t type)
void dt_masks_cleanup_unused(dt_develop_t *develop)
Cleanup unused masks and refresh the current forms snapshot.
int _find_in_group(dt_develop_t *dev, dt_masks_form_t *group_form, int form_id)
guint dt_masks_group_copy_members(const dt_masks_form_t *group, dt_masks_member_t *out, const guint out_max)
void dt_masks_form_move(dt_masks_form_t *group_form, int form_id, int move_up)
void dt_masks_form_invalidate_gravity_center(dt_masks_form_t *mask_form)
void dt_masks_write_masks_history_item(const int32_t image_id, const int history_num, dt_masks_form_t *mask_form)
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.
dt_masks_form_t * dt_masks_get_from_id(dt_develop_t *develop, int form_id)
uint64_t dt_masks_group_get_hash_ext(uint64_t hash, GList *masks, dt_masks_form_t *mask_form)
static void _cleanup_unused_recurs(GList *form_list, int form_id, GHashTable *used_form_ids)
int dt_masks_form_duplicate(dt_develop_t *develop, int form_id)
dt_masks_edit_mode_t dt_masks_get_edit_mode(struct dt_iop_module_t *module)
void dt_masks_form_update_gravity_center(dt_develop_t *dev, dt_masks_form_t *mask_form)
void dt_masks_points_bounding_box(const float *const points, const int num_points, int *width, int *height, int *posx, int *posy)
void _set_group_name_from_module(dt_iop_module_t *module, dt_masks_form_t *group_form)
dt_masks_form_t * _group_from_module(dt_develop_t *develop, dt_iop_module_t *module)
gboolean dt_masks_skip_contains(const dt_masks_skip_range_t *skips, const int skip_count, const int index)
static void _masks_fill_used_forms(GList *forms_list, const int form_id, int *used_form_ids, const int used_count)
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_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)
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_iop_use_same_as(dt_iop_module_t *module, dt_iop_module_t *source_module)
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)
static gboolean _group_covers_recurs(dt_develop_t *dev, const int group_id, const int target_id, gboolean *has_shapes)
void dt_masks_form_gui_points_free(gpointer data)
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)
static int dt_masks_legacy_params_v4_to_v5(dt_develop_t *develop, void *params)
dt_masks_raster_result_t
What a rasterisation attempt produced.
@ DT_MASKS_ELLIPSE_EQUIDISTANT
@ DT_MASKS_GRADIENT_STATE_LINEAR
#define DEVELOP_MASKS_VERSION
The per-shape function table, private to the masks implementation.
#define DT_MASKS_GRID_MAX_STEP
const dt_masks_functions_t dt_masks_functions_polygon
Ask the masks module about a shape or a group, instead of reading its structs.
void dt_masks_change_form_gui(dt_develop_t *dev, dt_masks_form_t *new_form)
gboolean dt_masks_form_get_gravity_center(dt_develop_t *dev, const dt_masks_form_t *mask_form, float center[2], float *area)
void dt_masks_append_form(dt_develop_t *develop, dt_masks_form_t *mask_form)
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)
void dt_masks_remove_form(dt_develop_t *develop, dt_masks_form_t *mask_form)
void dt_masks_replace_current_forms(dt_develop_t *dev, GList *forms)
dt_masks_form_t * dt_masks_cow_touch(dt_develop_t *dev, dt_masks_form_t *form)
static void dt_masks_touched_none(dt_iop_roi_t *touched)
@ DT_MASKS_STATE_IS_COMBINE_OP
dt_masks_result_t
What a request that may change the masks model did.
#define CLAMPF(a, mn, mx)
#define dt_free_align(ptr)
Release memory from dt_alloc_align() and set ptr to NULL.
static void * dt_calloc_align(size_t size)
dt_alloc_align() followed by a zero fill.
static void dt_free_gpointer(gpointer ptr)
g_free() one pointer, with the signature GDestroyNotify wants.
#define dt_free(ptr)
g_free() ptr and set it to NULL, skipping both if it is already NULL.
static float gh(const float f)
#define __OMP_PARALLEL_FOR__(...)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
unsigned __int64 uint64_t
dt_dev_history_item_t * last_history_item
dt_dev_history_item_t * history_item
struct dt_develop_blend_params_t * blend_params
dt_pthread_rwlock_t history_mutex
dt_pthread_rwlock_t masks_mutex
char filename[DT_MAX_FILENAME_LEN]
struct dt_develop_blend_params_t * blend_params
struct dt_develop_t * dev
Region of interest passed through the pixelpipe.
dt_masks_gradient_states_t state
void(* sanitize_config)(dt_masks_type_t type_flags)
void(* duplicate_points)(struct dt_develop_t *const dev, struct dt_masks_form_t *base, struct dt_masks_form_t *dest)
dt_masks_raster_result_t(* 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, dt_iop_roi_t *touched)
dt_masks_raster_result_t(* 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)
dt_masks_raster_result_t(* 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)
dt_masks_raster_result_t(* 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)
dt_masks_raster_result_t(* get_points_border)(struct dt_develop_t *dev, struct dt_masks_form_t *form, float **points, int *points_count, float **border, int *border_count, dt_masks_skip_range_t **border_skips, int *border_skip_count, int source, const dt_iop_module_t *const module)
One shape's membership of one group, BY VALUE.
dt_masks_ellipse_flags_t flags
One cut in a shape's border outline: while walking the border buffer forward, on reaching index jump_...
void dt_supervisor_form(const dt_sv_op_t op, const dt_masks_form_t *form)
static gboolean dt_supervisor_active(void)
static double dt_get_wtime(void)