gegl.c 10.6 KB
Newer Older
1 2 3 4
/* This file is part of GEGL editor -- a gtk frontend for GEGL
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
5
 * the Free Software Foundation; either version 3 of the License, or
6 7 8 9 10 11 12 13
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
14
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
15
 *
16
 * Copyright (C) 2003, 2004, 2006, 2007, 2008 Øyvind Kolås
17 18
 */

Øyvind Kolås's avatar
Øyvind Kolås committed
19 20
#include "config.h"

21
#include <glib.h>
22
#include <glib/gprintf.h>
23 24
#include <gegl.h>
#include <stdio.h>
25
#include <stdlib.h>
26
#include <string.h>
27
#ifdef HAVE_UNISTD_H
28
#include <unistd.h>
29
#endif
30

31
#include "gegl-options.h"
32
#ifdef HAVE_SPIRO
33
#include "gegl-path-spiro.h"
34
#endif
35
#include "gegl-path-smooth.h"
36
#include "operation/gegl-extension-handler.h"
37

38
#ifdef G_OS_WIN32
39 40
#include <direct.h>
#define getcwd(b,n) _getcwd(b,n)
41 42 43
#define realpath(a,b) _fullpath(b,a,_MAX_PATH)
#endif

44
#define DEFAULT_COMPOSITION \
45
"<?xml version='1.0' encoding='UTF-8'?> <gegl> <node operation='gegl:crop'> <params> <param name='x'>0</param> <param name='y'>0</param> <param name='width'>395</param> <param name='height'>200</param> </params> </node> <node operation='gegl:over'> <node operation='gegl:translate'> <params> <param name='x'>80</param> <param name='y'>162</param> </params> </node> <node operation='gegl:opacity'> <params> <param name='value'>0.5</param> </params> </node> <node name='text' operation='gegl:text'> <params> <param name='string'>2000-2011 © Various contributors</param> <param name='font'>Sans</param> <param name='size'>12</param> <param name='color'>rgb(0.0000, 0.0000, 0.0000)</param> <param name='wrap'>628</param> <param name='alignment'>0</param> <param name='width'>622</param> <param name='height'>40</param> </params> </node> </node> <node operation='gegl:over'> <node operation='gegl:translate'> <params> <param name='x'>20</param> <param name='y'>50</param> </params> </node> <node operation='gegl:over'> <node operation='gegl:translate'> <params> <param name='x'>0</param> <param name='y'>0</param> </params> </node> <node operation='gegl:dropshadow'> <params> <param name='opacity'>1.2</param> <param name='x'>0</param> <param name='y'>0</param> <param name='radius'>8</param> </params> </node> <gegl:fill-path d='M0,50 C0,78 24,100 50,100 C77,100 100,78 100,50 C100,45 99,40 98,35 C82,35 66,35 50,35 C42,35 35,42 35,50 C35,58 42,65 50,65 C56,65 61,61 64,56 C67,51 75,55 73,60 C69,69 60,75 50,75 C36,75 25,64 25,50 C25,36 36,25 50,25 L93,25 C83,9 67,0 49,0 C25,0 0,20 0,50 z' color='white'/> </node> <node operation='gegl:over'> <node operation='gegl:translate'> <params> <param name='x'>88</param> <param name='y'>0</param> </params> </node> <node operation='gegl:dropshadow'> <params> <param name='opacity'>1.2</param> <param name='x'>0</param> <param name='y'>0</param> <param name='radius'>8</param> </params> </node> <node operation='gegl:fill-path'> <params> <param name='d'>M50,0 C23,0 0,22 0,50 C0,77 22,100 50,100 C68,100 85,90 93,75 L40,75 C35,75 35,65 40,65 L98,65 C100,55 100,45 98,35 L40,35 C35,35 35,25 40,25 L93,25 C84,10 68,0 50,0 z</param> <param name='color'>rgb(1.0000, 1.0000, 1.0000)</param> </params> </node> </node> <node operation='gegl:over'> <node operation='gegl:translate'> <params> <param name='x'>176</param> <param name='y'>0</param> </params> </node> <node operation='gegl:dropshadow'> <params> <param name='opacity'>1.2</param> <param name='x'>0</param> <param name='y'>0</param> <param name='radius'>8</param> </params> </node> <node operation='gegl:fill-path'> <params> <param name='d'>M0,50 C0,78 24,100 50,100 C77,100 100,78 100,50 C100,45 99,40 98,35 C82,35 66,35 50,35 C42,35 35,42 35,50 C35,58 42,65 50,65 C56,65 61,61 64,56 C67,51 75,55 73,60 C69,69 60,75 50,75 C36,75 25,64 25,50 C25,36 36,25 50,25 L93,25 C83,9 67,0 49,0 C25,0 0,20 0,50 z</param> <param name='color'>rgb(1.0000, 1.0000, 1.0000)</param> </params> </node> </node> <node operation='gegl:translate'> <params> <param name='x'>264</param> <param name='y'>0</param> </params> </node> <node operation='gegl:dropshadow'> <params> <param name='opacity'>1.2</param> <param name='x'>0</param> <param name='y'>0</param> <param name='radius'>8</param> </params> </node> <node operation='gegl:fill-path'> <params> <param name='d'>M30,4 C12,13 0,30 0,50 C0,78 23,100 50,100 C71,100 88,88 96,71 L56,71 C42,71 30,59 30,45 L30,4 z</param> <param name='color'>rgb(1.0000, 1.0000, 1.0000)</param> </params> </node> </node> <node operation='gegl:rotate'> <params> <param name='origin-x'>0</param> <param name='origin-y'>0</param> <param name='filter'>linear</param> <param name='hard-edges'>false</param> <param name='lanczos-width'>3</param> <param name='degrees'>42</param> </params> </node> <node operation='gegl:checkerboard'> <params> <param name='x'>43</param> <param name='y'>44</param> <param name='x-offset'>0</param> <param name='y-offset'>0</param> <param name='color1'>rgb(0.7097, 0.7097, 0.7097)</param> <param name='color2'>rgb(0.7661, 0.7661, 0.7661)</param> </params> </node> </gegl>"
46

