42#define extent_MIN 0.0005f
43#define extent_MAX 1.0f
44#define CURVATURE_MIN -2.0f
45#define CURVATURE_MAX 2.0f
47#define BORDER_MIN 0.00005f
48#define BORDER_MAX 0.5f
58#pragma omp parallel for reduction(min:found) if(count > 1000)
59 for(
int i = 0;
i < count;
i++)
61 if(!isfinite(border[
i * 2]) && !isfinite(border[
i * 2 + 1]))
64 return (found == count) ? -1 : found;
66 for(
int i = 0;
i < count;
i++)
68 if(!isfinite(border[
i * 2]) && !isfinite(border[
i * 2 + 1]))
78 float *closest_x,
float *closest_y,
float *distance_sq)
80 const float seg_dx = x2 - x1;
81 const float seg_dy = y2 - y1;
82 const float seg_length_sq = seg_dx * seg_dx + seg_dy * seg_dy;
84 if(seg_length_sq < 1e-10f)
89 *distance_sq = (px - x1) * (px - x1) + (py - y1) * (py - y1);
94 const float t = fmaxf(0.0f, fminf(1.0f,
95 ((px - x1) * seg_dx + (py - y1) * seg_dy) / seg_length_sq));
97 *closest_x = x1 +
t * seg_dx;
98 *closest_y = y1 +
t * seg_dy;
99 *distance_sq = (px - *closest_x) * (px - *closest_x) + (py - *closest_y) * (py - *closest_y);
104 float *closest_x,
float *closest_y,
float *min_distance_sq)
106 *min_distance_sq = FLT_MAX;
107 *closest_x = *closest_y = 0.0f;
109 if(start_idx >= end_idx - 1)
return;
112 float global_min = FLT_MAX;
113 float global_x = 0.0f, global_y = 0.0f;
117 float local_min = FLT_MAX;
118 float local_x = 0.0f, local_y = 0.0f;
120#pragma omp for nowait
121 for(
int i = start_idx;
i < end_idx - 1;
i++)
123 float seg_closest_x, seg_closest_y, seg_dist_sq;
125 border[
i * 2], border[
i * 2 + 1],
126 border[(
i + 1) * 2], border[(
i + 1) * 2 + 1],
127 &seg_closest_x, &seg_closest_y, &seg_dist_sq);
129 if(seg_dist_sq < local_min)
131 local_min = seg_dist_sq;
132 local_x = seg_closest_x;
133 local_y = seg_closest_y;
137 if(local_min < global_min)
141 if(local_min < global_min)
143 global_min = local_min;
151 *min_distance_sq = global_min;
152 *closest_x = global_x;
153 *closest_y = global_y;
155 for(
int i = start_idx;
i < end_idx - 1;
i++)
157 float seg_closest_x, seg_closest_y, seg_dist_sq;
159 border[
i * 2], border[
i * 2 + 1],
160 border[(
i + 1) * 2], border[(
i + 1) * 2 + 1],
161 &seg_closest_x, &seg_closest_y, &seg_dist_sq);
163 if(seg_dist_sq < *min_distance_sq)
165 *min_distance_sq = seg_dist_sq;
166 *closest_x = seg_closest_x;
167 *closest_y = seg_closest_y;
175 const float gradient_dx = gpt->
points[2] - gpt->
points[0];
176 const float gradient_dy = gpt->
points[3] - gpt->
points[1];
177 return gradient_dx * gradient_dx + gradient_dy * gradient_dy;
193 values->rotation =
dt_conf_get_float(
"plugins/darkroom/masks/gradient/rotation");
194 if(!isfinite(values->rotation)) values->rotation = 0.0f;
202 gradient->
extent = values.extent;
204 gradient->
rotation = values.rotation;
208 float **points,
int *points_count);
210 float curvature,
float **points,
int *points_count);
225 if(!err && values.extent > 0.0f)
227 values.extent, values.curvature, &preview->
border,
233 int num_points,
int *inside,
int *inside_border,
int *near,
234 int *inside_source,
float *
dist)
242 const float sqr_dist_mouse = dist_mouse * dist_mouse;
247 float min_dist = FLT_MAX;
254 if(separator_idx > 0 && separator_idx < gpt->border_count - 1)
259 if(gradient_len_sq > 1e-12f)
262 float closest_x1, closest_y1, dist1_sq;
263 float closest_x2, closest_y2, dist2_sq;
266 &closest_x1, &closest_y1, &dist1_sq);
269 &closest_x2, &closest_y2, &dist2_sq);
272 if(dist1_sq < FLT_MAX && dist2_sq < FLT_MAX)
275 const float to_line1_x = closest_x1 -
x;
276 const float to_line1_y = closest_y1 - y;
277 const float to_line2_x = closest_x2 -
x;
278 const float to_line2_y = closest_y2 - y;
280 const float gradient_dx = gpt->
points[2] - gpt->
points[0];
281 const float gradient_dy = gpt->
points[3] - gpt->
points[1];
284 const float proj1 = to_line1_x * gradient_dx + to_line1_y * gradient_dy;
285 const float proj2 = to_line2_x * gradient_dx + to_line2_y * gradient_dy;
288 const gboolean between_lines = (proj1 * proj2 < 0.0f);
289 if(between_lines) *inside_border = 1;
292 const float min_dist_sq = fminf(dist1_sq, dist2_sq);
293 float handle_radius_sq =
CLAMPF(gradient_len_sq * 0.125f, sqr_dist_mouse, sqr_dist_mouse * 5);
295 if(min_dist_sq <= handle_radius_sq)
307 const float xx = gpt->
points[
i * 2];
308 const float yy = gpt->
points[
i * 2 + 1];
310 const float dx =
x - xx;
311 const float dy = y - yy;
312 const float dd = sqf(dx) + sqf(dy);
314 min_dist = fminf(min_dist, dd);
318 if(dd < sqr_dist_mouse)
327 float *node_x,
float *node_y,
void *user_data)
329 if(node_x) *node_x = NAN;
330 if(node_y) *node_y = NAN;
335 int *inside_border,
int *near,
int *inside_source,
float *
dist,
void *user_data)
338 inside_border, near, inside_source,
dist);
342 int inside_source,
void *user_data)
349 else if(inside_border)
367 increment, flow, _(
"extent: %3.2f%%"), 100.0f);
374 increment, flow, _(
"Curvature: %3.2f%%"), 50.f);
381 increment, flow, _(
"Opacity: %3.2f%%"), 100.f);
388 increment, flow, _(
"Rotation: %3.2f\302\260"), 1.0f);
416 center[0] = gradient->
center[0];
417 center[1] = gradient->
center[1];
480 if(amount > 2.0f && (gradient->
curvature > 2.0f ))
486 if(node_hovered == -1 || node_hovered == 0)
506 int flow_increased = (flow > 1) ? (flow - 1) * 5 : flow;
557 double pressure,
int which,
int type, uint32_t
state,
586 if(
type == GDK_2BUTTON_PRESS)
707 gradient->
center[0] = pts[0];
708 gradient->
center[1] = pts[1];
719 const float origin_point[2] = { gpt->
points[0], gpt->
points[1] };
734 return (isnormal(
x) && isnormal(y) && (
x >= -wd) && (
x <= 2 * wd) && (y >= -ht) && (y <= 2 * ht)) ?
TRUE :
FALSE;
746 float **points,
int *points_count)
753 if(!isfinite(wd) || !isfinite(ht) || wd <= 0.0f || ht <= 0.0f)
return 1;
755 const float scale = sqrtf(wd * wd + ht * ht);
756 const float distance = 0.1f * fminf(wd, ht);
758 const float v = (-rotation / 180.0f) *
M_PI;
759 const float cosv = cosf(
v);
760 const float sinv = sinf(
v);
762 const int count = sqrtf(wd * wd + ht * ht) + 3;
767 float center[2] = {
x, y };
769 const float center_x = center[0];
770 const float center_y = center[1];
771 (*points)[0] = center_x;
772 (*points)[1] = center_y;
775 const float v1 = (-(rotation - 90.0f) / 180.0f) *
M_PI;
776 const float x1 = center[0] + distance * cosf(v1);
777 const float y1 = center[1] + distance * sinf(v1);
780 const float v2 = (-(rotation + 90.0f) / 180.0f) *
M_PI;
781 const float x2 = center[0] + distance * cosf(v2);
782 const float y2 = center[1] + distance * sinf(v2);
787 size_t c_padded_size;
789 size_t pts_padded_size;
802 const float xstart = fabsf(curvature) > 1.0f ? -sqrtf(1.0f / fabsf(curvature)) : -1.0f;
803 const float xdelta = -2.0f * xstart / (count - 3);
807 for(
int i = 3;
i < count;
i++)
809 const float xi = xstart + (
i - 3) * xdelta;
810 const float yi = curvature * xi * xi;
811 const float xii = (cosv * xi + sinv * yi) * scale;
812 const float yii = (sinv * xi - cosv * yi) * scale;
813 const float xiii = xii + center_x;
814 const float yiii = yii + center_y;
818 if(!(xiii < -wd || xiii > 2 * wd || yiii < -ht || yiii > 2 * ht))
822 tpts[*tcount * 2] = xiii;
823 tpts[*tcount * 2 + 1] = yiii;
829 for(
int thread = 0; thread < nthreads; thread++)
831 const uint32_t tcount = *(uint32_t *)
dt_get_bythread(pts_count, c_padded_size, thread);
832 const float *
const tpts =
dt_get_bythread(pts, pts_padded_size, thread);
835 for(uint32_t
k = 0;
k < tcount && *points_count < count;
k++)
837 (*points)[(*points_count) * 2] = tpts[
k * 2];
838 (*points)[(*points_count) * 2 + 1] = tpts[
k * 2 + 1];
861 for(
int i = 3;
i < count;
i++, (*k)++)
863 dest[(*k) * 2] = src[
i * 2];
864 dest[(*k) * 2 + 1] = src[
i * 2 + 1];
869 float curvature,
float **points,
int *points_count)
878 const float scale = sqrtf(wd * wd + ht * ht);
881 const float v1 = (-(rotation - 90.0f) / 180.0f) *
M_PI;
882 const float v2 = (-(rotation + 90.0f) / 180.0f) *
M_PI;
885 float center[2] = {
x, y };
887 float offsets[4] = { center[0] + distance * scale * cosf(v1),
888 center[1] + distance * scale * sinf(v1),
889 center[0] + distance * scale * cosf(v2),
890 center[1] + distance * scale * sinf(v2) };
892 const float x1 = offsets[0];
893 const float y1 = offsets[1];
894 const float x2 = offsets[2];
895 const float y2 = offsets[3];
898 float *points1 = NULL, *points2 = NULL;
899 int points_count1 = 0, points_count2 = 0;
900 const int err1 =
_gradient_get_points(dev, x1, y1, rotation, curvature, &points1, &points_count1);
901 const int err2 =
_gradient_get_points(dev, x2, y2, rotation, curvature, &points2, &points_count2);
904 const gboolean valid1 = (err1 == 0) && points_count1 > 4;
905 const gboolean valid2 = (err2 == 0) && points_count2 > 4;
912 const int total_points = (points_count1 - 3) + (points_count2 - 3) + 1;
916 *points_count = total_points;
920 (*points)[
k * 2] = (*points)[
k * 2 + 1] = INFINITY;
928 *points_count = points_count1 - 3;
939 *points_count = points_count2 - 3;
954static void _gradient_draw_shape(cairo_t *cr,
const float *pts_line,
const int pts_line_count,
const int nb,
const gboolean border,
const gboolean source)
957 if(border && pts_line_count <= 3)
return;
958 if(!border && pts_line_count <= 4)
return;
960 const float *points = (border) ? pts_line : pts_line + 6;
961 const int points_count = (border) ? pts_line_count : pts_line_count - 3;
967 while(
i < points_count)
969 const float px = points[
i * 2];
970 const float py = points[
i * 2 + 1];
978 cairo_move_to(cr, px, py);
982 while(
i < points_count)
984 const float qx = points[
i * 2];
985 const float qy = points[
i * 2 + 1];
987 cairo_line_to(cr, qx, qy);
993static void _gradient_draw_arrow(cairo_t *cr,
const gboolean selected,
const gboolean pivot_selected,
const gboolean is_rotating,
994 const float zoom_scale,
float *pts,
int pts_count)
996 if(pts_count < 3)
return;
998 const float anchor_x = pts[0];
999 const float anchor_y = pts[1];
1000 const float pivot_end_x = pts[2];
1001 const float pivot_end_y = pts[3];
1002 const float pivot_start_x = pts[4];
1003 const float pivot_start_y = pts[5];
1009 const float scale = 1 / zoom_scale;
1010 const float dx = pivot_end_x - pivot_start_x;
1011 const float dy = pivot_end_y - pivot_start_y;
1013 const float new_x1 = pivot_start_x - (dx * scale * 0.5f);
1014 const float new_y1 = pivot_start_y - (dy * scale * 0.5f);
1015 const float new_x2 = pivot_end_x + (dx * scale * 0.5f);
1016 const float new_y2 = pivot_end_y + (dy * scale * 0.5f);
1017 cairo_move_to(cr, new_x1, new_y1);
1018 cairo_line_to(cr, new_x2, new_y2);
1026 const float arrow_angle = 0.25f;
1030 const float dx = pivot_end_x - anchor_x;
1031 const float dy = pivot_end_y - anchor_y;
1032 const float angle_dir = atan2f(dy, dx);
1035 const float tip_x = anchor_x + arrow_length * cosf(angle_dir);
1036 const float tip_y = anchor_y + arrow_length * sinf(angle_dir);
1039 const float half_w = arrow_length * tanf(arrow_angle);
1042 const float nx = -sinf(angle_dir);
1043 const float ny = cosf(angle_dir);
1046 const float arrow_x1 = anchor_x + nx * half_w;
1047 const float arrow_y1 = anchor_y + ny * half_w;
1048 const float arrow_x2 = anchor_x - nx * half_w;
1049 const float arrow_y2 = anchor_y - ny * half_w;
1052 cairo_move_to(cr, tip_x, tip_y);
1053 cairo_line_to(cr, arrow_x1, arrow_y1);
1054 cairo_line_to(cr, arrow_x2, arrow_y2);
1055 cairo_close_path(cr);
1058 cairo_fill_preserve(cr);
1060 cairo_set_line_width(cr, line_width);
1110 float **border,
int *border_count,
int source,
1118 points, points_count) != 0)
1123 border, border_count);
1134 float points[8] = { 0.0f, 0.0f, wd, 0.0f, wd, ht, 0.0f, ht };
1141 float xmin = 0.0f, xmax = 0.0f, ymin = 0.0f, ymax = 0.0f;
1142 xmin = ymin = FLT_MAX;
1143 xmax = ymax = FLT_MIN;
1144 for(
int i = 0;
i < 4;
i++)
1146 xmin = fminf(points[
i * 2], xmin);
1147 xmax = fmaxf(points[
i * 2], xmax);
1148 ymin = fminf(points[
i * 2 + 1], ymin);
1149 ymax = fmaxf(points[
i * 2 + 1], ymax);
1155 *
width = (xmax - xmin);
1164 const int bin1 =
i + 1;
1165 const float f =
i - bin0;
1166 return lut[bin1] *
f +
lut[bin0] * (1.0f -
f);
1172 float **buffer,
int *
width,
int *
height,
int *posx,
int *posy)
1175 double start2 = 0.0;
1191 const int w = *
width;
1193 const int px = *posx;
1194 const int py = *posy;
1196 const int gw = (w + grid - 1) / grid + 1;
1197 const int gh = (h + grid - 1) / grid + 1;
1202 for(
int j = 0; j <
gh; j++)
1203 for(
int i = 0;
i < gw;
i++)
1205 points[(j * gw +
i) * 2] = (grid *
i + px);
1206 points[(j * gw +
i) * 2 + 1] = (grid * j + py);
1231 const float wd = pipe->
iwidth;
1232 const float ht = pipe->
iheight;
1233 const float hwscale = 1.0f / sqrtf(wd * wd + ht * ht);
1234 const float ihwscale = 1.0f / hwscale;
1236 const float sinv = sinf(
v);
1237 const float cosv = cosf(
v);
1238 const float xoffset = cosv * gradient->
center[0] * wd + sinv * gradient->
center[1] * ht;
1239 const float yoffset = sinv * gradient->
center[0] * wd - cosv * gradient->
center[1] * ht;
1240 const float extent = fmaxf(gradient->
extent, 0.001f);
1241 const float normf = 1.0f / extent;
1242 const float curvature = gradient->
curvature;
1245 const int lutmax = ceilf(4 * extent * ihwscale);
1246 const int lutsize = 2 * lutmax + 2;
1256 const float distance = (
n - lutmax) * hwscale;
1262 float *clut =
lut + lutmax;
1266 for(
int j = 0; j <
gh; j++)
1268 for(
int i = 0;
i < gw;
i++)
1270 const float x = points[(j * gw +
i) * 2];
1271 const float y = points[(j * gw +
i) * 2 + 1];
1273 const float x0 = (cosv *
x + sinv * y - xoffset) * hwscale;
1274 const float y0 = (sinv *
x - cosv * y - yoffset) * hwscale;
1276 const float distance = y0 - curvature * x0 * x0;
1278 points[(j * gw +
i) * 2] = (distance <= -4.0f * extent) ? 0.0f :
1279 ((distance >= 4.0f * extent) ? 1.0f :
dt_gradient_lookup(clut, distance * ihwscale));
1293 const float inv_grid2 = 1.0f / (grid * grid);
1295 for(
int i = 0;
i < grid;
i++)
1297 w0[
i] = (float)(grid -
i);
1303 for(
int j = 0; j < h; j++)
1305 const int jj = j % grid;
1306 const int mj = j / grid;
1307 const float wj0 = w0[jj];
1308 const float wj1 =
w1[jj];
1309 const size_t row_base = (size_t)mj * gw;
1310 float *
const row = bufptr + (size_t)j * w;
1313 for(
int i = 0;
i < w;
i++)
1315 const size_t pt_index = row_base + mi;
1316 const float wii0 = w0[ii];
1317 const float wii1 =
w1[ii];
1318 row[
i] = (points[2 * pt_index] * wii0 * wj0
1319 + points[2 * (pt_index + 1)] * wii1 * wj0
1320 + points[2 * (pt_index + gw)] * wii0 * wj1
1321 + points[2 * (pt_index + gw + 1)] * wii1 * wj1) * inv_grid2;
1346 double start2 = 0.0;
1353 const int w = roi->
width;
1354 const int h = roi->
height;
1355 const int px = roi->
x;
1356 const int py = roi->
y;
1358 const int grid = CLAMP((10.0f*roi->
scale + 2.0f) / 3.0f, 1, 4);
1359 const int gw = (w + grid - 1) / grid + 1;
1360 const int gh = (h + grid - 1) / grid + 1;
1365 for(
int j = 0; j <
gh; j++)
1366 for(
int i = 0;
i < gw;
i++)
1369 const size_t index = (size_t)j * gw +
i;
1370 points[index * 2] = (grid *
i + px) *
iscale;
1371 points[index * 2 + 1] = (grid * j + py) *
iscale;
1397 const float wd = pipe->
iwidth;
1398 const float ht = pipe->
iheight;
1399 const float hwscale = 1.0f / sqrtf(wd * wd + ht * ht);
1400 const float ihwscale = 1.0f / hwscale;
1402 const float sinv = sinf(
v);
1403 const float cosv = cosf(
v);
1404 const float xoffset = cosv * gradient->
center[0] * wd + sinv * gradient->
center[1] * ht;
1405 const float yoffset = sinv * gradient->
center[0] * wd - cosv * gradient->
center[1] * ht;
1406 const float extent = fmaxf(gradient->
extent, 0.001f);
1407 const float normf = 1.0f / extent;
1408 const float curvature = gradient->
curvature;
1411 const int lutmax = ceilf(4 * extent * ihwscale);
1412 const int lutsize = 2 * lutmax + 2;
1422 const float distance = (
n - lutmax) * hwscale;
1428 float *clut =
lut + lutmax;
1431 for(
int j = 0; j <
gh; j++)
1433 for(
int i = 0;
i < gw;
i++)
1435 const size_t index = (size_t)j * gw +
i;
1436 const float x = points[index * 2];
1437 const float y = points[index * 2 + 1];
1439 const float x0 = (cosv *
x + sinv * y - xoffset) * hwscale;
1440 const float y0 = (sinv *
x - cosv * y - yoffset) * hwscale;
1442 const float distance = y0 - curvature * x0 * x0;
1444 points[index * 2] = (distance <= -4.0f * extent) ? 0.0f : ((distance >= 4.0f * extent) ? 1.0f :
dt_gradient_lookup(clut, distance * ihwscale));
1450 const float inv_grid2 = 1.0f / (grid * grid);
1452 for(
int i = 0;
i < grid;
i++)
1454 w0[
i] = (float)(grid -
i);
1460 for(
int j = 0; j < h; j++)
1462 const int jj = j % grid;
1463 const int mj = j / grid;
1464 const float wj0 = w0[jj];
1465 const float wj1 =
w1[jj];
1466 const size_t row_base = (size_t)mj * gw;
1467 float *
const row = buffer + (size_t)j * w;
1470 for(
int i = 0;
i < w;
i++)
1472 const size_t mindex = row_base + mi;
1473 const float wii0 = w0[ii];
1474 const float wii1 =
w1[ii];
1475 row[
i] = (points[mindex * 2] * wii0 * wj0
1476 + points[(mindex + 1) * 2] * wii1 * wj0
1477 + points[(mindex + gw) * 2] * wii0 * wj1
1478 + points[(mindex + gw + 1) * 2] * wii1 * wj1) * inv_grid2;
1505 snprintf(form->
name,
sizeof(form->
name), _(
"gradient #%d"), (
int)nb);
1509 const int opacity,
char *
const restrict msgbuf,
const size_t msgbuf_len)
1512 g_snprintf(msgbuf, msgbuf_len, _(
"<b>Extent</b>: scroll, <b>Curvature</b>: shift+scroll\n"
1513 "<b>Rotate</b>: shift+drag, <b>Opacity</b>: ctrl+scroll (%d%%)"), opacity);
1515 g_snprintf(msgbuf, msgbuf_len, _(
"<b>Extent</b>: scroll, <b>Curvature</b>: shift+scroll\n"
1516 "<b>Reset curvature</b>: double-click, <b>Opacity</b>: ctrl+scroll (%d%%)"), opacity);
static double dist(double x1, double y1, double x2, double y2)
void cleanup(dt_imageio_module_format_t *self)
const dt_aligned_pixel_t f
void dt_conf_set_float(const char *name, float val)
float dt_conf_get_float(const char *name)
void dt_conf_set_int(const char *name, int val)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_get_bythread(buf, padsize, tnum)
#define dt_pixelpipe_cache_alloc_align_float_cache(pixels, id)
#define dt_pixelpipe_cache_free_align(mem)
#define dt_get_perthread(buf, padsize)
#define __OMP_PARALLEL_FOR__(...)
static const dt_aligned_pixel_simd_t value
static double dt_get_wtime(void)
#define dt_pixelpipe_cache_calloc_perthread(n, objsize, padded_size)
#define __OMP_PARALLEL_FOR_SIMD__(...)
static gboolean dt_modifier_is(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
#define dt_pixelpipe_cache_alloc_perthread_float(n, padded_size)
#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)
void dt_dev_coordinates_raw_abs_to_raw_norm(dt_develop_t *dev, float *points, size_t num_points)
@ DT_DEV_TRANSFORM_DIR_BACK_INCL
#define DT_DRAW_SIZE_LINE
static void dt_draw_stroke_line(const dt_draw_dash_type_t dash_type, const gboolean source, cairo_t *cr, const gboolean selected, const float zoom_scale, const cairo_line_cap_t line_cap)
Stroke a line with style.
#define DT_DRAW_SIZE_LINE_SELECTED
static void dt_draw_set_color_overlay(cairo_t *cr, gboolean bright, double alpha)
#define DT_DRAW_SCALE_ARROW
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 void _gradient_events_post_expose(cairo_t *cr, float zoom_scale, dt_masks_form_gui_t *gui, int index, int nb)
static float _gradient_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 int _gradient_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 _gradient_get_distance(float x, float y, float dist_mouse, dt_masks_form_gui_t *gui, int index, int num_points, int *inside, int *inside_border, int *near, int *inside_source, float *dist)
static int _gradient_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 float _gradient_get_interaction_value(const dt_masks_form_t *form, dt_masks_interaction_t interaction)
static void _closest_point_on_segment(float px, float py, float x1, float y1, float x2, float y2, float *closest_x, float *closest_y, float *distance_sq)
static void _copy_points(float *dest, const float *src, int count, int *k)
static void _gradient_node_position_cb(const dt_masks_form_gui_points_t *gui_points, int node_index, float *node_x, float *node_y, void *user_data)
static void _gradient_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)
static float dt_gradient_lookup(const float *lut, const float i)
static int _gradient_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 _gradient_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 int _gradient_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 void _gradient_draw_shape(cairo_t *cr, const float *pts_line, const int pts_line_count, const int nb, const gboolean border, const gboolean source)
static void _gradient_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 _gradient_get_pts_border(dt_develop_t *dev, float x, float y, float rotation, float distance, float curvature, float **points, int *points_count)
static int _find_border_separator(const float *border, int count)
static int _change_extent(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 _change_curvature(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 _gradient_get_creation_values(dt_masks_gradient_creation_values_t *values)
static void _closest_point_on_line(float px, float py, const float *border, int start_idx, int end_idx, float *closest_x, float *closest_y, float *min_distance_sq)
static int _init_opacity(dt_masks_form_t *form, const float amount, const dt_masks_increment_t increment, const int flow)
static void _gradient_draw_arrow(cairo_t *cr, const gboolean selected, const gboolean pivot_selected, const gboolean is_rotating, const float zoom_scale, float *pts, int pts_count)
static int _find_closest_handle(dt_masks_form_t *mask_form, dt_masks_form_gui_t *mask_gui, int index)
static int _init_extent(dt_masks_form_t *form, const float amount, const dt_masks_increment_t increment, const int flow)
static int _gradient_get_creation_preview(dt_masks_form_gui_t *gui, dt_masks_preview_buffers_t *preview)
static int _init_curvature(dt_masks_form_t *form, const float amount, const dt_masks_increment_t increment, const int flow)
static int _gradient_get_points(dt_develop_t *dev, float x, float y, float rotation, float curvature, float **points, int *points_count)
Build the distorted display polyline for a gradient mask.
static void _gradient_set_form_name(struct dt_masks_form_t *const form, const size_t nb)
static int _gradient_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 _gradient_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 float _gradient_get_border_len_sq(const dt_masks_form_gui_points_t *gpt)
static gboolean _gradient_get_gravity_center(const dt_masks_form_t *form, float center[2], float *area)
static void _gradient_init_new(dt_masks_form_gui_t *gui, dt_masks_anchor_gradient_t *gradient)
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 void _gradient_duplicate_points(dt_develop_t *dev, dt_masks_form_t *const base, dt_masks_form_t *const dest)
static int _gradient_get_mask_roi(const dt_iop_module_t *const module, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *const piece, dt_masks_form_t *const form, const dt_iop_roi_t *roi, float *buffer)
static void _gradient_sanitize_config(dt_masks_type_t type)
static int _init_rotation(dt_masks_form_t *form, const float amount, const dt_masks_increment_t increment, const int flow)
static gboolean _gradient_is_canonical(const float x, const float y, const float wd, const float ht)
static void _gradient_post_select_cb(dt_masks_form_gui_t *mask_gui, int inside, int inside_border, int inside_source, void *user_data)
const dt_masks_functions_t dt_masks_functions_gradient
static int _gradient_get_points_border(dt_develop_t *dev, dt_masks_form_t *form, float **points, int *points_count, float **border, int *border_count, int source, const dt_iop_module_t *module)
const float const int lutsize
float *const restrict const size_t k
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)
int dt_masks_form_change_opacity(dt_masks_form_t *form, int parentid, int up, const int flow)
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.
@ DT_MASKS_INTERACTION_HARDNESS
@ DT_MASKS_INTERACTION_SIZE
@ DT_MASKS_INTERACTION_ROTATION
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_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.
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
@ DT_MASKS_INCREMENT_ABSOLUTE
dt_masks_gradient_states_t
@ DT_MASKS_GRADIENT_STATE_SIGMOIDAL
@ DT_MASKS_GRADIENT_STATE_LINEAR
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.
static void dt_masks_gui_delta_to_raw_norm(dt_develop_t *dev, const dt_masks_form_gui_t *gui, float point[2])
#define CLAMPF(a, mn, mx)
static float gh(const float f)
const float uint32_t state[4]
int32_t num_openmp_threads
struct dt_develop_t * develop
struct dt_develop_t::@17 roi
Region of interest passed through the pixelpipe.
dt_masks_gradient_states_t state
void(* draw_shape)(cairo_t *cr, const float *points, const int points_count, const int nb, const gboolean border, const gboolean source)