46#define HARDNESS_MIN 0.0005f
47#define HARDNESS_MAX 1.0f
49#define BORDER_MIN 0.00005f
50#define BORDER_MAX 0.5f
52#define RADIUS_CLONE_MIN 0.00005f
53#define RADIUS_CLONE_MAX 0.5f
55#define RADIUS_NON_CLONE_MIN 0.0005f
56#define RADIUS_NON_CLONE_MAX 1.0f
59 const float sinr,
const float cosr,
float *xnew,
float *ynew)
61 const float xtmp = (sinr * sinr + cosr * cosr) * (
x - xref) + (cosr * sinr - cosr * sinr) * (y - yref);
62 const float ytmp = (cosr * sinr - cosr * sinr) * (
x - xref) + (sinr * sinr + cosr * cosr) * (y - yref);
132 float radius2 = mouse_radius * mouse_radius;
134 const float lastx = points[2 * (points_count - 1)];
135 const float lasty = points[2 * (points_count - 1) + 1];
137 for(
int i = 0;
i < points_count;
i++)
139 const float px = points[2 *
i];
140 const float py = points[2 *
i + 1];
142 const float r1 =
x - lastx;
143 const float r2 = y - lasty;
144 const float r3 = px - lastx;
145 const float r4 = py - lasty;
147 const float d = r1 * r3 + r2 * r4;
148 const float l = sqf(r3) + sqf(r4);
149 const float p =
d / l;
151 float xx = 0.0f, yy = 0.0f;
153 if(
p < 0 || (px == lastx && py == lasty))
169 const float dx =
x - xx;
170 const float dy = y - yy;
172 if(sqf(dx) + sqf(dy) < radius2)
return 1;
178 int num_points,
int *inside,
int *inside_border,
int *near,
179 int *inside_source,
float *
dist)
191 const float pt[2] = {
x, y };
202 float min_dist_norm = FLT_MAX;
203 for(
int k=0;
k<5;
k++)
205 const float center_dx =
x - gpt->
source[
k * 2];
206 const float center_dy = y - gpt->
source[
k * 2 + 1];
207 const float dist2 = sqf(center_dx) + sqf(center_dy);
208 min_dist_norm = fminf(min_dist_norm, dist2);
210 *
dist = min_dist_norm;
218 const float center_dx =
x - gpt->
points[0];
219 const float center_dy = y - gpt->
points[1];
220 *
dist = sqf(center_dx) + sqf(center_dy);
225 if(!close_to_border && !in_border)
return;
230 *inside_border = !in_form;
245 values->border =
dt_conf_get_float(use_spot_defaults ?
"plugins/darkroom/spots/ellipse/border"
246 :
"plugins/darkroom/masks/ellipse/border");
247 values->flags =
dt_conf_get_int(use_spot_defaults ?
"plugins/darkroom/spots/ellipse/flags"
248 :
"plugins/darkroom/masks/ellipse/flags");
249 values->radius_a =
dt_conf_get_float(use_spot_defaults ?
"plugins/darkroom/spots/ellipse/radius_a"
250 :
"plugins/darkroom/masks/ellipse/radius_a");
251 values->radius_b =
dt_conf_get_float(use_spot_defaults ?
"plugins/darkroom/spots/ellipse/radius_b"
252 :
"plugins/darkroom/masks/ellipse/radius_b");
253 values->rotation =
dt_conf_get_float(use_spot_defaults ?
"plugins/darkroom/spots/ellipse/rotation"
254 :
"plugins/darkroom/masks/ellipse/rotation");
263 ellipse->
radius[0] = values.radius_a;
264 ellipse->
radius[1] = values.radius_b;
265 ellipse->
border = values.border;
266 ellipse->
rotation = values.rotation;
267 ellipse->
flags = values.flags;
276 float rotation,
float **points,
int *points_count);
287 ? values.radius_a * (1.0f + values.border)
288 : values.radius_a + values.border;
290 ? values.radius_b * (1.0f + values.border)
291 : values.radius_b + values.border;
299 if(!err && values.border > 0.0f)
305 float source_pos[2] = { 0.0f, 0.0f };
307 &source_pos[0], &source_pos[1],
FALSE);
308 const float center_source[2] = { source_pos[0] - gui->
pos[0], source_pos[1] - gui->
pos[1] };
327static float *
_points_to_transform(
float xx,
float yy,
float radius_a,
float radius_b,
float rotation,
float wd,
328 float ht,
int *points_count)
331 const float v = (rotation / 180.0f) *
M_PI;
334 const float a = radius_a *
MIN(wd, ht);
335 const float b = radius_b *
MIN(wd, ht);
337 const float sinv = sinf(
v);
338 const float cosv = cosf(
v);
342 const float lambda = (a - b) / (a + b);
344 100, (
int)((
M_PI * (a + b)
345 * (1.0f + (3.0f * lambda * lambda) / (10.0f + sqrtf(4.0f - 3.0f * lambda * lambda)))) /
n));
354 *points_count = l + 5;
357 float center[2] = { xx, yy };
359 const float x = points[0] = center[0];
360 const float y = points[1] = center[1];
363 points[2] =
x + a * cosv;
364 points[3] = y + a * sinv;
365 points[4] =
x - a * cosv;
366 points[5] = y - a * sinv;
368 points[6] =
x - b * sinv;
369 points[7] = y + b * cosv;
370 points[8] =
x + b * sinv;
371 points[9] = y - b * cosv;
373 for(
int i = 5;
i < l + 5;
i++)
375 const float alpha = (
i - 5) * 2.0 *
M_PI / (
float)l;
376 points[
i * 2] =
x + a * cosf(alpha) * cosv - b * sinf(alpha) * sinv;
377 points[
i * 2 + 1] = y + a * cosf(alpha) * sinv + b * sinf(alpha) * cosv;
384 float radius_b,
float rotation,
float **points,
int *points_count,
398 *points, *points_count))
403 float pts[2] = { xs, ys };
410 const float dx = pts[0] - (*points)[0];
411 const float dy = pts[1] - (*points)[1];
412 (*points)[0] = pts[0];
413 (*points)[1] = pts[1];
415 for(
int i = 5;
i < *points_count;
i++)
417 (*points)[
i * 2] += dx;
418 (*points)[
i * 2 + 1] += dy;
425 *points, *points_count))
439 float rotation,
float **points,
int *points_count)
460 int *points_count,
float **border,
int *border_count,
int source,
466 float x = 0.0f, y = 0.0f, a = 0.0f, b = 0.0f;
473 return _ellipse_get_points_source(dev,
x, y, xs, ys, a, b, ellipse->
rotation, points, points_count, module);
484 border, border_count);
498 float *node_x,
float *node_y,
void *user_data)
500 const float *nodes = gui_points->
points;
501 const float rotation = atan2f(nodes[3] - nodes[1], nodes[2] - nodes[0]);
502 const float sinr = sinf(rotation);
503 const float cosr = cosf(rotation);
505 sinr, cosr, node_x, node_y);
513 int *inside_border,
int *near,
int *inside_source,
float *
dist,
void *user_data)
516 inside_border, near, inside_source,
dist);
525 int inside_source,
void *user_data)
541 increment, flow, _(
"Hardness: %3.2f%%"), 100.0f);
549 dt_toast_log(_(
"Size: %3.2f%%"), fmaxf(mask_radius_a, mask_radius_b) * 2.f * 100.f);
556 increment, flow, _(
"Opacity: %3.2f%%"), 100.f);
563 increment, flow, _(
"Rotation: %3.2f\302\260"), 1.0f);
589 center[0] = ellipse->
center[0];
590 center[1] = ellipse->
center[1];
645 if(amount > 1.0f && (ellipse->
border > 1.0f ))
667 int flow_increased = (flow > 1) ? (flow - 1) * 5 : flow;
718 double pressure,
int which,
int type, uint32_t
state,
823 const float min_radius = fmin(ellipse->
radius[0], ellipse->
radius[1]);
827 ellipse->
flags &= ~DT_MASKS_ELLIPSE_PROPORTIONAL;
831 const float min_radius = fmin(ellipse->
radius[0], ellipse->
radius[1]);
833 ellipse->
border = CLAMP(ellipse->
border, 0.001f/min_radius, 1.0f/min_radius);
908 ellipse->
center[0] = pts[0];
909 ellipse->
center[1] = pts[1];
927 const float xref = gpt->
points[0];
928 const float yref = gpt->
points[1];
929 const float rx = gpt->
points[
k * 2] - xref;
930 const float ry = gpt->
points[
k * 2 + 1] - yref;
931 const float deltax = gui->
pos[0] + gui->
delta[0] - xref;
932 const float deltay = gui->
pos[1] + gui->
delta[1] - yref;
938 const float r = sqrtf(rx * rx + ry * ry);
939 const float d = (rx * deltax + ry * deltay) /
r;
940 const float s = fmaxf(
r > 0.0f ? (
r +
d) /
r : 0.0f, 0.0f);
950 else if(
k == 3 ||
k == 4)
969 const float origin_point[2] = { gpt->
points[0], gpt->
points[1] };
984static void _ellipse_draw_shape(cairo_t *cr,
const float *points,
const int points_count,
const int nb,
const gboolean border,
const gboolean source)
986 cairo_move_to(cr, points[10], points[11]);
987 for(
int t = 6;
t < points_count;
t++)
989 const float x = points[
t * 2];
990 const float y = points[
t * 2 + 1];
992 cairo_line_to(cr,
x, y);
994 cairo_close_path(cr);
1003 const float *nodes = gpt->
points;
1006 const float r = atan2f(nodes[3] - nodes[1], nodes[2] - nodes[0]);
1007 const float sinr = sinf(
r);
1008 const float cosr = cosf(
r);
1010 for(
int i = 1;
i < 5;
i++)
1014 const gboolean action = (
i == selected_node);
1087 float xmin = FLT_MAX, xmax = FLT_MIN, ymin = FLT_MAX, ymax = FLT_MIN;
1088 for(
int i = 1;
i < num_points;
i++)
1090 xmin = fminf(points[
i * 2], xmin);
1091 xmax = fmaxf(points[
i * 2], xmax);
1092 ymin = fminf(points[
i * 2 + 1], ymin);
1093 ymax = fmaxf(points[
i * 2 + 1], ymax);
1098 *
width = (xmax - xmin);
1102static void _fill_mask(
const size_t numpoints,
float *
const bufptr,
const float *
const points,
1103 const float *
const center,
const float a,
const float b,
const float ta,
const float tb,
1104 const float alpha,
const size_t out_scale)
1106 const float a2 = a * a;
1107 const float b2 = b * b;
1108 const float ta2 = ta * ta;
1109 const float tb2 = tb * tb;
1110 const float cos_alpha = cosf(alpha);
1111 const float sin_alpha = sinf(alpha);
1120 for(
size_t i = 0;
i < numpoints;
i++)
1122 const float x = points[2 *
i] - center[0];
1123 const float y = points[2 *
i + 1] - center[1];
1125 const float l2 =
x *
x + y * y;
1126 const float l = sqrtf(
l2);
1128 const float x_norm = l ?
x / l : 0.0f;
1129 const float y_norm = l ? y / l : 1.0f;
1131 const float x_rot = x_norm * cos_alpha + y_norm * sin_alpha;
1132 const float y_rot = -x_norm * sin_alpha + y_norm * cos_alpha;
1134 const float cosv2 = x_rot * x_rot;
1135 const float sinv2 = y_rot * y_rot;
1138 const float radius2 = a2 * b2 / (a2 * sinv2 + b2 * cosv2);
1139 const float total2 = ta2 * tb2 / (ta2 * sinv2 + tb2 * cosv2);
1143 const float ratio = (total2 -
l2) / (total2 - radius2);
1145 const float f =
CLIP(ratio);
1146 bufptr[
i << out_scale] =
f *
f;
1151 const float rotation,
const float wd,
const float ht,
size_t *point_count)
1154 const float v1 = ((rotation) / 180.0f) *
M_PI;
1155 const float v2 = ((rotation - 90.0f) / 180.0f) *
M_PI;
1156 float a = 0.0f, b = 0.0f,
v = 0.0f;
1171 const float sinv = sinf(
v);
1172 const float cosv = cosf(
v);
1175 const float lambda = (a - b) / (a + b);
1176 const int l = (int)(
M_PI * (a + b)
1177 * (1.0f + (3.0f * lambda * lambda) / (10.0f + sqrtf(4.0f - 3.0f * lambda * lambda))));
1183 *point_count = l + 5;
1186 float center[2] = { center_x, center_y };
1188 const float x = points[0] = center[0];
1189 const float y = points[1] = center[1];
1191 points[2] =
x + a * cosf(
v);
1192 points[3] = y + a * sinf(
v);
1193 points[4] =
x - a * cosf(
v);
1194 points[5] = y - a * sinf(
v);
1195 points[6] =
x + b * cosf(
v -
M_PI / 2.0f);
1196 points[7] = y + b * sinf(
v -
M_PI / 2.0f);
1197 points[8] =
x - b * cosf(
v -
M_PI / 2.0f);
1198 points[9] = y - b * sinf(
v -
M_PI / 2.0f);
1200 for(
int i = 5;
i < l + 5;
i++)
1202 float alpha = (
i - 5) * 2.0 *
M_PI / (
float)l;
1203 points[
i * 2] =
x + a * cosf(alpha) * cosv - b * sinf(alpha) * sinv;
1204 points[
i * 2 + 1] = y + a * cosf(alpha) * sinv + b * sinf(alpha) * cosv;
1219 const float total[2] = { (prop ? ellipse->
radius[0] * (1.0f + ellipse->
border) : ellipse->
radius[0] + ellipse->
border) *
MIN(wd, ht),
1223 size_t point_count = 0;
1224 float *
const restrict points
1253 const float total[2] = { (prop ? ellipse->
radius[0] * (1.0f + ellipse->
border) : ellipse->
radius[0] + ellipse->
border) *
MIN(wd, ht),
1257 size_t point_count = 0;
1258 float *
const restrict points
1279 float **buffer,
int *
width,
int *
height,
int *posx,
int *posy)
1282 double start2 = 0.0;
1299 const int posx_ = *posx;
1300 const int posy_ = *posy;
1305 for(
int i = 0;
i < h;
i++)
1306 for(
int j = 0; j < w; j++)
1308 points[(
i * w + j) * 2] = (j + posx_);
1309 points[(
i * w + j) * 2 + 1] = (
i + posy_);
1342 const float center[2] = { ellipse->
center[0] * wi, ellipse->
center[1] * hi };
1343 const float radius[2] = { ellipse->
radius[0] *
MIN(wi, hi), ellipse->
radius[1] *
MIN(wi, hi) };
1347 float a = 0.0F, b = 0.0F, ta = 0.0F, tb = 0.0F, alpha = 0.0F;
1349 if(radius[0] >= radius[1])
1366 float *
const bufptr = *buffer;
1368 _fill_mask((
size_t)(h)*w, bufptr, points, center, a, b, ta, tb, alpha, 0);
1384 double start1 = 0.0;
1385 double start2 = start1;
1392 const float center[2] = { ellipse->
center[0] * wi, ellipse->
center[1] * hi };
1393 const float radius[2] = { ellipse->
radius[0] *
MIN(wi, hi), ellipse->
radius[1] *
MIN(wi, hi) };
1397 const float a = radius[0];
1398 const float b = radius[1];
1399 const float ta = total[0];
1400 const float tb = total[1];
1401 const float alpha = (ellipse->
rotation / 180.0f) *
M_PI;
1402 const float cosa = cosf(alpha);
1403 const float sina = sinf(alpha);
1407 const int w = roi->
width;
1408 const int h = roi->
height;
1409 const int px = roi->
x;
1410 const int py = roi->
y;
1413 const float grid_scale = 1.0f /
MAX(roi->
scale, 1e-6f);
1414 const int grid = CLAMP((10.0f * grid_scale + 2.0f) / 3.0f, 1, 4);
1415 const int gw = (w + grid - 1) / grid + 1;
1416 const int gh = (h + grid - 1) / grid + 1;
1426 const float lambda = (ta - tb) / (ta + tb);
1427 const int l = (int)(
M_PI * (ta + tb) * (1.0f + (3.0f * lambda * lambda) / (10.0f + sqrtf(4.0f - 3.0f * lambda * lambda))));
1428 const size_t ellpts =
MIN(360, l);
1432 for(
int n = 0;
n < ellpts;
n++)
1434 const float phi = (2.0f *
M_PI *
n) / ellpts;
1435 const float cosp = cosf(phi);
1436 const float sinp = sinf(phi);
1437 ell[2 *
n] = center[0] + ta * cosa * cosp - tb * sina * sinp;
1438 ell[2 *
n + 1] = center[1] + ta * sina * cosp + tb * cosa * sinp;
1462 float xmin = FLT_MAX, ymin = FLT_MAX, xmax = FLT_MIN, ymax = FLT_MIN;
1463 for(
int n = 0;
n < ellpts;
n++)
1466 if(!(isnormal(ell[2 *
n]) && isnormal(ell[2 *
n + 1])))
continue;
1468 xmin =
MIN(xmin, ell[2 *
n]);
1469 xmax =
MAX(xmax, ell[2 *
n]);
1470 ymin =
MIN(ymin, ell[2 *
n + 1]);
1471 ymax =
MAX(ymax, ell[2 *
n + 1]);
1475 printf(
"xmin %f, xmax %f, ymin %f, ymax %f\n", xmin, xmax, ymin, ymax);
1476 printf(
"wi %d, hi %d, iscale %f\n", wi, hi,
iscale);
1477 printf(
"w %d, h %d, px %d, py %d\n", w, h, px, py);
1481 const int bbxm = CLAMP((
int)floorf(xmin /
iscale - px) / grid - 1, 0, gw - 1);
1482 const int bbXM = CLAMP((
int)ceilf(xmax /
iscale - px) / grid + 2, 0, gw - 1);
1483 const int bbym = CLAMP((
int)floorf(ymin /
iscale - py) / grid - 1, 0,
gh - 1);
1484 const int bbYM = CLAMP((
int)ceilf(ymax /
iscale - py) / grid + 2, 0,
gh - 1);
1485 const int bbw = bbXM - bbxm + 1;
1486 const int bbh = bbYM - bbym + 1;
1489 printf(
"bbxm %d, bbXM %d, bbym %d, bbYM %d\n", bbxm, bbXM, bbym, bbYM);
1490 printf(
"gw %d, gh %d, bbw %d, bbh %d\n", gw,
gh, bbw, bbh);
1503 if(bbw <= 1 || bbh <= 1)
1511 for(
int j = bbym; j <= bbYM; j++)
1512 for(
int i = bbxm;
i <= bbXM;
i++)
1514 const size_t index = (size_t)(j - bbym) * bbw +
i - bbxm;
1515 points[index * 2] = (grid *
i + px) *
iscale;
1516 points[index * 2 + 1] = (grid * j + py) *
iscale;
1542 _fill_mask((
size_t)(bbh)*bbw, points, points, center, a, b, ta, tb, alpha, 1);
1553 const int endx =
MIN(w, bbXM * grid);
1554 const int endy =
MIN(h, bbYM * grid);
1555 const float inv_grid2 = 1.0f / (grid * grid);
1557 for(
int i = 0;
i < grid;
i++)
1559 w0[
i] = (float)(grid -
i);
1563 for(
int j = bbym * grid; j < endy; j++)
1565 const int jj = j % grid;
1566 const int mj = j / grid - bbym;
1567 const float wj0 = w0[jj];
1568 const float wj1 =
w1[jj];
1569 const size_t row_base = (size_t)mj * bbw;
1570 float *
const row = buffer + (size_t)j * w;
1573 for(
int i = bbxm * grid;
i < endx;
i++)
1575 const size_t mindex = row_base + mi;
1576 const float wii0 = w0[ii];
1577 const float wii1 =
w1[ii];
1578 row[
i] = (points[mindex * 2] * wii0 * wj0
1579 + points[(mindex + 1) * 2] * wii1 * wj0
1580 + points[(mindex + bbw) * 2] * wii0 * wj1
1581 + points[(mindex + bbw + 1) * 2] * wii1 * wj1) * inv_grid2;
1604 snprintf(form->
name,
sizeof(form->
name), _(
"ellipse #%d"), (
int)nb);
1617 const float radius_a =
dt_conf_get_float(
"plugins/darkroom/spots/ellipse/radius_a");
1618 const float radius_b =
dt_conf_get_float(
"plugins/darkroom/spots/ellipse/radius_b");
1619 float offset[2] = { radius_a, -radius_b };
1626 const int opacity,
char *
const restrict msgbuf,
const size_t msgbuf_len)
1629 g_snprintf(msgbuf, msgbuf_len,
1630 _(
"<b>Size</b>: scroll, <b>Hardness</b>: shift+scroll\n"
1631 "<b>Rotate</b>: ctrl+shift+scroll, <b>Opacity</b>: ctrl+scroll (%d%%)"), opacity);
1633 g_snprintf(msgbuf, msgbuf_len,
1634 _(
"<b>Hardness mode</b>: shift+click, <b>Size</b>: scroll\n"
1635 "<b>Hardness</b>: shift+scroll, <b>Opacity</b>: ctrl+scroll (%d%%)"), opacity);
1641 float radius_a = 0.0f;
1642 float radius_b = 0.0f;
1643 float border = 0.0f;
1661 const float ratio = radius_a / radius_b;
1663 if(radius_a > radius_b)
1665 radius_a =
CLAMPS(radius_a, 0.001f, 0.5f);
1666 radius_b = radius_a / ratio;
1670 radius_b =
CLAMPS(radius_b, 0.001f, 0.5);
1671 radius_a = ratio * radius_b;
1675 border =
CLAMPS(border, 0.001f * reference, reference);
static double dist(double x1, double y1, double x2, double y2)
static void error(char *msg)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
const dt_aligned_pixel_t f
#define DT_CONF_SET_SANITIZED_FLOAT(name, val, min, max)
void dt_conf_set_float(const char *name, float val)
float dt_conf_get_float(const char *name)
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)
float dt_conf_get_and_sanitize_float(const char *name, float min, float max)
void dt_toast_log(const char *msg,...)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
#define __OMP_PARALLEL_FOR__(...)
static const dt_aligned_pixel_simd_t value
static double dt_get_wtime(void)
#define __OMP_PARALLEL_FOR_SIMD__(...)
static gboolean dt_modifier_is(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
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_EXCL
@ DT_DEV_TRANSFORM_DIR_BACK_INCL
@ DT_DEV_TRANSFORM_DIR_FORW_INCL
static void dt_draw_shape_lines(const dt_draw_dash_type_t dash_type, const gboolean source, cairo_t *cr, const int nb, const gboolean selected, const float zoom_scale, const float *points, const int points_count, const shape_draw_function_t *draw_shape_func, const cairo_line_cap_t line_cap)
Draw the lines of a mask shape.
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 int _ellipse_get_points_border(dt_develop_t *dev, struct dt_masks_form_t *form, float **points, int *points_count, float **border, int *border_count, int source, const dt_iop_module_t *module)
static gboolean _ellipse_get_gravity_center(const dt_masks_form_t *form, float center[2], float *area)
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 int _init_hardness(dt_masks_form_t *form, const float amount, const dt_masks_increment_t increment, const int flow)
static float *const _ellipse_points_to_transform(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 void _ellipse_sanitize_config(dt_masks_type_t type)
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 void _ellipse_initial_source_pos(const float iwd, const float iht, float *x, float *y)
static int _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 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, int *inside_source, float *dist, void *user_data)
Ellipse-specific inside/border hit testing adapter.
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 _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_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 int _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)
static int _change_hardness(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_draw_shape(cairo_t *cr, const float *points, const int points_count, const int nb, const gboolean border, const gboolean source)
static int _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_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, int *inside_source, float *dist)
static void _ellipse_set_hint_message(const dt_masks_form_gui_t *const gui, const dt_masks_form_t *const form, const int opacity, char *const restrict msgbuf, const size_t msgbuf_len)
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 float * _points_to_transform(float xx, float yy, float radius_a, float radius_b, float rotation, float wd, float ht, int *points_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_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 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 int _init_rotation(dt_masks_form_t *form, const float amount, const dt_masks_increment_t increment, const int flow)
static void _bounding_box(const float *const points, int num_points, int *width, int *height, int *posx, int *posy)
float *const restrict const size_t k
static int dt_masks_gui_selected_node_index(const dt_masks_form_gui_t *gui)
void dt_masks_calculate_source_pos_origin(dt_masks_form_gui_t *gui, const float initial_xpos, const float initial_ypos, const float xpos, const float ypos, float *px, float *py, const int adding)
Compute preview-space source position for drawing the clone indicator.
void dt_masks_gui_form_create(dt_masks_form_t *form, dt_masks_form_gui_t *gui, int index, struct dt_iop_module_t *module)
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)
int dt_masks_form_change_opacity(dt_masks_form_t *form, int parentid, int up, const int flow)
int dt_masks_point_in_form_exact(const float *pts, int num_pts, const float *points, int points_start, int points_count)
Check whether any 2D point in pts[] lies inside the form points[].
void dt_masks_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.
void dt_masks_gui_form_save_creation(dt_develop_t *dev, struct dt_iop_module_t *module, dt_masks_form_t *form, dt_masks_form_gui_t *gui)
Save the form creation right after a shape has been finished drawing.
float dt_masks_get_set_conf_value(dt_masks_form_t *form, char *feature, float new_value, float v_min, float v_max, dt_masks_increment_t increment, const int flow)
Change a numerical property of a mask shape, either by in/de-crementing the current value or setting ...
void dt_masks_draw_source(cairo_t *cr, dt_masks_form_gui_t *gui, const int index, const int nb, const float zoom_scale, struct dt_masks_gui_center_point_t *center_point, const shape_draw_function_t *draw_shape_func)
Draw the source for a correction mask.
@ DT_MASKS_INTERACTION_HARDNESS
@ DT_MASKS_INTERACTION_SIZE
static void dt_masks_gui_cursor_to_raw_norm(dt_develop_t *dev, const dt_masks_form_gui_t *gui, float point[2])
@ DT_MASKS_ELLIPSE_PROPORTIONAL
@ DT_MASKS_ELLIPSE_EQUIDISTANT
static void dt_masks_preview_buffers_cleanup(dt_masks_preview_buffers_t *buffers)
float dt_masks_apply_increment(float current, float amount, dt_masks_increment_t increment, int flow)
Apply a scroll increment to a scalar value.
static gboolean dt_masks_form_is_clone(const dt_masks_form_t *form)
float dt_masks_get_set_conf_value_with_toast(dt_masks_form_t *form, const char *feature, float amount, float v_min, float v_max, dt_masks_increment_t increment, int flow, const char *toast_fmt, float toast_scale)
Update a mask configuration value and emit a toast message.
float dt_masks_rotate_with_anchor(dt_develop_t *dev, const float anchor[2], const float center[2], dt_masks_form_gui_t *gui)
Rotate a mask shape around its center. WARNING: gui->delta will be updated with the new position afte...
@ DT_MASKS_INCREMENT_SCALE
@ DT_MASKS_INCREMENT_OFFSET
void dt_masks_set_source_pos_initial_value(dt_masks_form_gui_t *gui, dt_masks_form_t *form)
Initialize the clone source position based on current GUI state.
static void dt_masks_draw_preview_shape(cairo_t *cr, const float zoom_scale, const int num_points, float *points, const int points_count, float *border, const int border_count, void(*const *draw_shape)(cairo_t *cr, const float *points, const int points_count, const int nb, const gboolean border, const gboolean source), const cairo_line_cap_t shape_cap, const cairo_line_cap_t border_cap, const gboolean save_restore, const gboolean source)
int dt_masks_find_closest_handle_common(dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui, int form_index, int node_count_override, dt_masks_border_handle_fn border_handle_cb, dt_masks_curve_handle_fn curve_handle_cb, dt_masks_node_position_fn node_position_cb, dt_masks_distance_fn distance_cb, dt_masks_post_select_fn post_select_cb, void *user_data)
Shared selection logic for node/handle/segment hit testing.
dt_masks_form_t * dt_masks_get_visible_form(const struct dt_develop_t *dev)
static void dt_masks_gui_delta_to_raw_norm(dt_develop_t *dev, const dt_masks_form_gui_t *gui, float point[2])
void dt_masks_set_source_pos_initial_state(dt_masks_form_gui_t *gui, const uint32_t state)
Decide initial source positioning mode for clone masks.
static gboolean dt_masks_form_uses_spot_defaults(const dt_masks_form_t *form)
static void dt_masks_reset_source(dt_masks_form_t *form)
#define CLAMPF(a, mn, mx)
dt_mipmap_buffer_dsc_flags flags
static float gh(const float f)
const float uint32_t state[4]
struct dt_develop_t * develop
struct dt_dev_pixelpipe_t * virtual_pipe
struct dt_develop_t::@17 roi
Region of interest passed through the pixelpipe.
void(* draw_shape)(cairo_t *cr, const float *points, const int points_count, const int nb, const gboolean border, const gboolean source)
struct dt_masks_gui_center_point_t::@34 main
dt_masks_ellipse_flags_t flags