diff options
author | Oyvind Kolas <pippin@gimp.org> | 2015-07-27 00:57:11 +0200 |
---|---|---|
committer | Oyvind Kolas <pippin@gimp.org> | 2015-07-27 01:14:00 +0200 |
commit | c2aba45298c74228c9667cc3f3112c63c7482146 (patch) | |
tree | 1e41d5cd07639c3278814e012cf3a16d18173493 | |
parent | 16dea04ed66150aa06cc3693ec2e04b3f171a091 (diff) |
code reorg
-rw-r--r-- | bin/mrg-ui.c | 1316 |
1 files changed, 664 insertions, 652 deletions
diff --git a/bin/mrg-ui.c b/bin/mrg-ui.c index b56ca5fd..d3c36b22 100644 --- a/bin/mrg-ui.c +++ b/bin/mrg-ui.c @@ -13,7 +13,7 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, see <http://www.gnu.org/licenses/>. * - * Copyright (C) 2015 Øyvind Kolås + * Copyright (C) 2015 Øyvind Kolås pippin@gimp.org */ #define _BSD_SOURCE @@ -83,6 +83,545 @@ struct _State { void gegl_meta_set (const char *path, const char *meta_data); char * gegl_meta_get (const char *path); +static char *suffix_path (const char *path); +static char *unsuffix_path (const char *path); +static int is_giev_path (const char *path); + +static void contrasty_stroke (cairo_t *cr); + +static void mrg_gegl_blit (Mrg *mrg, + float x0, float y0, + float width, float height, + GeglNode *node, + float u, float v, + float scale, + float preview_multiplier); + +static void load_path (State *o); + +static void go_next (State *o); +static void go_prev (State *o); + + +static void go_next_cb (MrgEvent *event, void *data1, void *data2); +static void go_prev_cb (MrgEvent *event, void *data1, void *data2); + +static void leave_editor (State *o); + +static void drag_preview (MrgEvent *e); +static void load_into_buffer (State *o, const char *path); + +static GeglNode *locate_node (State *o, const char *op_name); + +static void zoom_to_fit (State *o); + +static void zoom_to_fit_buffer (State *o); + +static void zoom_fit_cb (MrgEvent *e, void *data1, void *data2); +static int deferred_zoom_to_fit (Mrg *mrg, void *data); + +static void pan_left_cb (MrgEvent *event, void *data1, void *data2); + +static void pan_right_cb (MrgEvent *event, void *data1, void *data2); + +static void pan_down_cb (MrgEvent *event, void *data1, void *data2); + +static void pan_up_cb (MrgEvent *event, void *data1, void *data2); + +static void get_coords (State *o, float screen_x, float screen_y, float *gegl_x, float *gegl_y); + +static void preview_more_cb (MrgEvent *event, void *data1, void *data2); + +static void preview_less_cb (MrgEvent *event, void *data1, void *data2); + +static void zoom_1_cb (MrgEvent *event, void *data1, void *data2); + +static void zoom_in_cb (MrgEvent *event, void *data1, void *data2); + +static void zoom_out_cb (MrgEvent *event, void *data1, void *data2); + +static void toggle_actions_cb (MrgEvent *event, void *data1, void *data2); + +static void toggle_fullscreen_cb (MrgEvent *event, void *data1, void *data2); + + +static void activate_op_cb (MrgEvent *event, void *data1, void *data2); + + +static void disable_filter_cb (MrgEvent *event, void *data1, void *data2); + +static void apply_filter_cb (MrgEvent *event, void *data1, void *data2); +static void discard_cb (MrgEvent *event, void *data1, void *data2); +static void save_cb (MrgEvent *event, void *data1, void *data2); + + + + +static void toggle_show_controls_cb (MrgEvent *event, void *data1, void *data2); + +static void gegl_ui (Mrg *mrg, void *data); +int mrg_ui_main (int argc, char **argv); + +void gegl_meta_set (const char *path, const char *meta_data); +char * gegl_meta_get (const char *path); + +static State *hack_state = NULL; // XXX: this shoudl be factored away + +int mrg_ui_main (int argc, char **argv) +{ + Mrg *mrg = mrg_new (1024, 768, NULL); + State o = {NULL,}; +#ifdef USE_MIPMAPS + g_setenv ("GEGL_MIPMAP_RENDERING", "1", TRUE); +#endif + g_setenv ("BABL_TOLERANCE", "0.1", TRUE); + + gegl_init (&argc, &argv); + o.gegl = gegl_node_new (); + o.mrg = mrg; + o.scale = 1.0; + o.render_quality = 1.0; + o.preview_quality = 4.0; + + if (access (argv[1], F_OK) != -1) + o.path = strdup (argv[1]); + else + { + printf ("usage: %s <full-path-to-image>\n", argv[0]); + return -1; + } + + load_path (&o); + mrg_set_ui (mrg, gegl_ui, &o); + hack_state = &o; + mrg_main (mrg); + + g_object_unref (o.gegl); + if (o.buffer) + { + g_object_unref (o.buffer); + o.buffer = NULL; + } + gegl_exit (); + return 0; +} + +static void on_pan_drag (MrgEvent *e, void *data1, void *data2) +{ + State *o = data1; + if (e->type == MRG_DRAG_MOTION) + { + o->u -= (e->delta_x ); + o->v -= (e->delta_y ); + mrg_queue_draw (e->mrg, NULL); + } + drag_preview (e); +} + +static void prop_double_drag_cb (MrgEvent *e, void *data1, void *data2) +{ + GeglNode *node = data1; + GParamSpec *pspec = data2; + GeglParamSpecDouble *gspec = data2; + gdouble value = 0.0; + float range = gspec->ui_maximum - gspec->ui_minimum; + + value = e->x / mrg_width (e->mrg); + value = value * range + gspec->ui_minimum; + gegl_node_set (node, pspec->name, value, NULL); + + drag_preview (e); + + mrg_queue_draw (e->mrg, NULL); +} + +static void draw_gegl_generic (State *state, Mrg *mrg, cairo_t *cr, GeglNode *node) +{ + const gchar* op_name = gegl_node_get_operation (node); + mrg_set_edge_left (mrg, mrg_width (mrg) * 0.1); + mrg_set_edge_top (mrg, mrg_height (mrg) * 0.1); + mrg_set_font_size (mrg, mrg_height (mrg) * 0.07); + mrg_set_style (mrg, "color:white; background-color: transparent"); + + cairo_save (cr); + mrg_printf (mrg, "%s\n", op_name); + { + guint n_props; + GParamSpec **pspecs = gegl_operation_list_properties (op_name, &n_props); + + if (pspecs) + { + int tot_pos = 0; + int pos_no = 0; + + for (gint i = 0; i < n_props; i++) + { + if (g_type_is_a (pspecs[i]->value_type, G_TYPE_DOUBLE) || + g_type_is_a (pspecs[i]->value_type, G_TYPE_INT) || + g_type_is_a (pspecs[i]->value_type, G_TYPE_STRING) || + g_type_is_a (pspecs[i]->value_type, G_TYPE_BOOLEAN)) + tot_pos ++; + } + + for (gint i = 0; i < n_props; i++) + { + mrg_set_xy (mrg, mrg_em(mrg), mrg_height (mrg) - mrg_em (mrg) * ((tot_pos-pos_no))); + + if (g_type_is_a (pspecs[i]->value_type, G_TYPE_DOUBLE)) + { + float xpos; + GeglParamSpecDouble *geglspec = (void*)pspecs[i]; + gdouble value; + gegl_node_get (node, pspecs[i]->name, &value, NULL); + + cairo_rectangle (cr, 0, + mrg_height (mrg) - mrg_em (mrg) * ((tot_pos-pos_no+1)), + mrg_width (mrg), mrg_em(mrg)); + cairo_set_source_rgba (cr, 0,0,0, 0.5); + + mrg_listen (mrg, MRG_DRAG, prop_double_drag_cb, node,(void*)pspecs[i]); + + cairo_fill (cr); + xpos = (value - geglspec->ui_minimum) / (geglspec->ui_maximum - geglspec->ui_minimum); + cairo_rectangle (cr, xpos * mrg_width(mrg) - mrg_em(mrg)/4, + mrg_height (mrg) - mrg_em (mrg) * ((tot_pos-pos_no+1)), + mrg_em(mrg)/2, mrg_em(mrg)); + cairo_set_source_rgba (cr, 1,1,1, 0.5); + cairo_fill (cr); + + mrg_printf (mrg, "%s:%f\n", pspecs[i]->name, value); + pos_no ++; + } + else if (g_type_is_a (pspecs[i]->value_type, G_TYPE_INT)) + { + gint value; + gegl_node_get (node, pspecs[i]->name, &value, NULL); + mrg_printf (mrg, "%s:%i\n", pspecs[i]->name, value); + pos_no ++; + } + else if (g_type_is_a (pspecs[i]->value_type, G_TYPE_STRING)) + { + char *value = NULL; + gegl_node_get (node, pspecs[i]->name, &value, NULL); + pos_no ++; + mrg_printf (mrg, "%s:%s\n", pspecs[i]->name, value); + if (value) g_free (value); + } + else if (g_type_is_a (pspecs[i]->value_type, G_TYPE_BOOLEAN)) + { + gboolean value = FALSE; + gegl_node_get (node, pspecs[i]->name, &value, NULL); + pos_no ++; + mrg_printf (mrg, "%s:%i\n", pspecs[i]->name, value); + } + + } + g_free (pspecs); + } + } + + cairo_restore (cr); + mrg_set_style (mrg, "color:yellow; background-color: transparent"); +} + +static void crop_drag_ul (MrgEvent *e, void *data1, void *data2) +{ + GeglNode *node = data1; + double x,y,width,height; + double x0, y0, x1, y1; + gegl_node_get (node, "x", &x, "y", &y, "width", &width, "height", &height, NULL); + x0 = x; y0 = y; x1 = x0 + width; y1 = y + height; + + if (e->type == MRG_DRAG_MOTION) + { + x0 += e->delta_x; + y0 += e->delta_y; + + x=x0; + y=y0; + width = x1 - x0; + height = y1 - y0; + gegl_node_set (node, "x", x, "y", y, "width", width, "height", height, NULL); + + mrg_queue_draw (e->mrg, NULL); + } + + drag_preview (e); +} + +static void crop_drag_lr (MrgEvent *e, void *data1, void *data2) +{ + GeglNode *node = data1; + double x,y,width,height; + double x0, y0, x1, y1; + gegl_node_get (node, "x", &x, "y", &y, "width", &width, "height", &height, NULL); + x0 = x; y0 = y; x1 = x0 + width; y1 = y + height; + + if (e->type == MRG_DRAG_MOTION) + { + x1 += e->delta_x; + y1 += e->delta_y; + + x=x0; + y=y0; + width = x1 - x0; + height = y1 - y0; + gegl_node_set (node, "x", x, "y", y, "width", width, "height", height, NULL); + + mrg_queue_draw (e->mrg, NULL); + } + + drag_preview (e); +} + +static void crop_drag_rotate (MrgEvent *e, void *data1, void *data2) +{ + State *o = hack_state; + double degrees; + gegl_node_get (o->rotate, "degrees", °rees, NULL); + + if (e->type == MRG_DRAG_MOTION) + { + degrees += e->delta_x / 100.0; + + gegl_node_set (o->rotate, "degrees", degrees, NULL); + + mrg_queue_draw (e->mrg, NULL); + } + + drag_preview (e); +} + +static void draw_gegl_crop (State *o, Mrg *mrg, cairo_t *cr, GeglNode *node) +{ + const gchar* op_name = gegl_node_get_operation (node); + float dim = mrg_height (mrg) * 0.1 / o->scale; + double x,y,width,height; + double x0, y0, x1, y1; + + mrg_set_edge_left (mrg, mrg_width (mrg) * 0.1); + mrg_set_edge_top (mrg, mrg_height (mrg) * 0.1); + mrg_set_font_size (mrg, mrg_height (mrg) * 0.07); + mrg_set_style (mrg, "color:white; background-color: transparent"); + + cairo_save (cr); + mrg_printf (mrg, "%s\n", op_name); + + cairo_translate (cr, -o->u, -o->v); + cairo_scale (cr, o->scale, o->scale); + + gegl_node_get (node, "x", &x, "y", &y, "width", &width, "height", &height, NULL); + x0 = x; y0 = y; x1 = x0 + width; y1 = y + height; + + cairo_rectangle (cr, x0, y0, dim, dim); + mrg_listen (mrg, MRG_DRAG, crop_drag_ul, node, NULL); + contrasty_stroke (cr); + + cairo_rectangle (cr, x1-dim, y1-dim, dim, dim); + mrg_listen (mrg, MRG_DRAG, crop_drag_lr, node, NULL); + contrasty_stroke (cr); + + cairo_rectangle (cr, x0+dim, y0+dim, width-dim-dim, height-dim-dim); + mrg_listen (mrg, MRG_DRAG, crop_drag_rotate, node, NULL); + cairo_new_path (cr); + + cairo_restore (cr); + mrg_set_style (mrg, "color:yellow; background-color: transparent"); +} + +static void ui_op_draw_apply_disable (State *o) +{ + Mrg *mrg = o->mrg; + mrg_set_font_size (mrg, mrg_height (mrg) * 0.1); + mrg_set_xy (mrg, 0, mrg_em(mrg)); + mrg_text_listen (mrg, MRG_PRESS, disable_filter_cb, o, NULL); + mrg_printf (mrg, "X"); + mrg_text_listen_done (mrg); + mrg_set_xy (mrg, mrg_width(mrg) - mrg_em (mrg), mrg_em(mrg)); + mrg_text_listen (mrg, MRG_PRESS, apply_filter_cb, o, NULL); + mrg_printf (mrg, "O"); + mrg_text_listen_done (mrg); +} + +static void ui_active_op (State *o) +{ + Mrg *mrg = o->mrg; + cairo_t *cr = mrg_cr (mrg); + char *opname = NULL; + g_object_get (o->active, "operation", &opname, NULL); + + if (!strcmp (opname, "gegl:crop")) { + zoom_to_fit_buffer (o); + draw_gegl_crop (o, mrg, cr, o->active); + ui_op_draw_apply_disable (o); + } + else + { + draw_gegl_generic (o, mrg, cr, o->active); + ui_op_draw_apply_disable (o); + } +} + +static void ui_debug_op_chain (State *o) +{ + Mrg *mrg = o->mrg; + GeglNode *iter; + mrg_set_edge_top (mrg, mrg_height (mrg) * 0.2); + iter = o->sink; + while (iter) + { + char *opname = NULL; + g_object_get (iter, "operation", &opname, NULL); + if (iter == o->active) + mrg_printf (mrg, "[%s]", opname); + else + mrg_printf (mrg, "%s", opname); + mrg_printf (mrg, "\n"); + + g_free (opname); + iter = gegl_node_get_producer (iter, "input", NULL); + } +} + +static void ui_actions (State *o) +{ + Mrg *mrg = o->mrg; + int i; + cairo_t *cr = mrg_cr (mrg); + mrg_set_edge_left (mrg, mrg_width (mrg) * 0.25); + mrg_set_edge_top (mrg, mrg_height (mrg) * 0.1); + mrg_set_font_size (mrg, mrg_height (mrg) * 0.08); + + for (i = 0; actions[i].label; i ++) + { + mrg_text_listen (mrg, MRG_PRESS, activate_op_cb, o, &actions[i]); + if (locate_node (o, actions[i].op_name)) + mrg_printf (mrg, "-"); + mrg_printf (mrg, "%s\n", actions[i].label); + mrg_text_listen_done (mrg); + } + + mrg_print (mrg, "\n"); + mrg_printf (mrg, "existing\n"); + mrg_text_listen (mrg, MRG_PRESS, discard_cb, o, NULL); + mrg_printf (mrg, "discard\n"); + mrg_text_listen_done (mrg); + cairo_scale (cr, mrg_width(mrg), mrg_height(mrg)); + cairo_new_path (cr); + cairo_arc (cr, 0.9, 0.1, 0.1, 0.0, G_PI * 2); + mrg_listen (mrg, MRG_PRESS, toggle_actions_cb, o, NULL); + contrasty_stroke (cr); +} + +static void ui_viewer (State *o) +{ + Mrg *mrg = o->mrg; + cairo_t *cr = mrg_cr (mrg); + cairo_rectangle (cr, 0,0, mrg_width(mrg), mrg_height(mrg)); + mrg_listen (mrg, MRG_DRAG, on_pan_drag, o, NULL); + cairo_new_path (cr); + cairo_scale (cr, mrg_width(mrg), mrg_height(mrg)); + cairo_move_to (cr, 0.2, 0.8); + cairo_line_to (cr, 0.2, 1.0); + cairo_line_to (cr, 0.0, 0.9); + cairo_close_path (cr); + mrg_listen (mrg, MRG_PRESS, go_prev_cb, o, NULL); + if (o->show_controls) + contrasty_stroke (cr); + else + cairo_new_path (cr); + + cairo_move_to (cr, 0.8, 0.8); + cairo_line_to (cr, 0.8, 1.0); + cairo_line_to (cr, 1.0, 0.9); + cairo_close_path (cr); + + mrg_listen (mrg, MRG_PRESS, go_next_cb, o, NULL); + if (o->show_controls) + contrasty_stroke (cr); + else + cairo_new_path (cr); + + cairo_arc (cr, 0.9, 0.1, 0.1, 0.0, G_PI * 2); + mrg_listen (mrg, MRG_PRESS, toggle_actions_cb, o, NULL); + + if (o->show_controls) + contrasty_stroke (cr); + else + cairo_new_path (cr); +} + +static void toggle_show_controls_cb (MrgEvent *event, void *data1, void *data2) +{ + State *o = data1; + o->show_controls = !o->show_controls; + mrg_queue_draw (o->mrg, NULL); +} + +static void gegl_ui (Mrg *mrg, void *data) +{ + State *o = data; + mrg_gegl_blit (mrg, + 0, 0, + mrg_width (mrg), mrg_height (mrg), + o->sink, + o->u, o->v, + o->scale, + o->render_quality); + + if (o->show_controls) + { + mrg_printf (mrg, "%s\n", o->path); +#if DEBUG_OP_LIST + ui_debug_op_chain (o); +#endif + } + + if (o->show_actions) + { + ui_actions (o); + mrg_add_binding (mrg, "return", NULL, NULL, toggle_actions_cb, o); + } + else if (o->active) + { + ui_active_op (o); + mrg_add_binding (mrg, "return", NULL, NULL, apply_filter_cb, o); + mrg_add_binding (mrg, "escape", NULL, NULL, disable_filter_cb, o); + } + else + { + ui_viewer (o); + mrg_add_binding (mrg, "return", NULL, NULL, toggle_actions_cb, o); + } + + mrg_add_binding (mrg, "left", NULL, NULL, pan_left_cb, o); + mrg_add_binding (mrg, "right", NULL, NULL, pan_right_cb, o); + mrg_add_binding (mrg, "up", NULL, NULL, pan_up_cb, o); + mrg_add_binding (mrg, "down", NULL, NULL, pan_down_cb, o); + mrg_add_binding (mrg, "+", NULL, NULL, zoom_in_cb, o); + mrg_add_binding (mrg, "=", NULL, NULL, zoom_in_cb, o); + mrg_add_binding (mrg, "-", NULL, NULL, zoom_out_cb, o); + mrg_add_binding (mrg, "1", NULL, NULL, zoom_1_cb, o); + mrg_add_binding (mrg, "m", NULL, NULL, zoom_fit_cb, o); + + mrg_add_binding (mrg, "control-q", NULL, NULL, mrg_quit_cb, o); + mrg_add_binding (mrg, "m", NULL, NULL, zoom_fit_cb, o); + mrg_add_binding (mrg, "q", NULL, NULL, mrg_quit_cb, o); + mrg_add_binding (mrg, "x", NULL, NULL, discard_cb, o); + mrg_add_binding (mrg, "f", NULL, NULL, toggle_fullscreen_cb, o); + mrg_add_binding (mrg, "F11", NULL, NULL, toggle_fullscreen_cb, o); + mrg_add_binding (mrg, "tab", NULL, NULL, toggle_show_controls_cb, o); + mrg_add_binding (mrg, "space", NULL, NULL, go_next_cb , o); + mrg_add_binding (mrg, "n", NULL, NULL, go_next_cb, o); + mrg_add_binding (mrg, "p", NULL, NULL, go_prev_cb, o); + mrg_add_binding (mrg, "backspace", NULL, NULL, go_prev_cb, o); + + mrg_add_binding (mrg, ",", NULL, NULL, preview_less_cb, o); + mrg_add_binding (mrg, ".", NULL, NULL, preview_more_cb, o); +} + +/***********************************************/ + static char *suffix_path (const char *path) { char *ret, *last_dot; @@ -105,21 +644,6 @@ static char *suffix_path (const char *path) return ret; } -static void contrasty_stroke (cairo_t *cr) -{ - double x0 = 6.0, y0 = 6.0; - double x1 = 4.0, y1 = 4.0; - - cairo_device_to_user_distance (cr, &x0, &y0); - cairo_device_to_user_distance (cr, &x1, &y1); - cairo_set_source_rgba (cr, 0,0,0,0.5); - cairo_set_line_width (cr, y0); - cairo_stroke_preserve (cr); - cairo_set_source_rgba (cr, 1,1,1,0.5); - cairo_set_line_width (cr, y1); - cairo_stroke (cr); -} - static char *unsuffix_path (const char *path) { char *ret = NULL, *last_dot, *extension; @@ -144,6 +668,21 @@ static int is_giev_path (const char *path) return 0; } +static void contrasty_stroke (cairo_t *cr) +{ + double x0 = 6.0, y0 = 6.0; + double x1 = 4.0, y1 = 4.0; + + cairo_device_to_user_distance (cr, &x0, &y0); + cairo_device_to_user_distance (cr, &x1, &y1); + cairo_set_source_rgba (cr, 0,0,0,0.5); + cairo_set_line_width (cr, y0); + cairo_stroke_preserve (cr); + cairo_set_source_rgba (cr, 1,1,1,0.5); + cairo_set_line_width (cr, y1); + cairo_stroke (cr); +} + static unsigned char *copy_buf = NULL; static int copy_buf_len = 0; @@ -223,7 +762,89 @@ foo++; cairo_restore (cr); } -static void load_path (State *o); +static void load_path (State *o) +{ + char *path; + char *meta; + if (is_giev_path (o->path)) + { + if (o->giev_path) + free (o->giev_path); + o->giev_path = o->path; + o->path = unsuffix_path (o->giev_path); + } + else + { + if (o->giev_path) + free (o->giev_path); + o->giev_path = suffix_path (o->path); + } + path = o->path; + + if (access (o->giev_path, F_OK) != -1) + path = o->giev_path; + + g_object_unref (o->gegl); + o->gegl = NULL; + + meta = gegl_meta_get (path); + if (meta) + { + GSList *nodes, *n; + o->gegl = gegl_node_new_from_xml (meta, NULL); + o->sink = gegl_node_new_child (o->gegl, + "operation", "gegl:nop", NULL); + o->source = NULL; + gegl_node_link_many ( + gegl_node_get_producer (o->gegl, "input", NULL), o->sink, NULL); + nodes = gegl_node_get_children (o->gegl); + for (n = nodes; n; n=n->next) + { + const char *op_name = gegl_node_get_operation (n->data); + if (!strcmp (op_name, "gegl:load")) + { + GeglNode *load; + gchar *path; + gegl_node_get (n->data, "path", &path, NULL); + load_into_buffer (o, path); + gegl_node_set (n->data, "operation", "gegl:nop", NULL); + o->source = n->data; + load = gegl_node_new_child (o->gegl, "operation", "gegl:buffer-source", + "buffer", o->buffer, NULL); + gegl_node_link_many (load, o->source, NULL); + g_free (path); + break; + } + } + o->save = gegl_node_new_child (o->gegl, + "operation", "gegl:save", + "path", path, + NULL); + } + else + { + o->gegl = gegl_node_new (); + o->sink = gegl_node_new_child (o->gegl, + "operation", "gegl:nop", NULL); + o->source = gegl_node_new_child (o->gegl, + "operation", "gegl:nop", NULL); + load_into_buffer (o, path); + o->load = gegl_node_new_child (o->gegl, + "operation", "gegl:buffer-source", + NULL); + o->save = gegl_node_new_child (o->gegl, + "operation", "gegl:save", + "path", o->giev_path, + NULL); + gegl_node_link_many (o->load, o->source, o->sink, NULL); + gegl_node_set (o->load, "buffer", o->buffer, NULL); + } + zoom_to_fit (o); + + mrg_queue_draw (o->mrg, NULL); + o->rev = 0; +} + static void go_next (State *o) { @@ -315,8 +936,6 @@ static void go_prev (State *o) } } -static void save_cb (MrgEvent *event, void *data1, void *data2); - static void go_next_cb (MrgEvent *event, void *data1, void *data2) { State *o = data1; @@ -337,12 +956,20 @@ static void go_prev_cb (MrgEvent *event, void *data1, void *data2) mrg_event_stop_propagate (event); } -static void on_pan_drag (MrgEvent *e, void *data1, void *data2) +static void leave_editor (State *o) { - State *o = data1; + char *opname = NULL; + g_object_get (o->active, "operation", &opname, NULL); + if (!strcmp (opname, "gegl:crop")) + { + zoom_to_fit (o); + } +} +static void drag_preview (MrgEvent *e) +{ + State *o = hack_state; static float old_factor = 1; - switch (e->type) { case MRG_DRAG_PRESS: @@ -354,11 +981,6 @@ static void on_pan_drag (MrgEvent *e, void *data1, void *data2) o->render_quality = old_factor; mrg_queue_draw (e->mrg, NULL); break; - case MRG_DRAG_MOTION: - o->u -= (e->delta_x ); - o->v -= (e->delta_y ); - mrg_queue_draw (e->mrg, NULL); - break; default: break; } @@ -394,6 +1016,20 @@ static void load_into_buffer (State *o, const char *path) o->buffer = tempbuf; } +static GeglNode *locate_node (State *o, const char *op_name) +{ + GeglNode *iter = o->sink; + while (iter) + { + char *opname = NULL; + g_object_get (iter, "operation", &opname, NULL); + if (!strcmp (opname, op_name)) + return iter; + g_free (opname); + iter = gegl_node_get_producer (iter, "input", NULL); + } + return NULL; +} static void zoom_to_fit (State *o) { Mrg *mrg = o->mrg; @@ -428,13 +1064,10 @@ static void zoom_to_fit_buffer (State *o) if (scale2 < scale) scale = scale2; o->scale = scale; - o->u = -(mrg_width (mrg) - rect.width * scale) / 2; o->v = -(mrg_height (mrg) - rect.height * scale) / 2; - o->u += rect.x * scale; o->v += rect.y * scale; - mrg_queue_draw (mrg, NULL); } @@ -461,7 +1094,6 @@ static void pan_right_cb (MrgEvent *event, void *data1, void *data2) { State *o = data1; float amount = mrg_width (event->mrg) * 0.1; - o->u = o->u + amount; mrg_queue_draw (o->mrg, NULL); } @@ -470,7 +1102,6 @@ static void pan_down_cb (MrgEvent *event, void *data1, void *data2) { State *o = data1; float amount = mrg_width (event->mrg) * 0.1; - o->v = o->v + amount; mrg_queue_draw (o->mrg, NULL); } @@ -479,9 +1110,7 @@ static void pan_up_cb (MrgEvent *event, void *data1, void *data2) { State *o = data1; float amount = mrg_width (event->mrg) * 0.1; - o->v = o->v - amount; - mrg_queue_draw (o->mrg, NULL); } @@ -505,7 +1134,6 @@ static void preview_less_cb (MrgEvent *event, void *data1, void *data2) o->render_quality /= 2; if (o->render_quality <= 1.0) o->render_quality = 1.0; - mrg_queue_draw (o->mrg, NULL); } @@ -557,30 +1185,14 @@ static void toggle_fullscreen_cb (MrgEvent *event, void *data1, void *data2) mrg_add_timeout (event->mrg, 250, deferred_zoom_to_fit, o); } -static GeglNode *locate_node (State *o, const char *op_name) -{ - GeglNode *iter = o->sink; - while (iter) - { - char *opname = NULL; - g_object_get (iter, "operation", &opname, NULL); - if (!strcmp (opname, op_name)) - return iter; - g_free (opname); - iter = gegl_node_get_producer (iter, "input", NULL); - } - return NULL; -} static void activate_op_cb (MrgEvent *event, void *data1, void *data2) { State *o = data1; GeglNode *found; ActionData *ad = data2; - o->show_actions = 0; o->rev ++; - found = locate_node (o, ad->op_name); if (found) { @@ -634,16 +1246,6 @@ static void activate_op_cb (MrgEvent *event, void *data1, void *data2) mrg_queue_draw (o->mrg, NULL); } -static void leave_editor (State *o) -{ - char *opname = NULL; - g_object_get (o->active, "operation", &opname, NULL); - if (!strcmp (opname, "gegl:crop")) - { - zoom_to_fit (o); - } -} - static void disable_filter_cb (MrgEvent *event, void *data1, void *data2) { State *o = data1; @@ -666,6 +1268,7 @@ static void disable_filter_cb (MrgEvent *event, void *data1, void *data2) o->active = NULL; mrg_queue_draw (o->mrg, NULL); } + static void apply_filter_cb (MrgEvent *event, void *data1, void *data2) { State *o = data1; @@ -704,316 +1307,6 @@ static void discard_cb (MrgEvent *event, void *data1, void *data2) free (old_path); } -static State *hack_state = NULL; -static void prop_double_drag_cb (MrgEvent *e, void *data1, void *data2) -{ - GeglNode *node = data1; - GParamSpec *pspec = data2; - State *o = hack_state; - static float old_factor = 1; - GeglParamSpecDouble *gspec = data2; - gdouble value = 0.0; - float range = gspec->ui_maximum - gspec->ui_minimum; - - value = e->x / mrg_width (e->mrg); - value = value * range + gspec->ui_minimum; - gegl_node_set (node, pspec->name, value, NULL); - - switch (e->type) - { - case MRG_DRAG_PRESS: - old_factor = o->render_quality; - if (o->render_quality < o->preview_quality) - o->render_quality = o->preview_quality; - break; - case MRG_DRAG_RELEASE: - o->render_quality = old_factor; - mrg_queue_draw (e->mrg, NULL); - break; - default: - break; - } - - mrg_queue_draw (e->mrg, NULL); -} - -static void draw_gegl_generic (State *state, Mrg *mrg, cairo_t *cr, GeglNode *node) -{ - const gchar* op_name = gegl_node_get_operation (node); - mrg_set_edge_left (mrg, mrg_width (mrg) * 0.1); - mrg_set_edge_top (mrg, mrg_height (mrg) * 0.1); - mrg_set_font_size (mrg, mrg_height (mrg) * 0.07); - mrg_set_style (mrg, "color:white; background-color: transparent"); - - cairo_save (cr); - mrg_printf (mrg, "%s\n", op_name); - { - guint n_props; - GParamSpec **pspecs = gegl_operation_list_properties (op_name, &n_props); - - if (pspecs) - { - int tot_pos = 0; - int pos_no = 0; - - for (gint i = 0; i < n_props; i++) - { - if (g_type_is_a (pspecs[i]->value_type, G_TYPE_DOUBLE) || - g_type_is_a (pspecs[i]->value_type, G_TYPE_INT) || - g_type_is_a (pspecs[i]->value_type, G_TYPE_STRING) || - g_type_is_a (pspecs[i]->value_type, G_TYPE_BOOLEAN)) - tot_pos ++; - } - - for (gint i = 0; i < n_props; i++) - { - mrg_set_xy (mrg, mrg_em(mrg), mrg_height (mrg) - mrg_em (mrg) * ((tot_pos-pos_no))); - - - if (g_type_is_a (pspecs[i]->value_type, G_TYPE_DOUBLE)) - { - float xpos; - GeglParamSpecDouble *geglspec = (void*)pspecs[i]; - gdouble value; - gegl_node_get (node, pspecs[i]->name, &value, NULL); - - cairo_rectangle (cr, 0, - mrg_height (mrg) - mrg_em (mrg) * ((tot_pos-pos_no+1)), - mrg_width (mrg), mrg_em(mrg)); - cairo_set_source_rgba (cr, 0,0,0, 0.5); - - mrg_listen (mrg, MRG_DRAG, prop_double_drag_cb, node,(void*)pspecs[i]); - - cairo_fill (cr); - xpos = (value - geglspec->ui_minimum) / (geglspec->ui_maximum - geglspec->ui_minimum); - cairo_rectangle (cr, xpos * mrg_width(mrg) - mrg_em(mrg)/4, - mrg_height (mrg) - mrg_em (mrg) * ((tot_pos-pos_no+1)), - mrg_em(mrg)/2, mrg_em(mrg)); - cairo_set_source_rgba (cr, 1,1,1, 0.5); - cairo_fill (cr); - - mrg_printf (mrg, "%s:%f\n", pspecs[i]->name, value); - pos_no ++; - } - else if (g_type_is_a (pspecs[i]->value_type, G_TYPE_INT)) - { - gint value; - gegl_node_get (node, pspecs[i]->name, &value, NULL); - mrg_printf (mrg, "%s:%i\n", pspecs[i]->name, value); - pos_no ++; - } - else if (g_type_is_a (pspecs[i]->value_type, G_TYPE_STRING)) - { - char *value = NULL; - gegl_node_get (node, pspecs[i]->name, &value, NULL); - pos_no ++; - mrg_printf (mrg, "%s:%s\n", pspecs[i]->name, value); - if (value) g_free (value); - } - else if (g_type_is_a (pspecs[i]->value_type, G_TYPE_BOOLEAN)) - { - gboolean value = FALSE; - gegl_node_get (node, pspecs[i]->name, &value, NULL); - pos_no ++; - mrg_printf (mrg, "%s:%i\n", pspecs[i]->name, value); - } - - } - g_free (pspecs); - } - } - - cairo_restore (cr); - mrg_set_style (mrg, "color:yellow; background-color: transparent"); -} - -static void crop_drag_ul (MrgEvent *e, void *data1, void *data2) -{ - GeglNode *node = data1; - State *o = hack_state; - static float old_factor = 1; - - double x,y,width,height; - double x0, y0, x1, y1; - gegl_node_get (node, "x", &x, "y", &y, "width", &width, "height", &height, NULL); - x0 = x; y0 = y; x1 = x0 + width; y1 = y + height; - - if (e->type == MRG_DRAG_MOTION) - { - x0 += e->delta_x; - y0 += e->delta_y; - - x=x0; - y=y0; - width = x1 - x0; - height = y1 - y0; - gegl_node_set (node, "x", x, "y", y, "width", width, "height", height, NULL); - - mrg_queue_draw (e->mrg, NULL); - } - - switch (e->type) - { - case MRG_DRAG_PRESS: - old_factor = o->render_quality; - if (o->render_quality < o->preview_quality) - o->render_quality = o->preview_quality; - break; - case MRG_DRAG_RELEASE: - o->render_quality = old_factor; - mrg_queue_draw (e->mrg, NULL); - break; - default: - break; - } -} - -static void crop_drag_lr (MrgEvent *e, void *data1, void *data2) -{ - GeglNode *node = data1; - State *o = hack_state; - static float old_factor = 1; - - double x,y,width,height; - double x0, y0, x1, y1; - gegl_node_get (node, "x", &x, "y", &y, "width", &width, "height", &height, NULL); - x0 = x; y0 = y; x1 = x0 + width; y1 = y + height; - - if (e->type == MRG_DRAG_MOTION) - { - x1 += e->delta_x; - y1 += e->delta_y; - - x=x0; - y=y0; - width = x1 - x0; - height = y1 - y0; - gegl_node_set (node, "x", x, "y", y, "width", width, "height", height, NULL); - - mrg_queue_draw (e->mrg, NULL); - } - - - switch (e->type) - { - case MRG_DRAG_PRESS: - old_factor = o->render_quality; - if (o->render_quality < o->preview_quality) - o->render_quality = o->preview_quality; - break; - case MRG_DRAG_RELEASE: - o->render_quality = old_factor; - mrg_queue_draw (e->mrg, NULL); - break; - default: - break; - } -} - - -static void crop_drag_rotate (MrgEvent *e, void *data1, void *data2) -{ - State *o = hack_state; - static float old_factor = 1; - - double degrees; - gegl_node_get (o->rotate, "degrees", °rees, NULL); - - if (e->type == MRG_DRAG_MOTION) - { - degrees += e->delta_x / 100.0; - - gegl_node_set (o->rotate, "degrees", degrees, NULL); - - mrg_queue_draw (e->mrg, NULL); - } - - switch (e->type) - { - case MRG_DRAG_PRESS: - old_factor = o->render_quality; - if (o->render_quality < o->preview_quality) - o->render_quality = o->preview_quality; - break; - case MRG_DRAG_RELEASE: - o->render_quality = old_factor; - mrg_queue_draw (e->mrg, NULL); - break; - default: - break; - } -} - -static void draw_gegl_crop (State *o, Mrg *mrg, cairo_t *cr, GeglNode *node) -{ - const gchar* op_name = gegl_node_get_operation (node); - float dim = mrg_height (mrg) * 0.1 / o->scale; - double x,y,width,height; - double x0, y0, x1, y1; - - mrg_set_edge_left (mrg, mrg_width (mrg) * 0.1); - mrg_set_edge_top (mrg, mrg_height (mrg) * 0.1); - mrg_set_font_size (mrg, mrg_height (mrg) * 0.07); - mrg_set_style (mrg, "color:white; background-color: transparent"); - - cairo_save (cr); - mrg_printf (mrg, "%s\n", op_name); - - cairo_translate (cr, -o->u, -o->v); - cairo_scale (cr, o->scale, o->scale); - - gegl_node_get (node, "x", &x, "y", &y, "width", &width, "height", &height, NULL); - x0 = x; y0 = y; x1 = x0 + width; y1 = y + height; - - cairo_rectangle (cr, x0, y0, dim, dim); - mrg_listen (mrg, MRG_DRAG, crop_drag_ul, node, NULL); - contrasty_stroke (cr); - - cairo_rectangle (cr, x1-dim, y1-dim, dim, dim); - mrg_listen (mrg, MRG_DRAG, crop_drag_lr, node, NULL); - contrasty_stroke (cr); - - cairo_rectangle (cr, x0+dim, y0+dim, width-dim-dim, height-dim-dim); - mrg_listen (mrg, MRG_DRAG, crop_drag_rotate, node, NULL); - cairo_new_path (cr); - - cairo_restore (cr); - mrg_set_style (mrg, "color:yellow; background-color: transparent"); -} - -static void ui_op_draw_apply_disable (State *o) -{ - Mrg *mrg = o->mrg; - mrg_set_font_size (mrg, mrg_height (mrg) * 0.1); - mrg_set_xy (mrg, 0, mrg_em(mrg)); - mrg_text_listen (mrg, MRG_PRESS, disable_filter_cb, o, NULL); - mrg_printf (mrg, "X"); - mrg_text_listen_done (mrg); - mrg_set_xy (mrg, mrg_width(mrg) - mrg_em (mrg), mrg_em(mrg)); - mrg_text_listen (mrg, MRG_PRESS, apply_filter_cb, o, NULL); - mrg_printf (mrg, "O"); - mrg_text_listen_done (mrg); -} - -static void ui_active_op (State *o) -{ - Mrg *mrg = o->mrg; - cairo_t *cr = mrg_cr (mrg); - char *opname = NULL; - g_object_get (o->active, "operation", &opname, NULL); - - if (!strcmp (opname, "gegl:crop")) { - zoom_to_fit_buffer (o); - draw_gegl_crop (o, mrg, cr, o->active); - ui_op_draw_apply_disable (o); - } - else - { - draw_gegl_generic (o, mrg, cr, o->active); - ui_op_draw_apply_disable (o); - } -} - static void save_cb (MrgEvent *event, void *data1, void *data2) { GeglNode *load; @@ -1038,164 +1331,6 @@ static void save_cb (MrgEvent *event, void *data1, void *data2) o->rev = 0; } -static void ui_debug_op_chain (State *o) -{ - Mrg *mrg = o->mrg; - GeglNode *iter; - mrg_set_edge_top (mrg, mrg_height (mrg) * 0.2); - iter = o->sink; - while (iter) - { - char *opname = NULL; - g_object_get (iter, "operation", &opname, NULL); - if (iter == o->active) - mrg_printf (mrg, "[%s]", opname); - else - mrg_printf (mrg, "%s", opname); - mrg_printf (mrg, "\n"); - - g_free (opname); - iter = gegl_node_get_producer (iter, "input", NULL); - } -} - -static void ui_actions (State *o) -{ - Mrg *mrg = o->mrg; - int i; - cairo_t *cr = mrg_cr (mrg); - mrg_set_edge_left (mrg, mrg_width (mrg) * 0.25); - mrg_set_edge_top (mrg, mrg_height (mrg) * 0.1); - mrg_set_font_size (mrg, mrg_height (mrg) * 0.08); - - for (i = 0; actions[i].label; i ++) - { - mrg_text_listen (mrg, MRG_PRESS, activate_op_cb, o, &actions[i]); - if (locate_node (o, actions[i].op_name)) - mrg_printf (mrg, "-"); - mrg_printf (mrg, "%s\n", actions[i].label); - mrg_text_listen_done (mrg); - } - - mrg_print (mrg, "\n"); - mrg_printf (mrg, "existing\n"); - mrg_text_listen (mrg, MRG_PRESS, discard_cb, o, NULL); - mrg_printf (mrg, "discard\n"); - mrg_text_listen_done (mrg); - cairo_scale (cr, mrg_width(mrg), mrg_height(mrg)); - cairo_new_path (cr); - cairo_arc (cr, 0.9, 0.1, 0.1, 0.0, G_PI * 2); - mrg_listen (mrg, MRG_PRESS, toggle_actions_cb, o, NULL); - contrasty_stroke (cr); -} - -static void ui_viewer (State *o) -{ - Mrg *mrg = o->mrg; - cairo_t *cr = mrg_cr (mrg); - cairo_rectangle (cr, 0,0, mrg_width(mrg), mrg_height(mrg)); - mrg_listen (mrg, MRG_DRAG, on_pan_drag, o, NULL); - cairo_new_path (cr); - cairo_scale (cr, mrg_width(mrg), mrg_height(mrg)); - cairo_move_to (cr, 0.2, 0.8); - cairo_line_to (cr, 0.2, 1.0); - cairo_line_to (cr, 0.0, 0.9); - cairo_close_path (cr); - mrg_listen (mrg, MRG_PRESS, go_prev_cb, o, NULL); - if (o->show_controls) - contrasty_stroke (cr); - else - cairo_new_path (cr); - - cairo_move_to (cr, 0.8, 0.8); - cairo_line_to (cr, 0.8, 1.0); - cairo_line_to (cr, 1.0, 0.9); - cairo_close_path (cr); - - mrg_listen (mrg, MRG_PRESS, go_next_cb, o, NULL); - if (o->show_controls) - contrasty_stroke (cr); - else - cairo_new_path (cr); - - cairo_arc (cr, 0.9, 0.1, 0.1, 0.0, G_PI * 2); - mrg_listen (mrg, MRG_PRESS, toggle_actions_cb, o, NULL); - - if (o->show_controls) - contrasty_stroke (cr); - else - cairo_new_path (cr); -} - -static void toggle_show_controls_cb (MrgEvent *event, void *data1, void *data2) -{ - State *o = data1; - o->show_controls = !o->show_controls; - mrg_queue_draw (o->mrg, NULL); -} - -static void ui (Mrg *mrg, void *data) -{ - State *o = data; - mrg_gegl_blit (mrg, - 0, 0, - mrg_width (mrg), mrg_height (mrg), - o->sink, - o->u, o->v, - o->scale, - o->render_quality); - - if (o->show_controls) - { - mrg_printf (mrg, "%s\n", o->path); -#if DEBUG_OP_LIST - ui_debug_op_chain (o); -#endif - } - - if (o->show_actions) - { - ui_actions (o); - mrg_add_binding (mrg, "return", NULL, NULL, toggle_actions_cb, o); - } - else if (o->active) - { - ui_active_op (o); - mrg_add_binding (mrg, "return", NULL, NULL, apply_filter_cb, o); - mrg_add_binding (mrg, "escape", NULL, NULL, disable_filter_cb, o); - } - else - { - ui_viewer (o); - mrg_add_binding (mrg, "return", NULL, NULL, toggle_actions_cb, o); - } - - mrg_add_binding (mrg, "left", NULL, NULL, pan_left_cb, o); - mrg_add_binding (mrg, "right", NULL, NULL, pan_right_cb, o); - mrg_add_binding (mrg, "up", NULL, NULL, pan_up_cb, o); - mrg_add_binding (mrg, "down", NULL, NULL, pan_down_cb, o); - mrg_add_binding (mrg, "+", NULL, NULL, zoom_in_cb, o); - mrg_add_binding (mrg, "=", NULL, NULL, zoom_in_cb, o); - mrg_add_binding (mrg, "-", NULL, NULL, zoom_out_cb, o); - mrg_add_binding (mrg, "1", NULL, NULL, zoom_1_cb, o); - mrg_add_binding (mrg, "m", NULL, NULL, zoom_fit_cb, o); - - mrg_add_binding (mrg, "control-q", NULL, NULL, mrg_quit_cb, o); - mrg_add_binding (mrg, "m", NULL, NULL, zoom_fit_cb, o); - mrg_add_binding (mrg, "q", NULL, NULL, mrg_quit_cb, o); - mrg_add_binding (mrg, "x", NULL, NULL, discard_cb, o); - mrg_add_binding (mrg, "f", NULL, NULL, toggle_fullscreen_cb, o); - mrg_add_binding (mrg, "F11", NULL, NULL, toggle_fullscreen_cb, o); - mrg_add_binding (mrg, "tab", NULL, NULL, toggle_show_controls_cb, o); - mrg_add_binding (mrg, "space", NULL, NULL, go_next_cb , o); - mrg_add_binding (mrg, "n", NULL, NULL, go_next_cb, o); - mrg_add_binding (mrg, "p", NULL, NULL, go_prev_cb, o); - mrg_add_binding (mrg, "backspace", NULL, NULL, go_prev_cb, o); - - mrg_add_binding (mrg, ",", NULL, NULL, preview_less_cb, o); - mrg_add_binding (mrg, ".", NULL, NULL, preview_more_cb, o); -} - #if 0 void gegl_node_defaults (GeglNode *node) { @@ -1233,129 +1368,6 @@ void gegl_node_defaults (GeglNode *node) * creates live gegl pipeline, or nops.. rigs up o->giev_path to be * the location where default saves ends up. */ -static void load_path (State *o) -{ - char *path; - char *meta; - if (is_giev_path (o->path)) - { - if (o->giev_path) - free (o->giev_path); - o->giev_path = o->path; - o->path = unsuffix_path (o->giev_path); - } - else - { - if (o->giev_path) - free (o->giev_path); - o->giev_path = suffix_path (o->path); - } - path = o->path; - - if (access (o->giev_path, F_OK) != -1) - path = o->giev_path; - - g_object_unref (o->gegl); - o->gegl = NULL; - - meta = gegl_meta_get (path); - if (meta) - { - GSList *nodes, *n; - o->gegl = gegl_node_new_from_xml (meta, NULL); - o->sink = gegl_node_new_child (o->gegl, - "operation", "gegl:nop", NULL); - o->source = NULL; - gegl_node_link_many ( - gegl_node_get_producer (o->gegl, "input", NULL), o->sink, NULL); - nodes = gegl_node_get_children (o->gegl); - for (n = nodes; n; n=n->next) - { - const char *op_name = gegl_node_get_operation (n->data); - if (!strcmp (op_name, "gegl:load")) - { - GeglNode *load; - gchar *path; - gegl_node_get (n->data, "path", &path, NULL); - load_into_buffer (o, path); - gegl_node_set (n->data, "operation", "gegl:nop", NULL); - o->source = n->data; - load = gegl_node_new_child (o->gegl, "operation", "gegl:buffer-source", - "buffer", o->buffer, NULL); - gegl_node_link_many (load, o->source, NULL); - g_free (path); - break; - } - } - o->save = gegl_node_new_child (o->gegl, - "operation", "gegl:save", - "path", path, - NULL); - } - else - { - o->gegl = gegl_node_new (); - o->sink = gegl_node_new_child (o->gegl, - "operation", "gegl:nop", NULL); - o->source = gegl_node_new_child (o->gegl, - "operation", "gegl:nop", NULL); - load_into_buffer (o, path); - o->load = gegl_node_new_child (o->gegl, - "operation", "gegl:buffer-source", - NULL); - o->save = gegl_node_new_child (o->gegl, - "operation", "gegl:save", - "path", o->giev_path, - NULL); - gegl_node_link_many (o->load, o->source, o->sink, NULL); - gegl_node_set (o->load, "buffer", o->buffer, NULL); - } - zoom_to_fit (o); - - mrg_queue_draw (o->mrg, NULL); - o->rev = 0; -} - -int mrg_ui_main (int argc, char **argv); -int mrg_ui_main (int argc, char **argv) -{ - Mrg *mrg = mrg_new (1024, 768, NULL); - State o = {NULL,}; -#ifdef USE_MIPMAPS - g_setenv ("GEGL_MIPMAP_RENDERING", "1", TRUE); -#endif - g_setenv ("BABL_TOLERANCE", "0.1", TRUE); - - gegl_init (&argc, &argv); - o.gegl = gegl_node_new (); - o.mrg = mrg; - o.scale = 1.0; - o.render_quality = 1.0; - o.preview_quality = 4.0; - - if (access (argv[1], F_OK) != -1) - o.path = strdup (argv[1]); - else - { - printf ("usage: %s <full-path-to-image>\n", argv[0]); - return -1; - } - - load_path (&o); - mrg_set_ui (mrg, ui, &o); - hack_state = &o; - mrg_main (mrg); - - g_object_unref (o.gegl); - if (o.buffer) - { - g_object_unref (o.buffer); - o.buffer = NULL; - } - gegl_exit (); - return 0; -} - void gegl_meta_set (const char *path, const char *meta_data) |