diff --git a/src/develop/develop.h b/src/develop/develop.h index 9218201f466d..8e4836c9eb4b 100644 --- a/src/develop/develop.h +++ b/src/develop/develop.h @@ -289,11 +289,16 @@ typedef struct dt_develop_t dt_dev_chroma_t chroma; - // for exposing the crop + // for exposing and handling the crop struct { // set by dt_dev_pixelpipe_synch() if an enabled crop module is included in history struct dt_iop_module_t *exposer; + + // proxy to change crop settings via flip module + struct dt_iop_module_t *flip_handler; + void (*flip_callback)(struct dt_iop_module_t *crop, + const dt_image_orientation_t flipmode); } cropping; // for the overexposure indicator diff --git a/src/iop/crop.c b/src/iop/crop.c index 07e065c8a32a..231908faf449 100644 --- a/src/iop/crop.c +++ b/src/iop/crop.c @@ -236,8 +236,7 @@ static gboolean _set_max_clip(dt_iop_module_t *self) // we want to know the size of the actual buffer dt_dev_pixelpipe_t *fpipe = self->dev->full.pipe; - dt_dev_pixelpipe_iop_t *piece = - dt_dev_distort_get_iop_pipe(self->dev, fpipe, self); + const dt_dev_pixelpipe_iop_t *piece = dt_dev_distort_get_iop_pipe(self->dev, fpipe, self); if(!piece) return FALSE; const float wp = piece->buf_out.width; @@ -536,8 +535,7 @@ static float _aspect_ratio_get(dt_iop_module_t *self, GtkWidget *combo) } // we want to know the size of the actual buffer - dt_dev_pixelpipe_iop_t *piece = - dt_dev_distort_get_iop_pipe(self->dev, self->dev->preview_pipe, self); + const dt_dev_pixelpipe_iop_t *piece = dt_dev_distort_get_iop_pipe(self->dev, self->dev->preview_pipe, self); if(!piece) return 0.0f; const int iwd = piece->buf_in.width, iht = piece->buf_in.height; @@ -1117,6 +1115,23 @@ static gchar *_aspect_format(gchar *original, return g_strdup_printf("%s %4.2f", original, (float)adim / (float)bdim); } +static void _crop_handle_flip(dt_iop_module_t *self, const dt_image_orientation_t mode) +{ + dt_iop_crop_params_t *p = self ? self->params : NULL; + if(!p || (p->cx == 0.f && p->cy == 0.f && p->cw == 1.f && p->ch == 1.f)) + return; + + const float ocx = p->cx; + const float ocy = p->cy; + if(mode == ORIENTATION_FLIP_HORIZONTALLY) {p->cx = 1.f-p->cw; p->cw = 1.f-ocx;} + else if(mode == ORIENTATION_FLIP_VERTICALLY) {p->cy = 1.f-p->ch; p->ch = 1.f-ocy;} + else if(mode == ORIENTATION_ROTATE_CW_90_DEG) {p->cx = 1.f-p->ch; p->ch = p->cw; p->cw = 1.f-p->cy; p->cy = ocx;} + else if(mode == ORIENTATION_ROTATE_CCW_90_DEG) {p->cx = p->cy; p->cy = 1.f-p->cw; p->cw = p->ch; p->ch = 1.f-ocx;} + + dt_iop_gui_update(self); + dt_dev_add_history_item(darktable.develop, self, self->enabled); +} + void gui_init(dt_iop_module_t *self) { dt_iop_crop_gui_data_t *g = IOP_GUI_ALLOC(crop); @@ -1308,6 +1323,9 @@ void gui_init(dt_iop_module_t *self) _("the bottom margin cannot overlap with the top margin")); self->widget = box_enabled; + + darktable.develop->cropping.flip_handler = self; + darktable.develop->cropping.flip_callback = _crop_handle_flip; } static void _aspect_free(gpointer data) diff --git a/src/iop/flip.c b/src/iop/flip.c index 12750303dad2..6d76a931871a 100644 --- a/src/iop/flip.c +++ b/src/iop/flip.c @@ -431,7 +431,7 @@ void commit_params(dt_iop_module_t *self, d->orientation = p->orientation; if(d->orientation == ORIENTATION_NONE) - piece->enabled = 0; + piece->enabled = FALSE; } void init_pipe(dt_iop_module_t *self, @@ -518,6 +518,20 @@ void reload_defaults(dt_iop_module_t *self) } } +static void _crop_callback(dt_iop_module_t *self, + const dt_image_orientation_t mode) +{ + dt_develop_t *dev = darktable.develop; + dt_iop_module_t *cropper = dev->cropping.flip_handler; + + // FIXME: can we "compress" history here by checking for a flip/crop pair on top of history + // and a) drop the crop on top of history and b) compress flip in one step + + dt_dev_add_history_item(dev, self, TRUE); + if(cropper && dev->cropping.flip_callback) + dev->cropping.flip_callback(cropper, mode); +} + static void do_rotate(dt_iop_module_t *self, uint32_t cw) { dt_iop_flip_params_t *p = self->params; @@ -543,7 +557,7 @@ static void do_rotate(dt_iop_module_t *self, uint32_t cw) orientation ^= ORIENTATION_SWAP_XY; p->orientation = orientation; - dt_dev_add_history_item(darktable.develop, self, TRUE); + _crop_callback(self, cw ? ORIENTATION_ROTATE_CW_90_DEG : ORIENTATION_ROTATE_CCW_90_DEG); } static void rotate_cw(GtkWidget *widget, dt_iop_module_t *self) @@ -569,7 +583,7 @@ static void _flip_h(GtkWidget *widget, dt_iop_module_t *self) else p->orientation = orientation ^ ORIENTATION_FLIP_HORIZONTALLY; - dt_dev_add_history_item(darktable.develop, self, TRUE); + _crop_callback(self, ORIENTATION_FLIP_HORIZONTALLY); } static void _flip_v(GtkWidget *widget, dt_iop_module_t *self) @@ -586,7 +600,7 @@ static void _flip_v(GtkWidget *widget, dt_iop_module_t *self) else p->orientation = orientation ^ ORIENTATION_FLIP_VERTICALLY; - dt_dev_add_history_item(darktable.develop, self, TRUE); + _crop_callback(self, ORIENTATION_FLIP_VERTICALLY); } void gui_init(dt_iop_module_t *self)