53#define FADING_MIN 0.0005f
54#define FADING_MAX 1.0f
56#define BORDER_MIN 0.00005f
57#define BORDER_MAX 0.5f
59#define RADIUS_CLONE_MIN 0.00005f
60#define RADIUS_CLONE_MAX 0.5f
62#define RADIUS_NON_CLONE_MIN 0.0005f
63#define RADIUS_NON_CLONE_MAX 1.0f
66 const float sinr,
const float cosr,
float *xnew,
float *ynew)
68 const float xtmp = (sinr * sinr + cosr * cosr) * (
x - xref) + (cosr * sinr - cosr * sinr) * (y - yref);
69 const float ytmp = (cosr * sinr - cosr * sinr) * (
x - xref) + (sinr * sinr + cosr * cosr) * (y - yref);
139 float radius2 = mouse_radius * mouse_radius;
141 const float lastx = points[2 * (points_count - 1)];
142 const float lasty = points[2 * (points_count - 1) + 1];
144 for(
int i = 0;
i < points_count;
i++)
146 const float px = points[2 *
i];
147 const float py = points[2 *
i + 1];
149 const float r1 =
x - lastx;
150 const float r2 = y - lasty;
151 const float r3 = px - lastx;
152 const float r4 = py - lasty;
154 const float d = r1 * r3 + r2 * r4;
155 const float l = sqf(r3) + sqf(r4);
156 const float p =
d / l;
158 float xx = 0.0f, yy = 0.0f;
160 if(
p < 0 || (px == lastx && py == lasty))
176 const float dx =
x - xx;
177 const float dy = y - yy;
179 if(sqf(dx) + sqf(dy) < radius2)
return 1;
185 int num_points,
int *inside,
int *inside_border,
int *near_handle,
186 int *inside_source,
float *
dist)
202 const float pt[2] = {
x, y };
213 float min_dist_norm = FLT_MAX;
214 for(
int k=0;
k<5;
k++)
216 const float center_dx =
x - gpt->
source[
k * 2];
217 const float center_dy = y - gpt->
source[
k * 2 + 1];
218 const float dist2 = sqf(center_dx) + sqf(center_dy);
219 min_dist_norm = fminf(min_dist_norm, dist2);
221 *
dist = min_dist_norm;
229 const float center_dx =
x - gpt->
points[0];
230 const float center_dy = y - gpt->
points[1];
231 *
dist = sqf(center_dx) + sqf(center_dy);
236 if(!close_to_border && !in_border)
return;
241 *inside_border = !in_form;
256 values->border =
dt_conf_get_float(use_spot_defaults ?
"plugins/darkroom/spots/ellipse/border"
257 :
"plugins/darkroom/masks/ellipse/border");
258 values->flags =
dt_conf_get_int(use_spot_defaults ?
"plugins/darkroom/spots/ellipse/flags"
259 :
"plugins/darkroom/masks/ellipse/flags");
260 values->radius_a =
dt_conf_get_float(use_spot_defaults ?
"plugins/darkroom/spots/ellipse/radius_a"
261 :
"plugins/darkroom/masks/ellipse/radius_a");
262 values->radius_b =
dt_conf_get_float(use_spot_defaults ?
"plugins/darkroom/spots/ellipse/radius_b"
263 :
"plugins/darkroom/masks/ellipse/radius_b");
264 values->rotation =
dt_conf_get_float(use_spot_defaults ?
"plugins/darkroom/spots/ellipse/rotation"
265 :
"plugins/darkroom/masks/ellipse/rotation");
274 ellipse->
radius[0] = values.radius_a;
275 ellipse->
radius[1] = values.radius_b;
276 ellipse->
border = values.border;
277 ellipse->
rotation = values.rotation;
278 ellipse->
flags = values.flags;
287 float rotation,
float **points,
int *points_count);
298 ? values.radius_a * (1.0f + values.border)
299 : values.radius_a + values.border;
301 ? values.radius_b * (1.0f + values.border)
302 : values.radius_b + values.border;
310 if(!err && values.border > 0.0f)
324 float rotation,
float wd,
float ht,
int *points_count)
327 const float v = (rotation / 180.0f) *
M_PI;
330 const float a = radius_a *
MIN(wd, ht);
331 const float b = radius_b *
MIN(wd, ht);
333 const float sinv = sinf(
v);
334 const float cosv = cosf(
v);
338 const float lambda = (a - b) / (a + b);
340 100, (
int)((
M_PI * (a + b)
341 * (1.0f + (3.0f * lambda * lambda) / (10.0f + sqrtf(4.0f - 3.0f * lambda * lambda)))) /
n));
350 *points_count = l + 5;
353 float center[2] = { xx, yy };
355 const float x = points[0] = center[0];
356 const float y = points[1] = center[1];
359 points[2] =
x + a * cosv;
360 points[3] = y + a * sinv;
361 points[4] =
x - a * cosv;
362 points[5] = y - a * sinv;
364 points[6] =
x - b * sinv;
365 points[7] = y + b * cosv;
366 points[8] =
x + b * sinv;
367 points[9] = y - b * cosv;
369 for(
int i = 5;
i < l + 5;
i++)
371 const float alpha = (
i - 5) * 2.0 *
M_PI / (
float)l;
372 points[
i * 2] =
x + a * cosf(alpha) * cosv - b * sinf(alpha) * sinv;
373 points[
i * 2 + 1] = y + a * cosf(alpha) * sinv + b * sinf(alpha) * cosv;
380 float radius_b,
float rotation,
float **points,
int *points_count,
384 const float wd =
geometry.raw_width;
385 const float ht =
geometry.raw_height;
389 *points =
_points_to_transform(dev, xx, yy, radius_a, radius_b, rotation, wd, ht, points_count);
396 float rotation,
float **points,
int *points_count)
399 const float wd =
geometry.raw_width;
400 const float ht =
geometry.raw_height;
402 *points =
_points_to_transform(dev, xx, yy, radius_a, radius_b, rotation, wd, ht, points_count);
419 int *points_count,
float **border,
int *border_count,
424 if(!
IS_NULL_PTR(border_skips)) *border_skips = NULL;
425 if(!
IS_NULL_PTR(border_skip_count)) *border_skip_count = 0;
431 float x = 0.0f, y = 0.0f, a = 0.0f, b = 0.0f;
439 _ellipse_get_points_source(dev,
x, y, xs, ys, a, b, ellipse->
rotation, points, points_count, module));
451 border, border_count));
464 float *node_x,
float *node_y,
void *user_data)
466 const float *nodes = gui_points->
points;
467 const float rotation = atan2f(nodes[3] - nodes[1], nodes[2] - nodes[0]);
468 const float sinr = sinf(rotation);
469 const float cosr = cosf(rotation);
471 sinr, cosr, node_x, node_y);
479 int *inside_border,
int *near_handle,
int *inside_source,
float *
dist,
void *user_data)
482 inside_border, near_handle, inside_source,
dist);
491 int inside_source,
void *user_data)
507 increment, flow, _(
"Fading: %3.2f%%"), 100.0f);
515 dt_toast_log(_(
"Size: %3.2f%%"), fmaxf(mask_radius_a, mask_radius_b) * 2.f * 100.f);
522 increment, flow, _(
"Opacity: %3.2f%%"), 100.f);
529 increment, flow, _(
"Rotation: %3.2f\302\260"), 1.0f);
557 center[0] = ellipse->
center[0];
558 center[1] = ellipse->
center[1];
621 if(amount > 1.0f && (ellipse->
border > 1.0f ))
643 int flow_increased = (flow > 1) ? (flow - 1) * 5 : flow;
706 double pressure,
int which,
int type, uint32_t
state,
811 const float min_radius = fmin(ellipse->
radius[0], ellipse->
radius[1]);
815 ellipse->
flags &= ~DT_MASKS_ELLIPSE_PROPORTIONAL;
819 const float min_radius = fmin(ellipse->
radius[0], ellipse->
radius[1]);
821 ellipse->
border = CLAMP(ellipse->
border, 0.001f/min_radius, 1.0f/min_radius);
896 ellipse->
center[0] = pts[0];
897 ellipse->
center[1] = pts[1];
915 const float xref = gpt->
points[0];
916 const float yref = gpt->
points[1];
917 const float rx = gpt->
points[
k * 2] - xref;
918 const float ry = gpt->
points[
k * 2 + 1] - yref;
919 const float deltax = gui->
pos[0] + gui->
delta[0] - xref;
920 const float deltay = gui->
pos[1] + gui->
delta[1] - yref;
926 const float r = dt_fast_hypotf(rx, ry);
927 const float d = (rx * deltax + ry * deltay) /
r;
928 const float s = fmaxf(
r > 0.0f ? (
r +
d) /
r : 0.0f, 0.0f);
938 else if(
k == 3 ||
k == 4)
957 const float origin_point[2] = { gpt->
points[0], gpt->
points[1] };
972static void _ellipse_draw_shape(
dt_develop_t *dev, cairo_t *cr,
const float *points,
const int points_count,
const int nb,
const gboolean border,
const gboolean source,
981 const double min_step2 = min_step * min_step;
982 double last_x = points[10], last_y = points[11];
983 cairo_move_to(cr, last_x, last_y);
984 for(
int t = 6;
t < points_count;
t++)
986 const double x = points[
t * 2];
987 const double y = points[
t * 2 + 1];
988 const double dx =
x - last_x, dy = y - last_y;
989 if((dx * dx + dy * dy) < min_step2)
continue;
990 cairo_line_to(cr,
x, y);
991 last_x =
x; last_y = y;
993 cairo_close_path(cr);
1002 const float *nodes = gpt->
points;
1005 const float r = atan2f(nodes[3] - nodes[1], nodes[2] - nodes[0]);
1006 const float sinr = sinf(
r);
1007 const float cosr = cosf(
r);
1009 for(
int i = 1;
i < 5;
i++)
1013 const gboolean action = (
i == selected_node);
1084static void _fill_mask(
const size_t numpoints,
float *
const bufptr,
const float *
const points,
1085 const float *
const center,
const float a,
const float b,
const float ta,
const float tb,
1086 const float alpha,
const size_t out_scale)
1088 const float a2 = a * a;
1089 const float b2 = b * b;
1090 const float ta2 = ta * ta;
1091 const float tb2 = tb * tb;
1092 const float cos_alpha = cosf(alpha);
1093 const float sin_alpha = sinf(alpha);
1102 for(
size_t i = 0;
i < numpoints;
i++)
1104 const float x = points[2 *
i] - center[0];
1105 const float y = points[2 *
i + 1] - center[1];
1107 const float l2 =
x *
x + y * y;
1108 const float l = sqrtf(
l2);
1110 const float x_norm = l ?
x / l : 0.0f;
1111 const float y_norm = l ? y / l : 1.0f;
1113 const float x_rot = x_norm * cos_alpha + y_norm * sin_alpha;
1114 const float y_rot = -x_norm * sin_alpha + y_norm * cos_alpha;
1116 const float cosv2 = x_rot * x_rot;
1117 const float sinv2 = y_rot * y_rot;
1120 const float radius2 = a2 * b2 / (a2 * sinv2 + b2 * cosv2);
1121 const float total2 = ta2 * tb2 / (ta2 * sinv2 + tb2 * cosv2);
1125 const float ratio = (total2 -
l2) / (total2 - radius2);
1127 const float f =
CLIP(ratio);
1128 bufptr[
i << out_scale] =
f *
f;
1133 const float rotation,
const float wd,
const float ht,
size_t *point_count)
1136 const float v1 = ((rotation) / 180.0f) *
M_PI;
1137 const float v2 = ((rotation - 90.0f) / 180.0f) *
M_PI;
1138 float a = 0.0f, b = 0.0f,
v = 0.0f;
1153 const float sinv = sinf(
v);
1154 const float cosv = cosf(
v);
1157 const float lambda = (a - b) / (a + b);
1158 const int l = (int)(
M_PI * (a + b)
1159 * (1.0f + (3.0f * lambda * lambda) / (10.0f + sqrtf(4.0f - 3.0f * lambda * lambda))));
1165 *point_count = l + 5;
1168 float center[2] = { center_x, center_y };
1170 const float x = points[0] = center[0];
1171 const float y = points[1] = center[1];
1173 points[2] =
x + a * cosf(
v);
1174 points[3] = y + a * sinf(
v);
1175 points[4] =
x - a * cosf(
v);
1176 points[5] = y - a * sinf(
v);
1177 points[6] =
x + b * cosf(
v -
M_PI / 2.0f);
1178 points[7] = y + b * sinf(
v -
M_PI / 2.0f);
1179 points[8] =
x - b * cosf(
v -
M_PI / 2.0f);
1180 points[9] = y - b * sinf(
v -
M_PI / 2.0f);
1182 for(
int i = 5;
i < l + 5;
i++)
1184 float alpha = (
i - 5) * 2.0 *
M_PI / (
float)l;
1185 points[
i * 2] =
x + a * cosf(alpha) * cosv - b * sinf(alpha) * sinv;
1186 points[
i * 2 + 1] = y + a * cosf(alpha) * sinv + b * sinf(alpha) * cosv;
1208 const float total[2] = { (prop ? ellipse->
radius[0] * (1.0f + ellipse->
border) : ellipse->
radius[0] + ellipse->
border) *
MIN(wd, ht),
1212 size_t point_count = 0;
1213 float *
const restrict points
1246 const float total[2] = { (prop ? ellipse->
radius[0] * (1.0f + ellipse->
border) : ellipse->
radius[0] + ellipse->
border) *
MIN(wd, ht),
1250 size_t point_count = 0;
1251 float *
const restrict points
1272 float **buffer,
int *
width,
int *
height,
int *posx,
int *posy)
1280 double start2 = 0.0;
1298 const int posx_ = *posx;
1299 const int posy_ = *posy;
1304 for(
int i = 0;
i < h;
i++)
1305 for(
int j = 0; j < w; j++)
1307 points[(
i * w + j) * 2] = (j + posx_);
1308 points[(
i * w + j) * 2 + 1] = (
i + posy_);
1341 const float center[2] = { ellipse->
center[0] * wi, ellipse->
center[1] * hi };
1342 const float radius[2] = { ellipse->
radius[0] *
MIN(wi, hi), ellipse->
radius[1] *
MIN(wi, hi) };
1346 float a = 0.0F, b = 0.0F, ta = 0.0F, tb = 0.0F, alpha = 0.0F;
1348 if(radius[0] >= radius[1])
1365 float *
const bufptr = *buffer;
1367 _fill_mask((
size_t)(h)*w, bufptr, points, center, a, b, ta, tb, alpha, 0);
1385 double start1 = 0.0;
1386 double start2 = start1;
1393 const float center[2] = { ellipse->
center[0] * wi, ellipse->
center[1] * hi };
1394 const float radius[2] = { ellipse->
radius[0] *
MIN(wi, hi), ellipse->
radius[1] *
MIN(wi, hi) };
1398 const float a = radius[0];
1399 const float b = radius[1];
1400 const float ta = total[0];
1401 const float tb = total[1];
1402 const float alpha = (ellipse->
rotation / 180.0f) *
M_PI;
1403 const float cosa = cosf(alpha);
1404 const float sina = sinf(alpha);
1408 const int w = roi->
width;
1409 const int h = roi->
height;
1410 const int px = roi->
x;
1411 const int py = roi->
y;
1414 const float grid_scale = 1.0f /
MAX(roi->
scale, 1e-6f);
1415 const int grid = CLAMP((10.0f * grid_scale + 2.0f) / 3.0f, 1, 4);
1416 const int gw = (w + grid - 1) / grid + 1;
1417 const int gh = (h + grid - 1) / grid + 1;
1427 const float lambda = (ta - tb) / (ta + tb);
1428 const int l = (int)(
M_PI * (ta + tb) * (1.0f + (3.0f * lambda * lambda) / (10.0f + sqrtf(4.0f - 3.0f * lambda * lambda))));
1429 const size_t ellpts =
MIN(360, l);
1433 for(
int n = 0;
n < ellpts;
n++)
1435 const float phi = (2.0f *
M_PI *
n) / ellpts;
1436 const float cosp = cosf(phi);
1437 const float sinp = sinf(phi);
1438 ell[2 *
n] = center[0] + ta * cosa * cosp - tb * sina * sinp;
1439 ell[2 *
n + 1] = center[1] + ta * sina * cosp + tb * cosa * sinp;
1463 float xmin = FLT_MAX, ymin = FLT_MAX, xmax = FLT_MIN, ymax = FLT_MIN;
1464 for(
int n = 0;
n < ellpts;
n++)
1467 if(!(isnormal(ell[2 *
n]) && isnormal(ell[2 *
n + 1])))
continue;
1469 xmin =
MIN(xmin, ell[2 *
n]);
1470 xmax =
MAX(xmax, ell[2 *
n]);
1471 ymin =
MIN(ymin, ell[2 *
n + 1]);
1472 ymax =
MAX(ymax, ell[2 *
n + 1]);
1476 printf(
"xmin %f, xmax %f, ymin %f, ymax %f\n", xmin, xmax, ymin, ymax);
1477 printf(
"wi %d, hi %d, iscale %f\n", wi, hi,
iscale);
1478 printf(
"w %d, h %d, px %d, py %d\n", w, h, px, py);
1482 const int bbxm = CLAMP((
int)floorf(xmin /
iscale - px) / grid - 1, 0, gw - 1);
1483 const int bbXM = CLAMP((
int)ceilf(xmax /
iscale - px) / grid + 2, 0, gw - 1);
1484 const int bbym = CLAMP((
int)floorf(ymin /
iscale - py) / grid - 1, 0,
gh - 1);
1485 const int bbYM = CLAMP((
int)ceilf(ymax /
iscale - py) / grid + 2, 0,
gh - 1);
1486 const int bbw = bbXM - bbxm + 1;
1487 const int bbh = bbYM - bbym + 1;
1490 printf(
"bbxm %d, bbXM %d, bbym %d, bbYM %d\n", bbxm, bbXM, bbym, bbYM);
1491 printf(
"gw %d, gh %d, bbw %d, bbh %d\n", gw,
gh, bbw, bbh);
1504 if(bbw <= 1 || bbh <= 1)
1508 = { .
x0 = bbxm, .y0 = bbym, .width = bbw, .height = bbh,
1509 .step = grid, .px = px, .py = py, .iscale =
iscale };
1517 _fill_mask((
size_t)(bbh)*bbw, points, points, center, a, b, ta, tb, alpha, 1);
1528 int endx = 0, endy = 0;
1546 snprintf(form->
name,
sizeof(form->
name), _(
"ellipse #%d"), (
int)nb);
1559 const float radius_a =
dt_conf_get_float(
"plugins/darkroom/spots/ellipse/radius_a");
1560 const float radius_b =
dt_conf_get_float(
"plugins/darkroom/spots/ellipse/radius_b");
1561 float offset[2] = { radius_a, -radius_b };
1568 char *
const restrict msgbuf,
const size_t msgbuf_len)
1575 g_strlcat(msgbuf, _(
"<b>Set source</b>: Shift+Click"), msgbuf_len);
1578 g_strlcat(msgbuf, _(
"<b>Move source</b>: Drag"), msgbuf_len);
1581 g_strlcat(msgbuf, _(
"<b>Resize axis</b>: Drag"), msgbuf_len);
1584 g_strlcat(msgbuf, _(
"<b>Rotate</b>: Drag"), msgbuf_len);
1586 g_strlcat(msgbuf, _(
"<b>Move</b>: Drag, <b>Fading mode</b>: Shift+Click"), msgbuf_len);
1592 float radius_a = 0.0f;
1593 float radius_b = 0.0f;
1594 float border = 0.0f;
1612 const float ratio = radius_a / radius_b;
1614 if(radius_a > radius_b)
1616 radius_a =
CLAMPS(radius_a, 0.001f, 0.5f);
1617 radius_b = radius_a / ratio;
1621 radius_b =
CLAMPS(radius_b, 0.001f, 0.5);
1622 radius_a = ratio * radius_b;
Handle default and user-set shortcuts (accelerators)
static double dist(double x1, double y1, double x2, double y2)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
void dt_conf_set_float(const char *name, float val)
float dt_conf_get_float(const char *name)
Float for name, clamped to its declared bounds.
int dt_conf_get_and_sanitize_int(const char *name, int min, int max)
void dt_conf_set_int(const char *name, int val)
int dt_conf_get_int(const char *name)
Integer for name, clamped to the bounds declared in the XML.
float dt_conf_get_and_sanitize_float(const char *name, float min, float max)
#define DT_CONF_SET_SANITIZED_FLOAT(name, val, min, max)
Clamp val to [min, max] and store it as a float.
void dt_toast_log(const char *msg,...)
dt_dev_image_geometry_t dt_dev_geometry_snapshot(const dt_develop_t *dev)
int dt_dev_coordinates_raw_abs_to_image_abs(dt_develop_t *dev, float *points, size_t points_count)
void dt_dev_coordinates_raw_norm_to_raw_abs(dt_develop_t *dev, float *points, size_t num_points)
int dt_dev_distort_transform_plus(const dt_dev_pixelpipe_t *pipe, const double iop_order, const int transf_direction, float *points, size_t points_count)
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)
@ DT_DEV_TRANSFORM_DIR_BACK_INCL
GtkWidget * geometry
its size, under the preview
GtkWidget * preview
what the selected row actually captures
GHashTable * selected
set of checked row labels, mirrored to conf on every change
static double dt_draw_min_emit_step(cairo_t *cr)
Stroke a line with style.
static void dt_draw_shape_lines(struct dt_develop_t *dev, 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, const struct dt_masks_skip_range_t *skips, const int skip_count)
Draw the lines of a mask shape.
static void dt_draw_node(cairo_t *cr, const gboolean square, const gboolean point_action, const gboolean selected, const float zoom_scale, const float x, const float y)
Draw an node point of a mask.
static dt_masks_raster_result_t _ellipse_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 dt_masks_raster_result_t _ellipse_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)
static void _ellipse_initial_source_pos(dt_develop_t *dev, const float iwd, const float iht, float *x, float *y)
static int _find_closest_handle(dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui, int form_index)
static int _ellipse_events_mouse_moved(struct dt_iop_module_t *module, double x, double y, double pressure, int which, dt_masks_form_t *form, int parentid, dt_masks_form_gui_t *gui, int index)
static gboolean _ellipse_get_gravity_center(dt_develop_t *dev, const dt_masks_form_t *form, float center[2], float *area)
static void _ellipse_sanitize_config(dt_masks_type_t type)
static dt_masks_raster_result_t _ellipse_get_points_border(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 *module)
static dt_masks_raster_result_t _ellipse_get_area(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, int *width, int *height, int *posx, int *posy)
static void _ellipse_draw_handles(const dt_masks_form_gui_t *gui, cairo_t *cr, const float zoom_scale, dt_masks_form_gui_points_t *gpt, const int index)
static void _ellipse_point_transform(const float xref, const float yref, const float x, const float y, const float sinr, const float cosr, float *xnew, float *ynew)
static int _ellipse_events_key_pressed(struct dt_iop_module_t *module, GdkEventKey *event, dt_masks_form_t *form, int parentid, dt_masks_form_gui_t *gui, int index)
static void _ellipse_node_position_cb(const dt_masks_form_gui_points_t *gui_points, int node_index, float *node_x, float *node_y, void *user_data)
Ellipse-specific node position lookup.
static dt_masks_raster_result_t _ellipse_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)
static int _ellipse_get_creation_preview(dt_masks_form_t *form, dt_masks_form_gui_t *gui, dt_masks_preview_buffers_t *preview)
static void _ellipse_duplicate_points(dt_develop_t *const dev, dt_masks_form_t *const base, dt_masks_form_t *const dest)
static int _change_fading(dt_masks_form_t *form, dt_masks_form_gui_t *gui, struct dt_iop_module_t *module, int index, const float amount, const dt_masks_increment_t increment, const int flow)
static int _init_opacity(dt_masks_form_t *form, const float amount, const dt_masks_increment_t increment, const int flow)
static void _fill_mask(const size_t numpoints, float *const bufptr, const float *const points, const float *const center, const float a, const float b, const float ta, const float tb, const float alpha, const size_t out_scale)
static int _change_size(dt_masks_form_t *form, dt_masks_form_gui_t *gui, struct dt_iop_module_t *module, int index, const float amount, const dt_masks_increment_t increment, const int flow)
static void _ellipse_init_new(dt_masks_form_t *form, dt_masks_form_gui_t *gui, dt_masks_node_ellipse_t *ellipse)
static void _ellipse_get_distance(float x, float y, float mouse_radius, dt_masks_form_gui_t *gui, int index, int num_points, int *inside, int *inside_border, int *near_handle, int *inside_source, float *dist)
static void _ellipse_post_select_cb(dt_masks_form_gui_t *mask_gui, int inside, int inside_border, int inside_source, void *user_data)
Ellipse-specific post-selection hook.
static void _ellipse_get_creation_values(const dt_masks_form_t *form, dt_masks_ellipse_creation_values_t *values)
static float _ellipse_get_interaction_value(const dt_masks_form_t *form, dt_masks_interaction_t interaction)
static void _ellipse_set_hint_message(const dt_masks_form_gui_t *const gui, const dt_masks_form_t *const form, char *const restrict msgbuf, const size_t msgbuf_len)
static float * _points_to_transform(dt_develop_t *dev, float xx, float yy, float radius_a, float radius_b, float rotation, float wd, float ht, int *points_count)
static int _ellipse_events_button_pressed(struct dt_iop_module_t *module, double x, double y, double pressure, int which, int type, uint32_t state, dt_masks_form_t *form, int parentid, dt_masks_form_gui_t *gui, int index)
static int _init_size(dt_masks_form_t *form, const float amount, const dt_masks_increment_t increment, const int flow)
static void _ellipse_events_post_expose(cairo_t *cr, float zoom_scale, dt_masks_form_gui_t *gui, int index, int num_points)
static int _ellipse_get_points(dt_develop_t *dev, float xx, float yy, float radius_a, float radius_b, float rotation, float **points, int *points_count)
static void _ellipse_set_form_name(struct dt_masks_form_t *const form, const size_t nb)
const dt_masks_functions_t dt_masks_functions_ellipse
static int _ellipse_point_close_to_path(float x, float y, float mouse_radius, float *points, int points_count)
static float _ellipse_set_interaction_value(dt_masks_form_t *form, dt_masks_interaction_t interaction, float value, dt_masks_increment_t increment, int flow, dt_masks_form_gui_t *gui, struct dt_iop_module_t *module)
static void _ellipse_distance_cb(float pointer_x, float pointer_y, float cursor_radius, dt_masks_form_gui_t *mask_gui, int form_index, int node_count, int *inside, int *inside_border, int *near_handle, int *inside_source, float *dist, void *user_data)
Ellipse-specific inside/border hit testing adapter.
static float *const _ellipse_points_to_transform(dt_develop_t *dev, const float center_x, const float center_y, const float dim1, const float dim2, const float rotation, const float wd, const float ht, size_t *point_count)
static int _ellipse_events_button_released(struct dt_iop_module_t *module, double x, double y, int which, uint32_t state, dt_masks_form_t *form, int parentid, dt_masks_form_gui_t *gui, int index)
static int _change_rotation(dt_masks_form_t *form, dt_masks_form_gui_t *gui, struct dt_iop_module_t *module, int index, const float amount, const dt_masks_increment_t increment, const int flow)
static int _ellipse_events_mouse_scrolled(struct dt_iop_module_t *module, double x, double y, int up, const int flow, uint32_t state, dt_masks_form_t *form, int parentid, dt_masks_form_gui_t *gui, int index, dt_masks_interaction_t interaction)
static int _ellipse_get_points_source(dt_develop_t *dev, float xx, float yy, float xs, float ys, float radius_a, float radius_b, float rotation, float **points, int *points_count, const dt_iop_module_t *module)
static void _ellipse_draw_shape(dt_develop_t *dev, cairo_t *cr, const float *points, const int points_count, const int nb, const gboolean border, const gboolean source, const dt_masks_skip_range_t *skips, const int skip_count)
static int _init_fading(dt_masks_form_t *form, const float amount, const dt_masks_increment_t increment, const int flow)
static int _init_rotation(dt_masks_form_t *form, const float amount, const dt_masks_increment_t increment, const int flow)
_lib_location_type_t type
int32_t dt_get_debug_flags(void)
void dt_print(dt_debug_thread_t thread, const char *msg,...) __attribute__((format(printf
Print to stdout when thread is enabled, prefixed with seconds since startup.
float *const restrict const size_t k
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
void dt_masks_points_bounding_box(const float *const points, const int num_points, int *width, int *height, int *posx, int *posy)
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)
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 dt_masks_raster_result_t dt_masks_raster_from_status(const int status)
dt_masks_raster_result_t
What a rasterisation attempt produced.
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_ELLIPSE_PROPORTIONAL
@ DT_MASKS_ELLIPSE_EQUIDISTANT
int dt_masks_form_change_opacity(dt_develop_t *dev, dt_masks_form_t *form, int parentid, int up, const int flow)
static gboolean dt_masks_form_is_clone(const dt_masks_form_t *form)
static gboolean dt_masks_form_uses_spot_defaults(const dt_masks_form_t *form)
static void dt_masks_reset_source(dt_masks_form_t *form)
The per-shape function table, private to the masks implementation.
int dt_masks_point_in_form_exact(const float *pts, int num_pts, const float *points, int points_start, int points_count, const dt_masks_skip_range_t *skips, int skip_count)
Ray-cast point-in-polygon over a form point stream, honouring skip ranges.
int dt_masks_points_shift_to_source(struct dt_develop_t *dev, const struct dt_iop_module_t *module, float **points, int *points_count, const float xs, const float ys, const int first_shifted)
int dt_masks_preview_add_clone_source(struct dt_masks_form_gui_t *gui, struct dt_masks_preview_buffers_t *preview)
void dt_masks_draw_source(cairo_t *cr, dt_masks_form_gui_t *mask_gui, const int form_index, const int node_count, const float zoom_scale, struct dt_masks_gui_center_point_t *center_point, const shape_draw_function_t *draw_shape_func)
Draw the source for a correction mask.
float dt_masks_get_set_conf_value(dt_masks_form_t *mask_form, char *feature, float new_value, float value_min, float value_max, dt_masks_increment_t increment, int flow)
Change a numerical property of a mask shape, either by in/de-crementing the current value or setting ...
float dt_masks_rotate_with_anchor(dt_develop_t *develop, const float anchor[2], const float center[2], dt_masks_form_gui_t *mask_gui)
Compute rotation angle (degrees) around a center using an anchor point.
dt_masks_form_t * dt_masks_get_visible_form(const dt_develop_t *dev)
Return the currently visible form used by the masks GUI.
float dt_masks_apply_increment(float current, float amount, dt_masks_increment_t increment, int flow)
Apply a scroll increment to a scalar value.
void dt_masks_set_source_pos_initial_value(dt_masks_form_gui_t *mask_gui, dt_masks_form_t *mask_form)
Initialize the clone source position based on current GUI state.
int dt_masks_find_closest_handle_common(dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui, int form_index, int node_count_override, dt_masks_border_handle_fn border_handle_cb, dt_masks_curve_handle_fn curve_handle_cb, dt_masks_node_position_fn node_position_cb, dt_masks_distance_fn distance_cb, dt_masks_post_select_fn post_select_cb, void *user_data)
Centralized hit-testing for node/handle/segment selection across shapes.
void dt_masks_set_source_pos_initial_state(dt_masks_form_gui_t *mask_gui, const uint32_t key_state)
Decide initial source positioning mode for clone masks.
void dt_masks_gui_form_create(dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui, int form_index, dt_iop_module_t *module)
float dt_masks_get_set_conf_value_with_toast(dt_masks_form_t *mask_form, const char *feature, float amount, float value_min, float value_max, dt_masks_increment_t increment, int flow, const char *toast_fmt, float toast_scale)
Update a mask configuration value and emit a toast message.
void dt_masks_gui_form_save_creation(dt_develop_t *develop, dt_iop_module_t *module, dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui)
Save the form creation right after a shape has been finished drawing.
The interactive half of the masks subsystem: the editing state (dt_masks_form_gui_t),...
static int dt_masks_gui_selected_node_index(const dt_masks_form_gui_t *gui)
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)
static void dt_masks_gui_cursor_to_raw_norm(dt_develop_t *dev, const dt_masks_form_gui_t *gui, float point[2])
static void dt_masks_draw_preview_shape(struct dt_develop_t *dev, cairo_t *cr, const float zoom_scale, const int num_points, float *points, const int points_count, float *border, const int border_count, const shape_draw_function_t *draw_shape, const cairo_line_cap_t shape_cap, const cairo_line_cap_t border_cap, const gboolean save_restore, const gboolean source)
static void dt_masks_preview_buffers_cleanup(dt_masks_preview_buffers_t *buffers)
static gboolean dt_masks_gui_points_reach(const dt_masks_form_gui_points_t *gp, const float x, const float y, const float reach)
static void dt_masks_gui_delta_to_raw_norm(dt_develop_t *dev, const dt_masks_form_gui_t *gui, float point[2])
static void dt_masks_touched_set(dt_iop_roi_t *touched, int x0, int y0, int x1, int y1, const int width, const int height)
static void dt_masks_touched_none(dt_iop_roi_t *touched)
@ DT_MASKS_INTERACTION_OPACITY
@ DT_MASKS_INTERACTION_SIZE
@ DT_MASKS_INTERACTION_FADING
@ DT_MASKS_INTERACTION_ROTATION
@ DT_MASKS_INCREMENT_SCALE
@ DT_MASKS_INCREMENT_OFFSET
#define CLAMPF(a, mn, mx)
dt_mipmap_buffer_dsc_flags flags
static float gh(const float f)
static double reference(const op_t op, const double x)
#define __OMP_PARALLEL_FOR__(...)
#define __OMP_PARALLEL_FOR_SIMD__(...)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
static const dt_aligned_pixel_simd_t value
const float uint32_t state[4]
Objective facts about the image a dev is working on.
struct dt_develop_t * dev
Region of interest passed through the pixelpipe.
shape_draw_function_t draw_shape
struct dt_masks_gui_center_point_t::@27 main
dt_masks_ellipse_flags_t flags
One cut in a shape's border outline: while walking the border buffer forward, on reaching index jump_...
static double dt_get_wtime(void)
Telling the user something happened.