47 48
#define STDIN_BUF_SIZE 128

49 50 51 52 53 54 55 56 57 58 59
static void
gegl_enable_fatal_warnings (void)
{
  GLogLevelFlags fatal_mask;

  fatal_mask = g_log_set_always_fatal (G_LOG_FATAL_MASK);
  fatal_mask |= G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL;

  g_log_set_always_fatal (fatal_mask);
}

60 61 62 63 64 65 66 67 68 69 70
static gboolean file_is_gegl_xml (const gchar *path)
{
  gchar *extension;

  extension = strrchr (path, '.');
  if (!extension)
    return FALSE;
  extension++;
  if (extension[0]=='\0')
    return FALSE;
  if (!strcmp (extension, "xml")||
71 72 73
      !strcmp (extension, "XML")||
      !strcmp (extension, "svg")
      )
74 75 76
    return TRUE;
  return FALSE;
}
77 78 79 80 81

gint
main (gint    argc,
      gchar **argv)
{
82 83 84 85
  GeglOptions *o         = NULL;
  GeglNode    *gegl      = NULL;
  gchar       *script    = NULL;
  GError      *err       = NULL;
86
  gchar       *path_root = NULL;
87 88

  o = gegl_options_parse (argc, argv);
89 90 91 92 93 94

  if (o->fatal_warnings)
    {
      gegl_enable_fatal_warnings ();
    }

95
  g_thread_init (NULL);
96
  gegl_init (&argc, &argv);
97
#ifdef HAVE_SPIRO
98
  gegl_path_spiro_init ();
99
#endif
100
  gegl_path_smooth_init ();
101 102 103

  if (o->xml)
    {
104
      path_root = g_get_current_dir ();
105 106 107 108 109
    }
  else if (o->file)
    {
      if (!strcmp (o->file, "-"))  /* read XML from stdin */
        {
110
          path_root = g_get_current_dir ();
111 112 113
        }
      else
        {
114
          gchar *tmp;
115
          gchar *temp1 = g_strdup (o->file);
116
          gchar *temp2 = g_path_get_dirname (temp1);
117 118
          path_root = g_strdup (tmp = realpath (temp2, NULL));
          g_free (tmp);
119 120 121 122 123
          g_free (temp1);
          g_free (temp2);
        }
    }

124 125 126 127 128 129
  if (o->xml)
    {
      script = g_strdup (o->xml);
    }
  else if (o->file)
    {
130
      if (!strcmp (o->file, "-"))  /* read XML from stdin */
131
        {
132
          gchar buf[STDIN_BUF_SIZE];
133 134
          GString *acc = g_string_new ("");

135
          while (fgets (buf, STDIN_BUF_SIZE, stdin))
136 137 138 139 140
            {
              g_string_append (acc, buf);
            }
          script = g_string_free (acc, FALSE);
        }
141
      else if (file_is_gegl_xml (o->file))
142 143 144 145 146 147 148
        {
          g_file_get_contents (o->file, &script, NULL, &err);
          if (err != NULL)
            {
              g_warning ("Unable to read file: %s", err->message);
            }
        }
149 150
      else
        {
151
          gchar *leaked_string = g_malloc (strlen (o->file) + 5);
152
          GString *acc = g_string_new ("");
153

154 155 156 157 158
          {
            gchar *file_basename;
            gchar *tmp;
            tmp = g_strdup (o->file);
            file_basename = g_path_get_basename (tmp);
159

160 161 162
            g_string_append (acc, "<gegl><gegl:load path='");
            g_string_append (acc, file_basename);
            g_string_append (acc, "'/></gegl>");
163

164 165
            g_free (tmp);
          }
166

167 168 169 170 171 172
          script = g_string_free (acc, FALSE);

          leaked_string[0]='\0';
          strcat (leaked_string, o->file);
          strcat (leaked_string, ".xml");
        }
173 174 175
    }
  else
    {
176 177 178 179 180 181
      if (o->rest)
        {
          script = g_strdup ("<gegl></gegl>");
        }
      else
        {
182
          script = g_strdup (DEFAULT_COMPOSITION);
183
        }
184
    }
185

186
  gegl = gegl_node_new_from_xml (script, path_root);
187

188 189 190
  if (!gegl)
    {
      g_print ("Invalid graph, abort.\n");
Martin Nordholts's avatar
Martin Nordholts committed
191
      return 1;
192 193
    }

194 195 196 197
  if (o->rest)
    {
      GeglNode *proxy;
      GeglNode *iter;
198

199
      gchar **operation = o->rest;
200
      proxy = gegl_node_get_output_proxy (gegl, "output");
Øyvind Kolås's avatar
Øyvind Kolås committed
201
      iter = gegl_node_get_producer (proxy, "input", NULL);
202 203 204

      while (*operation)
        {
Sven Neumann's avatar
Sven Neumann committed
205 206
          GeglNode *new;

207
          new = gegl_node_new_child (gegl, "operation", *operation, NULL);
208 209 210 211 212 213 214 215
          if (iter)
            {
              gegl_node_link_many (iter, new, proxy, NULL);
            }
          else
            {
              gegl_node_link_many (new, proxy, NULL);
            }
216 217 218 219 220
          iter = new;
          operation++;
        }
    }

221 222
  switch (o->mode)
    {
223 224 225 226
      case GEGL_RUN_MODE_DISPLAY:
        {
          GeglNode *output = gegl_node_new_child (gegl,
                                                  "operation", "gegl:display",
227
                                                  o->file ? "window-title" : NULL, o->file,
228 229 230 231
                                                  NULL);
          gegl_node_connect_from (output, "input", gegl_node_get_output_proxy (gegl, "output"), "output");
          gegl_node_process (output);
          g_main_loop_run (g_main_loop_new (NULL, TRUE));
232
          g_object_unref (output);
233 234
        }
        break;
235
      case GEGL_RUN_MODE_XML:
236 237
        g_printf ("%s\n", gegl_node_to_xml (gegl, path_root));
        return 0;
238
        break;
239

240
      case GEGL_RUN_MODE_OUTPUT:
241
        {
242
          GeglNode *output = gegl_node_new_child (gegl,
243 244 245
                                                  "operation", "gegl:save",
                                                  "path", o->output,
                                                  NULL);
246
          gegl_node_connect_from (output, "input", gegl_node_get_output_proxy (gegl, "output"), "output");
247
          gegl_node_process (output);
248
          g_object_unref (output);
249
        }
250
        break;  
251

252 253
      case GEGL_RUN_MODE_HELP:
        break;
254

255
      default:
256
        g_warning ("Unknown GeglOption mode: %d", o->mode);
257 258
        break;
    }
259

Massimo Valentini's avatar
Massimo Valentini committed
260
  g_list_free_full (o->files, g_free);
261 262 263
  g_free (o);
  g_object_unref (gegl);
  g_free (script);
264
  g_clear_error (&err);
265
  g_free (path_root);
266
  gegl_exit ();
267 268
  return 0;
}