55#include <gdk/gdkkeysyms.h>
143 const int new_version)
155 return _(
"reframe|distortion");
161 _(
"linear, RGB, scene-referred"), _(
"geometric, RGB"),
162 _(
"linear, RGB, scene-referred"));
195 g->clip_w =
p->cw -
p->cx;
197 g->clip_h =
p->ch -
p->cy;
214 const float bbox_left =
g->clip_x * wd;
215 const float bbox_top =
g->clip_y * ht;
216 const float bbox_right = (
g->clip_x +
g->clip_w) * wd;
217 const float bbox_bottom = (
g->clip_y +
g->clip_h) * ht;
235 p->cx =
CLAMPF(points[0] / wd, 0.0f, 0.9f);
236 p->cy =
CLAMPF(points[1] / ht, 0.0f, 0.9f);
237 p->cw =
CLAMPF(points[2] / wd, 0.1f, 1.0f);
238 p->ch =
CLAMPF(points[3] / ht, 0.1f, 1.0f);
273 float points[8] = { 0.0f, 0.0f, wp, hp,
p->cx * wp,
p->cy * hp,
p->cw * wp,
p->ch * hp };
279 g->clip_max_x = fmaxf(points[0], 0.0f);
280 g->clip_max_y = fmaxf(points[1], 0.0f);
281 g->clip_max_w = fminf(points[2] - points[0], 1.0f);
282 g->clip_max_h = fminf(points[3] - points[1], 1.0f);
294 float *
const restrict points,
size_t points_count)
302 if(crop_top == 0 && crop_left == 0)
return 1;
304 for(
size_t i = 0;
i < points_count * 2;
i += 2)
306 points[
i] -= crop_left;
307 points[
i + 1] -= crop_top;
314 float *
const restrict points,
size_t points_count)
322 if(crop_top == 0 && crop_left == 0)
return 1;
324 for(
size_t i = 0;
i < points_count * 2;
i += 2)
326 points[
i] += crop_left;
327 points[
i + 1] += crop_top;
354 roi_out->
x = roi_in->
width *
d->cx;
355 roi_out->
y = roi_in->
height *
d->cy;
358 if(roi_out->
x < 0) roi_out->
x = 0;
359 if(roi_out->
y < 0) roi_out->
y = 0;
374 roi_in->
x += iw *
d->cx;
375 roi_in->
y += ih *
d->cy;
377 roi_in->
x = CLAMP(roi_in->
x, 0, (
int)floorf(iw));
378 roi_in->
y = CLAMP(roi_in->
y, 0, (
int)floorf(ih));
396 size_t origin[] = { 0, 0, 0 };
397 size_t region[] = { roi_out->
width, roi_out->
height, 1 };
399 if(err != CL_SUCCESS)
goto error;
461 if(text && !g_strcmp0(text, _(
"original image")))
463 int proc_iwd = 0, proc_iht = 0;
466 if(!(proc_iwd > 0 && proc_iht > 0))
return 0.0f;
468 if((
p->ratio_d > 0 && proc_iwd > proc_iht) || (
p->ratio_d < 0 && proc_iwd < proc_iht))
469 return (
float)proc_iwd / (float)proc_iht;
471 return (
float)proc_iht / (float)proc_iwd;
481 if(
p->ratio_d == -2 &&
p->ratio_n == -2)
483 if(
p->cw == 1.0 &&
p->cx == 0.0 &&
p->ch == 1.0 &&
p->cy == 0.0)
491 const float whratio = ((float)(iwd - 2 * interpolation->
width) * (
p->cw -
p->cx))
492 / ((float)(iht - 2 * interpolation->
width) * (
p->ch -
p->cy));
493 const float ri = (float)iwd / (
float)iht;
495 const float prec = 0.0003f;
496 if(fabsf(whratio - 3.0f / 2.0f) < prec)
501 else if(fabsf(whratio - 2.0f / 1.0f) < prec)
506 else if(fabsf(whratio - 7.0f / 5.0f) < prec)
511 else if(fabsf(whratio - 4.0f / 3.0f) < prec)
516 else if(fabsf(whratio - 5.0f / 4.0f) < prec)
521 else if(fabsf(whratio - 1.0f / 1.0f) < prec)
526 else if(fabsf(whratio - 16.0f / 9.0f) < prec)
531 else if(fabsf(whratio - 16.0f / 10.0f) < prec)
536 else if(fabsf(whratio - 244.5f / 203.2f) < prec)
541 else if(fabsf(whratio - sqrtf(2.0f)) < prec)
543 p->ratio_d = 14142136;
544 p->ratio_n = 10000000;
546 else if(fabsf(whratio -
PHI) < prec)
548 p->ratio_d = 16180340;
549 p->ratio_n = 10000000;
551 else if(fabsf(whratio - ri) < prec)
564 if(
p->ratio_d == 0 &&
p->ratio_n == 0)
return -1.0f;
565 float d = 1.0f,
n = 1.0f;
568 d = copysignf(iwd,
p->ratio_d);
578 const float dn = copysignf(
MAX(fabsf(
d), fabsf(
n)),
d);
579 const float nn = copysignf(
MIN(fabsf(
d), fabsf(
n)),
n);
595 if(aspect <= 0)
return;
602 if(iwd < iht) aspect = 1.0f / aspect;
606 double clip_x =
MAX(iwd *
g->clip_x / (
float)iwd, 0.0f);
607 double clip_y =
MAX(iht *
g->clip_y / (
float)iht, 0.0f);
608 double clip_w =
MIN(iwd *
g->clip_w / (
float)iwd, 1.0f);
609 double clip_h =
MIN(iht *
g->clip_h / (
float)iht, 1.0f);
612 const double target_h = (
double)iwd *
g->clip_w / ((
double)iht * aspect);
613 const double target_w = (
double)iht *
g->clip_h * aspect / (
double)iwd;
621 clip_x = clip_x + clip_w - (target_w + clip_w) * .5;
622 clip_y = clip_y + clip_h - (target_h + clip_h) * .5;
623 clip_w = (target_w + clip_w) * .5;
624 clip_h = (target_h + clip_h) * .5;
628 clip_y = clip_y + clip_h - (target_h + clip_h) * .5;
629 clip_w = (target_w + clip_w) * .5;
630 clip_h = (target_h + clip_h) * .5;
634 clip_w = (target_w + clip_w) * .5;
635 clip_h = (target_h + clip_h) * .5;
639 clip_h = (target_h + clip_h) * .5;
640 clip_x = clip_x + clip_w - (target_w + clip_w) * .5;
641 clip_w = (target_w + clip_w) * .5;
646 const double off = target_h - clip_h;
647 clip_h = clip_h + off;
648 clip_y = clip_y - .5 * off;
653 const double off = target_w - clip_w;
654 clip_w = clip_w + off;
655 clip_x = clip_x - .5 * off;
658 if(clip_x < g->clip_max_x)
660 const double prev_clip_h = clip_h;
661 clip_h *= (clip_w + clip_x -
g->clip_max_x) / clip_w;
662 clip_w = clip_w + clip_x -
g->clip_max_x;
663 clip_x =
g->clip_max_x;
664 if(grab &
GRAB_TOP) clip_y += prev_clip_h - clip_h;
666 if(clip_y < g->clip_max_y)
668 const double prev_clip_w = clip_w;
669 clip_w *= (clip_h + clip_y -
g->clip_max_y) / clip_h;
670 clip_h = clip_h + clip_y -
g->clip_max_y;
671 clip_y =
g->clip_max_y;
672 if(grab &
GRAB_LEFT) clip_x += prev_clip_w - clip_w;
674 if(clip_x + clip_w >
g->clip_max_x +
g->clip_max_w)
676 const double prev_clip_h = clip_h;
677 clip_h *= (
g->clip_max_x +
g->clip_max_w - clip_x) / clip_w;
678 clip_w =
g->clip_max_x +
g->clip_max_w - clip_x;
679 if(grab &
GRAB_TOP) clip_y += prev_clip_h - clip_h;
681 if(clip_y + clip_h >
g->clip_max_y +
g->clip_max_h)
683 const double prev_clip_w = clip_w;
684 clip_w *= (
g->clip_max_y +
g->clip_max_h - clip_y) / clip_h;
685 clip_h =
g->clip_max_y +
g->clip_max_h - clip_y;
686 if(grab &
GRAB_LEFT) clip_x += prev_clip_w - clip_w;
688 g->clip_x = fmaxf(clip_x, 0.0f);
689 g->clip_y = fmaxf(clip_y, 0.0f);
690 g->clip_w = fminf(clip_w, 1.0f);
691 g->clip_h = fminf(clip_h, 1.0f);
711 return d->cx ==
p->cx &&
d->cy ==
p->cy &&
d->cw ==
p->cw &&
d->ch &&
p->cw;
717 gboolean sep_found =
FALSE;
718 char *
p = (
char *)num;
725 if(sep_found) *
d *= 10;
728 if(!sep_found && ((*
p ==
',') || (*
p ==
'.')))
732 else if(*
p <
'0' || *
p >
'9')
755 int d = abs(
p->ratio_d),
n =
p->ratio_n;
761 const char *c = text;
762 const char *end = text + strlen(text);
763 while(*c !=
':' && *c !=
'/' && c < end) c++;
768 const int dd = atoi(text);
769 const int nn = atoi(c);
771 if(nn == 0 || dd == 0)
773 dt_control_log(_(
"invalid ratio format. it should be \"number:number\""));
787 if(dd == 0 || nn == 0)
789 dt_control_log(_(
"invalid ratio format. it should be a positive number"));
803 while((nn % 2 == 0) && (dd % 2 == 0))
830 for(
const GList *iter =
g->aspect_list; iter; iter = g_list_next(iter))
833 if(g_strcmp0(aspect->
name, text) == 0)
843 if(
d != abs(
p->ratio_d) ||
n !=
p->ratio_n)
860 for(
const GList *iter =
g->aspect_list; iter; iter = g_list_next(iter))
863 if((aspect->
d ==
d) && (aspect->
n ==
n))
878 snprintf(str,
sizeof(str),
"%d:%d %2.2f", abs(
p->ratio_d), abs(
p->ratio_n),
879 (
float)abs(
p->ratio_d) / (
float)abs(
p->ratio_n));
900 g->clip_w =
g->clip_x +
g->clip_w -
p->cx;
906 g->clip_w =
p->cw -
g->clip_x;
911 g->clip_h =
g->clip_y +
g->clip_h -
p->cy;
917 g->clip_h =
p->ch -
g->clip_y;
920 else if(w ==
g->aspect_presets)
959 if(
p->ratio_d == -1 &&
p->ratio_n == -1)
965 const int d = abs(
p->ratio_d);
966 const int n =
p->ratio_n;
970 for(
const GList *iter =
g->aspect_list; iter; iter = g_list_next(iter))
973 if((aspect->
d ==
d) && (aspect->
n ==
n))
987 snprintf(str,
sizeof(str),
"%d:%d %2.2f", abs(
p->ratio_d), abs(
p->ratio_n),
988 (
float)abs(
p->ratio_d) / (
float)abs(
p->ratio_n));
1005 p->ratio_d = -
p->ratio_d;
1016 g->editing = gtk_toggle_button_get_active(button);
1028 gtk_button_set_label(GTK_BUTTON(button), _(
"Cancel"));
1029 gtk_widget_set_sensitive(
g->commit_button,
TRUE);
1046 gtk_button_set_label(GTK_BUTTON(button), _(
"Edit"));
1047 gtk_widget_set_sensitive(
g->commit_button,
FALSE);
1061 gtk_widget_set_sensitive(
g->commit_button,
FALSE);
1071 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(
g->edit_button),
FALSE);
1072 gtk_button_set_label(GTK_BUTTON(
g->edit_button), _(
"Edit"));
1085 if((a->
d == 0 || a->
d == 1) && a->
n == 0)
return -1;
1087 const float ad =
MAX(a->
d, a->
n);
1088 const float an =
MIN(a->
d, a->
n);
1089 const float bd =
MAX(b->d, b->n);
1090 const float bn =
MIN(b->d, b->n);
1091 const float aratio = ad / an;
1092 const float bratio = bd / bn;
1094 if(aratio < bratio)
return -1;
1096 const float prec = 0.0003f;
1097 if(fabsf(aratio - bratio) < prec)
return 0;
1105 if(bdim == 0)
return g_strdup(original);
1107 return g_strdup_printf(
"%s %4.2f", original, (
float)adim / (
float)bdim);
1114 g->aspect_list = NULL;
1115 g->clip_x =
g->clip_y =
g->handle_x =
g->handle_y = 0.0;
1116 g->clip_w =
g->clip_h = 1.0;
1117 g->clip_max_x =
g->clip_max_y = 0.0;
1118 g->clip_max_w =
g->clip_max_h = 1.0;
1129 { _(
"freehand"), 0, 0 },
1130 { _(
"original image"), 1, 0 },
1131 { _(
"square"), 1, 1 },
1132 { _(
"7:6, 6x7"), 7, 6 },
1133 { _(
"10:8 in print"), 2445, 2032 },
1134 { _(
"6:5, 5x6"), 6, 5 },
1135 { _(
"5:4, 4x5, 8x10"), 5, 4 },
1136 { _(
"11x14"), 14, 11 },
1137 { _(
"8.5x11, letter"), 110, 85 },
1138 { _(
"4:3, VGA, TV"), 4, 3 },
1140 { _(
"ISO 216, DIN 476, A4"), 14142136, 10000000 },
1141 { _(
"3:2, 4x6, 35mm"), 3, 2 },
1142 { _(
"16:10, 8x5"), 16, 10 },
1143 { _(
"golden cut"), 16180340, 10000000 },
1144 { _(
"5:3, 12x20"), 5, 3 },
1145 { _(
"16:9, HDTV"), 16, 9 },
1146 { _(
"widescreen"), 185, 100 },
1147 { _(
"2:1, Univisium"), 2, 1 },
1148 { _(
"Cinemascope"), 235, 100 },
1149 { _(
"21:9"), 7, 3 },
1150 { _(
"Anamorphic"), 239, 100 },
1151 { _(
"65:24, XPan"), 65, 24 },
1152 { _(
"3:1, panorama"), 3, 1 },
1153 { _(
"4:1, Polyvision"), 4, 1 },
1158 for(
int i = 0;
i < aspects_count;
i++)
1162 aspect->
d = aspects[
i].
d;
1163 aspect->
n = aspects[
i].
n;
1164 g->aspect_list = g_list_append(
g->aspect_list, aspect);
1169 for(GSList *iter = custom_aspects; iter; iter = g_slist_next(iter))
1173 const char *c = nv->
value;
1174 const char *end = nv->
value + strlen(nv->
value);
1175 while(*c !=
':' && *c !=
'/' && c < end) c++;
1182 if(
n == 0 ||
d == 0)
1184 fprintf(stderr,
"invalid ratio format for `%s'. it should be \"number:number\"\n", nv->
key);
1185 dt_control_log(_(
"invalid ratio format for `%s'. it should be \"number:number\""), nv->
key);
1192 g->aspect_list = g_list_append(
g->aspect_list, aspect);
1196 fprintf(stderr,
"invalid ratio format for `%s'. it should be \"number:number\"\n", nv->
key);
1197 dt_control_log(_(
"invalid ratio format for `%s'. it should be \"number:number\""), nv->
key);
1209 for(GList *iter =
g->aspect_list; iter; iter = g_list_next(iter))
1212 int dd =
MIN(aspect->
d, aspect->
n);
1213 int nn =
MAX(aspect->
d, aspect->
n);
1214 if(dd ==
d && nn ==
n)
1218 GList *prev = g_list_previous(iter);
1219 g->aspect_list = g_list_delete_link(
g->aspect_list, iter);
1221 iter = prev ? prev :
g->aspect_list;
1234 for(GList *iter =
g->aspect_list; iter; iter = g_list_next(iter))
1243 gtk_widget_set_tooltip_text(
g->aspect_presets, _(
"set the aspect ratio\n"
1244 "the list is sorted: from most square to least square\n"
1245 "to enter custom aspect ratio open the combobox and type ratio in x:y or decimal format"));
1248 g_signal_connect(G_OBJECT(
g->aspect_presets),
"quad-pressed", G_CALLBACK(
_event_aspect_flip), self);
1249 gtk_box_pack_start(GTK_BOX(box_enabled),
g->aspect_presets,
TRUE,
TRUE, 0);
1253 g->edit_button = gtk_toggle_button_new_with_label(_(
"Edit"));
1254 g_signal_connect(GTK_TOGGLE_BUTTON(
g->edit_button),
"toggled", G_CALLBACK(
_enter_edit_mode), self);
1255 gtk_box_pack_start(GTK_BOX(box),
g->edit_button,
TRUE,
TRUE, 0);
1258 gtk_box_pack_start(GTK_BOX(box),
g->commit_button,
TRUE,
TRUE, 0);
1259 gtk_widget_set_sensitive(
g->commit_button,
FALSE);
1261 gtk_box_pack_end(GTK_BOX(box_enabled), GTK_WIDGET(box),
TRUE,
TRUE, 0);
1267 "plugins/darkroom/crop/expand_margins",
1269 GTK_BOX(box_enabled), GTK_PACK_END);
1271 self->
widget = GTK_WIDGET(
g->cs.container);
1276 gtk_widget_set_tooltip_text(
g->cx, _(
"the left margin cannot overlap with the right margin"));
1283 gtk_widget_set_tooltip_text(
g->cw, _(
"the right margin cannot overlap with the left margin"));
1288 gtk_widget_set_tooltip_text(
g->cy, _(
"the top margin cannot overlap with the bottom margin"));
1295 gtk_widget_set_tooltip_text(
g->ch, _(
"the bottom margin cannot overlap with the top margin"));
1297 self->
widget = box_enabled;
1311 g->aspect_list = NULL;
1317 const float wd,
const float ht)
1319 if(wd == 0.f || ht == 0.f)
return GRAB_NONE;
1322 if(!(pzx < g->clip_x || pzx >
g->clip_x +
g->clip_w || pzy < g->clip_y || pzy >
g->clip_y +
g->clip_h))
1326 const float x_border = (border == 0.f) ? 0.f : border / wd;
1327 const float y_border = (border == 0.f) ? 0.f : border / ht;
1331 if((pzx >=
g->clip_x) && pzx < g->clip_x + x_border)
1334 if((pzy >=
g->clip_y) && pzy < g->clip_y + y_border)
1337 if((pzx <= g->clip_x +
g->clip_w) && (pzx >
g->clip_w +
g->clip_x - x_border))
1340 if((pzy <= g->clip_y +
g->clip_h) && (pzy >
g->clip_h +
g->clip_y - y_border))
1358 if(
g->wd < 1.0 ||
g->ht < 1.0)
return;
1366 const float guide_x =
g->editing ?
g->clip_x *
g->wd : 0;
1367 const float guide_y =
g->editing ?
g->clip_y *
g->ht : 0;
1368 const float guide_w =
g->editing ?
g->clip_w *
g->wd :
g->wd;
1369 const float guide_h =
g->editing ?
g->clip_h *
g->ht :
g->ht;
1371 dt_guides_draw(cr, guide_x, guide_y, guide_w, guide_h, zoom_scale);
1373 if(!
g->editing)
return;
1376 double border_width = dashes / 2.;
1379 float pzxpy[2] = { (float)pointerx, (
float)pointery };
1381 float pzx = pzxpy[0];
1382 float pzy = pzxpy[1];
1383 cairo_set_line_width(cr, border_width);
1387 cairo_set_source_rgba(cr, .1, .1, .1, .8);
1388 cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
1389 const float max_x =
g->clip_max_x *
g->wd;
1390 const float max_y =
g->clip_max_y *
g->ht;
1391 const float max_w =
g->clip_max_w *
g->wd;
1392 const float max_h =
g->clip_max_h *
g->ht;
1393 cairo_rectangle(cr, max_x, max_y, max_w, max_h);
1395 const float clip_x =
g->clip_x *
g->wd - border_width / 2.;
1396 const float clip_y =
g->clip_y *
g->ht - border_width / 2.;
1397 const float clip_w =
g->clip_w *
g->wd + border_width;
1398 const float clip_h =
g->clip_h *
g->ht + border_width;
1399 cairo_rectangle(cr, clip_x, clip_y, clip_w, clip_h);
1402 if(
g->clip_x > .0f ||
g->clip_y > .0f ||
g->clip_w < 1.0f ||
g->clip_h < 1.0f)
1404 const float rect_x =
g->clip_x *
g->wd - border_width / 2.;
1405 const float rect_y =
g->clip_y *
g->ht - border_width / 2.;
1406 const float rect_w =
g->clip_w *
g->wd + border_width;
1407 const float rect_h =
g->clip_h *
g->ht + border_width;
1408 cairo_rectangle(cr, rect_x, rect_y, rect_w, rect_h);
1416 char dimensions[16];
1417 dimensions[0] =
'\0';
1418 PangoLayout *layout;
1421 pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD);
1422 pango_font_description_set_absolute_size(desc,
DT_PIXEL_APPLY_DPI(16) * PANGO_SCALE / zoom_scale);
1423 layout = pango_cairo_create_layout(cr);
1424 pango_layout_set_font_description(layout, desc);
1429 snprintf(dimensions,
sizeof(dimensions),
"%.0f x %.0f", (
float)procw *
g->clip_w, (
float)proch *
g->clip_h);
1431 pango_layout_set_text(layout, dimensions, -1);
1432 pango_layout_get_pixel_extents(layout, NULL, &ext);
1433 const float text_w = ext.width;
1436 float xp = (
g->clip_x +
g->clip_w * .5f) *
g->wd - text_w * .5f;
1437 float yp = (
g->clip_y +
g->clip_h * .5f) *
g->ht - text_h * .5f;
1444 cairo_clip_extents(cr, &x1, &y1, &x2, &y2);
1445 xp =
CLAMPF(xp, x1 + 2.0 * margin, x2 - text_w - 2.0 * margin);
1446 yp =
CLAMPF(yp, y1 + 2.0 * margin, y2 - text_h - 2.0 * margin);
1448 cairo_set_source_rgba(cr, .5, .5, .5, .9);
1450 cairo_set_source_rgb(cr, .7, .7, .7);
1451 cairo_move_to(cr, xp, yp);
1452 pango_cairo_show_layout(cr, layout);
1453 pango_font_description_free(desc);
1454 g_object_unref(layout);
1464 const float clip_x_px =
g->clip_x *
g->wd;
1465 const float clip_y_px =
g->clip_y *
g->ht;
1466 const float clip_w_px =
g->clip_w *
g->wd;
1467 const float clip_h_px =
g->clip_h *
g->ht;
1468 const float clip_right_px = clip_x_px + clip_w_px;
1469 const float clip_bottom_px = clip_y_px + clip_h_px;
1471 if(grab ==
GRAB_LEFT) cairo_rectangle(cr, clip_x_px, clip_y_px, border, clip_h_px);
1472 if(grab ==
GRAB_TOP) cairo_rectangle(cr, clip_x_px, clip_y_px, clip_w_px, border);
1473 if(grab ==
GRAB_TOP_LEFT) cairo_rectangle(cr, clip_x_px, clip_y_px, border, border);
1474 if(grab ==
GRAB_RIGHT) cairo_rectangle(cr, clip_right_px - border, clip_y_px, border, clip_h_px);
1475 if(grab ==
GRAB_BOTTOM) cairo_rectangle(cr, clip_x_px, clip_bottom_px - border, clip_w_px, border);
1476 if(grab ==
GRAB_BOTTOM_RIGHT) cairo_rectangle(cr, clip_right_px - border, clip_bottom_px - border, border, border);
1477 if(grab ==
GRAB_TOP_RIGHT) cairo_rectangle(cr, clip_right_px - border, clip_y_px, border, border);
1478 if(grab ==
GRAB_BOTTOM_LEFT) cairo_rectangle(cr, clip_x_px, clip_bottom_px - border, border, border);
1486 if(!
g->editing)
return 0;
1488 float pzxpy[2] = { (float)
x, (
float)y };
1490 float pzx = pzxpy[0];
1491 float pzy = pzxpy[1];
1503 const float bzx =
g->button_down_zoom_x;
1504 const float bzy =
g->button_down_zoom_y;
1511 = fminf(
g->clip_max_w +
g->clip_max_x -
g->clip_w,
1512 fmaxf(
g->clip_max_x,
g->handle_x + pzx - bzx));
1516 = fminf(
g->clip_max_h +
g->clip_max_y -
g->clip_h,
1517 fmaxf(
g->clip_max_y,
g->handle_y + pzy - bzy));
1529 xx = (
g->cropping &
GRAB_LEFT) ? (pzx - bzx) : (bzx - pzx);
1531 yy = (
g->cropping &
GRAB_TOP) ? (pzy - bzy) : (bzy - pzy);
1533 float ratio = fmaxf((
g->prev_clip_w - 2.0f * xx) /
g->prev_clip_w,
1534 (
g->prev_clip_h - 2.0f * yy) /
g->prev_clip_h);
1537 if(
g->prev_clip_w * ratio < 0.1f) ratio = 0.1f /
g->prev_clip_w;
1538 if(
g->prev_clip_h * ratio < 0.1f) ratio = 0.1f /
g->prev_clip_h;
1541 if(
g->prev_clip_w * ratio >
g->clip_max_w) ratio =
g->clip_max_w /
g->prev_clip_w;
1542 if(
g->prev_clip_h * ratio >
g->clip_max_h) ratio =
g->clip_max_h /
g->prev_clip_h;
1545 float nx =
g->prev_clip_x - (
g->prev_clip_w * ratio -
g->prev_clip_w) / 2.0f;
1546 float ny =
g->prev_clip_y - (
g->prev_clip_h * ratio -
g->prev_clip_h) / 2.0f;
1547 float nw =
g->prev_clip_w * ratio;
1548 float nh =
g->prev_clip_h * ratio;
1551 nx = fmaxf(nx,
g->clip_max_x);
1553 nx = fminf(nx,
g->clip_max_w +
g->clip_max_x - nw);
1555 ny = fmaxf(ny,
g->clip_max_y);
1557 ny = fminf(ny,
g->clip_max_h +
g->clip_max_y - nh);
1568 const float old_clip_x =
g->clip_x;
1569 g->clip_x = fminf(fmaxf(
g->clip_max_x, pzx -
g->handle_x),
g->clip_x +
g->clip_w - 0.1f);
1570 g->clip_w = old_clip_x +
g->clip_w -
g->clip_x;
1574 const float old_clip_y =
g->clip_y;
1575 g->clip_y = fminf(fmaxf(
g->clip_max_y, pzy -
g->handle_y),
g->clip_y +
g->clip_h - 0.1f);
1576 g->clip_h = old_clip_y +
g->clip_h -
g->clip_y;
1579 g->clip_w = fmaxf(0.1f, fminf(
g->clip_max_w +
g->clip_max_x, pzx -
g->clip_x -
g->handle_x));
1581 g->clip_h = fmaxf(0.1f, fminf(
g->clip_max_h +
g->clip_max_y, pzy -
g->clip_y -
g->handle_y));
1584 if(
g->clip_x +
g->clip_w >
g->clip_max_w +
g->clip_max_x)
1585 g->clip_w =
g->clip_max_w +
g->clip_max_x -
g->clip_x;
1586 if(
g->clip_y +
g->clip_h >
g->clip_max_h +
g->clip_max_y)
1587 g->clip_h =
g->clip_max_h +
g->clip_max_y -
g->clip_y;
1637 if(!
g->editing)
return 0;
1657 if(!
g->editing)
return 0;
1660 if(
type == GDK_2BUTTON_PRESS && which == 1)
1666 float pzxpy[2] = { (float)
x, (
float)y };
1668 float pzx = pzxpy[0];
1669 float pzy = pzxpy[1];
1672 g->button_down_x =
x;
1673 g->button_down_y = y;
1675 g->button_down_zoom_x = pzx;
1676 g->button_down_zoom_y = pzy;
1679 g->prev_clip_x =
g->clip_x;
1680 g->prev_clip_y =
g->clip_y;
1681 g->prev_clip_w =
g->clip_w;
1682 g->prev_clip_h =
g->clip_h;
1701 g->handle_x =
g->clip_x;
1702 g->handle_y =
g->clip_y;
1706 if(
g->cropping &
GRAB_LEFT)
g->handle_x = pzx -
g->clip_x;
1707 if(
g->cropping &
GRAB_TOP)
g->handle_y = pzy -
g->clip_y;
1708 if(
g->cropping &
GRAB_RIGHT)
g->handle_x = pzx - (
g->clip_w +
g->clip_x);
1709 if(
g->cropping &
GRAB_BOTTOM)
g->handle_y = pzy - (
g->clip_h +
g->clip_y);
1731 if(!
g->editing)
return 0;
static void error(char *msg)
void dt_bauhaus_slider_set_digits(GtkWidget *widget, int val)
void dt_bauhaus_combobox_set_editable(GtkWidget *widget, int editable)
void dt_bauhaus_combobox_set_text(GtkWidget *widget, const char *text)
int dt_bauhaus_combobox_get(GtkWidget *widget)
void dt_bauhaus_widget_set_quad_toggle(GtkWidget *widget, int toggle)
void dt_bauhaus_slider_set_offset(GtkWidget *widget, float offset)
void dt_bauhaus_slider_set_soft_max(GtkWidget *widget, float val)
void dt_bauhaus_slider_set_soft_min(GtkWidget *widget, float val)
const char * dt_bauhaus_combobox_get_text(GtkWidget *widget)
void dt_bauhaus_slider_set(GtkWidget *widget, float pos)
void dt_bauhaus_combobox_set(GtkWidget *widget, const int pos)
void dt_bauhaus_widget_set_label(GtkWidget *widget, const char *label)
GtkWidget * dt_bauhaus_combobox_new(dt_bauhaus_t *bh, dt_gui_module_t *self)
void dt_bauhaus_slider_set_format(GtkWidget *widget, const char *format)
void dt_bauhaus_combobox_add(GtkWidget *widget, const char *text)
void dt_bauhaus_widget_set_quad_paint(GtkWidget *widget, dt_bauhaus_quad_paint_f f, int paint_flags, void *paint_data)
void dt_bauhaus_slider_set_factor(GtkWidget *widget, float factor)
static const dt_aligned_pixel_simd_t const dt_adaptation_t const float p
const dt_colormatrix_t dt_aligned_pixel_t out
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
void dt_conf_string_entry_free(gpointer data)
void dt_conf_set_int(const char *name, int val)
GSList * dt_conf_all_string_entries(const char *dir)
int dt_conf_get_int(const char *name)
void dt_control_log(const char *msg,...)
void dt_control_queue_redraw_center()
request redraw of center window. This redraws the center view within a gdk critical section to preven...
void dt_control_hinter_message(const struct dt_control_t *s, const char *message)
void dt_control_navigation_redraw()
request redraw of the navigation widget. This redraws the wiget of the navigation module.
#define dt_control_change_cursor(cursor)
#define dt_control_queue_cursor(cursor)
int operation_tags_filter()
void commit_params(struct dt_iop_module_t *self, dt_iop_params_t *p1, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void distort_mask(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, const float *const in, float *const out, const dt_iop_roi_t *const roi_in, const dt_iop_roi_t *const roi_out)
const char ** description(struct dt_iop_module_t *self)
int distort_backtransform(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, float *const restrict points, size_t points_count)
static gchar * _aspect_format(gchar *original, int adim, int bdim)
int distort_transform(dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, float *const restrict points, size_t points_count)
static void _float_to_fract(const char *num, int *n, int *d)
void init_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
void gui_reset(struct dt_iop_module_t *self)
void gui_update(struct dt_iop_module_t *self)
void gui_init(struct dt_iop_module_t *self)
int button_pressed(struct dt_iop_module_t *self, double x, double y, double pressure, int which, int type, uint32_t state)
void gui_changed(dt_iop_module_t *self, GtkWidget *w, void *previous)
int button_released(struct dt_iop_module_t *self, double x, double y, int which, uint32_t state)
static void _aspect_apply(dt_iop_module_t *self, _grab_region_t grab)
void reload_defaults(dt_iop_module_t *self)
static void _enter_edit_mode(GtkToggleButton *button, struct dt_iop_module_t *self)
int default_colorspace(dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
void gui_post_expose(struct dt_iop_module_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery)
static void _commit_box(dt_iop_module_t *self, dt_iop_crop_gui_data_t *g, dt_iop_crop_params_t *p)
void gui_cleanup(struct dt_iop_module_t *self)
int mouse_leave(struct dt_iop_module_t *self)
static void _aspect_free(gpointer data)
int process(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, const void *const ivoid, void *const ovoid)
static void _params_to_gui(dt_iop_crop_params_t *p, dt_iop_crop_gui_data_t *g)
static void _event_aspect_presets_changed(GtkWidget *combo, dt_iop_module_t *self)
static gboolean _set_max_clip(dt_dev_pixelpipe_t *pipe, struct dt_iop_module_t *self)
this function initializes the maximum clip rectangle from crop parameters and correct the clip rectan...
void cleanup_pipe(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, dt_dev_pixelpipe_iop_t *piece)
static void _event_key_swap(dt_iop_module_t *self)
gboolean has_defaults(struct dt_iop_module_t *self)
int process_cl(struct dt_iop_module_t *self, const dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece, cl_mem dev_in, cl_mem dev_out)
int mouse_moved(struct dt_iop_module_t *self, double x, double y, double pressure, int which)
static _grab_region_t _gui_get_grab(float pzx, float pzy, dt_iop_crop_gui_data_t *g, const float border, const float wd, const float ht)
static void _event_commit_clicked(GtkButton *button, dt_iop_module_t *self)
static void _event_aspect_flip(GtkWidget *button, dt_iop_module_t *self)
void modify_roi_in(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, const dt_iop_roi_t *roi_out, dt_iop_roi_t *roi_in)
void modify_roi_out(struct dt_iop_module_t *self, const struct dt_dev_pixelpipe_t *pipe, struct dt_dev_pixelpipe_iop_t *piece, dt_iop_roi_t *roi_out, const dt_iop_roi_t *roi_in)
static gint _aspect_ratio_cmp(const dt_iop_crop_aspect_t *a, const dt_iop_crop_aspect_t *b)
int legacy_params(dt_iop_module_t *self, const void *const old_params, const int old_version, void *new_params, const int new_version)
static float _aspect_ratio_get(dt_iop_module_t *self, GtkWidget *combo)
gboolean runtime_data_hash(struct dt_iop_module_t *self, dt_dev_pixelpipe_t *pipe, const dt_dev_pixelpipe_iop_t *piece)
void dt_print(dt_debug_thread_t thread, const char *msg,...)
#define dt_free_align(ptr)
static void * dt_calloc_align(size_t size)
static gboolean dt_modifiers_include(const GdkModifierType state, const GdkModifierType desired_modifier_mask)
float dt_boundingbox_t[4]
#define DT_MODULE_INTROSPECTION(MODVER, PARAMSTYPE)
#define __OMP_PARALLEL_FOR_SIMD__(...)
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
#define dt_dev_add_history_item(dev, module, enable, redraw)
#define dt_dev_pixelpipe_resync_history_all(dev)
void dt_dev_get_processed_size(const dt_develop_t *dev, int *procw, int *proch)
dt_dev_pixelpipe_iop_t * dt_dev_distort_get_iop_pipe(struct dt_dev_pixelpipe_t *pipe, struct dt_iop_module_t *module)
void dt_dev_coordinates_preview_abs_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
int dt_dev_get_thumbnail_size(dt_develop_t *dev)
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)
float dt_dev_get_overlay_scale(dt_develop_t *dev)
Get the overlay scale factor in GUI logical coordinates.
gboolean dt_dev_clip_roi(dt_develop_t *dev, cairo_t *cr, int32_t width, int32_t height)
Clip the view to the ROI. WARNING: this must be done before any translation.
gboolean dt_dev_rescale_roi(dt_develop_t *dev, cairo_t *cr, int32_t width, int32_t height)
Scale the ROI to fit within given width/height, centered.
void dt_dev_coordinates_widget_to_image_norm(dt_develop_t *dev, float *points, size_t num_points)
Coordinate conversion helpers between widget, normalized image, and absolute image spaces.
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_FORW_EXCL
static void dt_draw_set_color_overlay(cairo_t *cr, gboolean bright, double alpha)
void dtgtk_cairo_paint_aspectflip(cairo_t *cr, gint x, gint y, gint w, gint h, gint flags, void *data)
void dt_gui_new_collapsible_section(dt_gui_collapsible_section_t *cs, const char *confname, const char *label, GtkBox *parent, GtkPackType pack)
Create a collapsible section and pack it into the parent box.
void dt_gui_draw_rounded_rectangle(cairo_t *cr, float width, float height, float x, float y)
void dt_gui_update_collapsible_section(dt_gui_collapsible_section_t *cs)
#define DT_GUI_BOX_SPACING
#define DT_PIXEL_APPLY_DPI(value)
void dt_guides_draw(cairo_t *cr, const float left, const float top, const float width, const float height, const float zoom_scale)
void dt_iop_copy_image_roi(float *const __restrict__ out, const float *const __restrict__ in, const size_t ch, const dt_iop_roi_t *const __restrict__ roi_in, const dt_iop_roi_t *const __restrict__ roi_out, const int zero_pad)
void dt_iop_request_focus(dt_iop_module_t *module)
const char ** dt_iop_set_description(dt_iop_module_t *module, const char *main_text, const char *purpose, const char *input, const char *process, const char *output)
void dt_iop_set_cache_bypass(dt_iop_module_t *module, gboolean state)
@ IOP_FLAGS_GUIDES_SPECIAL_DRAW
@ IOP_FLAGS_TILING_FULL_ROI
#define IOP_GUI_ALLOC(module)
GtkWidget * dt_bauhaus_slider_from_params(dt_iop_module_t *self, const char *param)
const struct dt_interpolation * dt_interpolation_new(enum dt_interpolation_type type)
@ DT_INTERPOLATION_USERPREF_WARP
GtkWidget * dt_action_button_new(dt_lib_module_t *self, const gchar *label, gpointer callback, gpointer data, const gchar *tooltip, guint accel_key, GdkModifierType mods)
float *const restrict const size_t k
#define CLAMPF(a, mn, mx)
int dt_opencl_enqueue_copy_image(const int devid, cl_mem src, cl_mem dst, size_t *orig_src, size_t *orig_dst, size_t *region)
struct _GtkWidget GtkWidget
const float uint32_t state[4]
struct dt_gui_gtk_t * gui
struct dt_bauhaus_t * bauhaus
struct dt_develop_t * develop
struct dt_control_t * control
PangoFontDescription * pango_font_desc
struct dt_iop_module_t *void * data
struct dt_develop_t * dev
struct dt_dev_pixelpipe_t * virtual_pipe
struct dt_develop_t::@17 roi
dt_boundingbox_t usercrop
GtkWidget * aspect_presets
dt_gui_collapsible_section_t cs
GtkWidget * commit_button
dt_iop_crop_params_t previous_params
dt_iop_params_t * default_params
struct dt_develop_t * dev
dt_iop_gui_data_t * gui_data
Region of interest passed through the pixelpipe.
typedef double((*spd)(unsigned long int wavelength, double TempK))