Blame operations/external/svg-load.c

Packit bc1512
/* This file is an image processing operation for GEGL
Packit bc1512
 *
Packit bc1512
 * GEGL is free software; you can redistribute it and/or
Packit bc1512
 * modify it under the terms of the GNU Lesser General Public
Packit bc1512
 * License as published by the Free Software Foundation; either
Packit bc1512
 * version 3 of the License, or (at your option) any later version.
Packit bc1512
 *
Packit bc1512
 * GEGL is distributed in the hope that it will be useful,
Packit bc1512
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bc1512
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit bc1512
 * Lesser General Public License for more details.
Packit bc1512
 *
Packit bc1512
 * You should have received a copy of the GNU Lesser General Public
Packit bc1512
 * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
Packit bc1512
 *
Packit bc1512
 * Copyright 2006 Kevin Cozens <kcozens@cvs.gimp.org>
Packit bc1512
 */
Packit bc1512
Packit bc1512
#include "config.h"
Packit bc1512
#include <glib/gi18n-lib.h>
Packit bc1512
Packit bc1512
Packit bc1512
#ifdef GEGL_CHANT_PROPERTIES
Packit bc1512
Packit bc1512
gegl_chant_file_path (path, _("File"), "",
Packit bc1512
                 _("Path to SVG file to load"))
Packit bc1512
gegl_chant_int (width,  _("Width"),  1, G_MAXINT, 100,
Packit bc1512
                _("Width for rendered image"))
Packit bc1512
gegl_chant_int (height, _("Height"), 1, G_MAXINT, 100,
Packit bc1512
                _("Height for rendered image"))
Packit bc1512
Packit bc1512
#else
Packit bc1512
Packit bc1512
#define GEGL_CHANT_TYPE_SOURCE
Packit bc1512
#define GEGL_CHANT_C_FILE       "svg-load.c"
Packit bc1512
Packit bc1512
#include "gegl-chant.h"
Packit bc1512
#include <cairo.h>
Packit bc1512
#include <librsvg/rsvg.h>
Packit bc1512
#include <librsvg/rsvg-cairo.h>
Packit bc1512
#include <gdk-pixbuf/gdk-pixbuf.h>
Packit bc1512
#include <gdk-pixbuf/gdk-pixdata.h>
Packit bc1512
Packit bc1512
#define SVG_DEFAULT_RESOLUTION  90.0
Packit bc1512
#define SVG_DEFAULT_SIZE        500
Packit bc1512
Packit bc1512
typedef struct
Packit bc1512
{
Packit bc1512
  gdouble    resolution;
Packit bc1512
  gint       width;
Packit bc1512
  gint       height;
Packit bc1512
} SvgLoadVals;
Packit bc1512
Packit bc1512
static void prepare (GeglOperation *operation)
Packit bc1512
{
Packit bc1512
  gegl_operation_set_format (operation, "output", babl_format ("R'G'B'A u8"));
Packit bc1512
}
Packit bc1512
Packit bc1512
static gint
Packit bc1512
gegl_buffer_import_svg (GeglBuffer  *gegl_buffer,
Packit bc1512
                        const gchar *path,
Packit bc1512
                        gint         width,
Packit bc1512
                        gint         height,
Packit bc1512
                        gint         dest_x,
Packit bc1512
                        gint         dest_y,
Packit bc1512
                        gint        *ret_width,
Packit bc1512
                        gint        *ret_height)
Packit bc1512
{
Packit bc1512
    cairo_surface_t *surface;
Packit bc1512
    cairo_t    *cr;
Packit bc1512
    GdkPixbuf  *pixbuf;
Packit bc1512
    GError     *pError = NULL;
Packit bc1512
Packit bc1512
    surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, *ret_width, *ret_height);
Packit bc1512
    cr = cairo_create (surface);
Packit bc1512
Packit bc1512
    rsvg_init();
Packit bc1512
Packit bc1512
/*
Packit bc1512
FIXME: The routine 'rsvg_pixbuf_from_file_at_size' is deprecated. Set up a
Packit bc1512
cairo matrix and use rsvg_handle_new_from_file() + rsvg_handle_render_cairo()
Packit bc1512
instead.
Packit bc1512
*/
Packit bc1512
    pixbuf = rsvg_pixbuf_from_file_at_size (path,
Packit bc1512
                                            width,
Packit bc1512
                                            height,
Packit bc1512
                                            &pError);
Packit bc1512
    if (pixbuf)
Packit bc1512
    {
Packit bc1512
      guchar        *pixeldata;
Packit bc1512
      GeglRectangle  rect;
Packit bc1512
Packit bc1512
      rect.x = dest_x;
Packit bc1512
      rect.y = dest_y;
Packit bc1512
      rect.width = width;
Packit bc1512
      rect.height = height;
Packit bc1512
Packit bc1512
      pixeldata = gdk_pixbuf_get_pixels (pixbuf);
Packit bc1512
      gegl_buffer_set (gegl_buffer, &rect, 0, babl_format ("R'G'B'A u8"), pixeldata, GEGL_AUTO_ROWSTRIDE);
Packit bc1512
    }
Packit bc1512
Packit bc1512
    rsvg_term();
Packit bc1512
Packit bc1512
    cairo_destroy (cr);
Packit bc1512
    cairo_surface_destroy (surface);
Packit bc1512
Packit bc1512
    return 0;
Packit bc1512
}
Packit bc1512
Packit bc1512
/*  This is the callback used from load_rsvg_size().  */
Packit bc1512
static void
Packit bc1512
load_get_size_callback (gint     *width,
Packit bc1512
                        gint     *height,
Packit bc1512
                        gpointer  data)
Packit bc1512
{
Packit bc1512
  SvgLoadVals *vals = data;
Packit bc1512
Packit bc1512
  *width  = vals->width;
Packit bc1512
  *height = vals->height;
Packit bc1512
Packit bc1512
  if (*width < 1 || *height < 1)
Packit bc1512
    {
Packit bc1512
      *width  = SVG_DEFAULT_SIZE;
Packit bc1512
      *height = SVG_DEFAULT_SIZE;
Packit bc1512
    }
Packit bc1512
Packit bc1512
  /*  cancel loading  */
Packit bc1512
  vals->resolution = 0.0;
Packit bc1512
}
Packit bc1512
Packit bc1512
static gint
Packit bc1512
query_svg (const gchar *path,
Packit bc1512
           gint        *width,
Packit bc1512
           gint        *height)
Packit bc1512
{
Packit bc1512
  RsvgHandle       *handle;
Packit bc1512
  RsvgDimensionData dimension_data;
Packit bc1512
  GError           *pError = NULL;
Packit bc1512
  SvgLoadVals       vals;
Packit bc1512
Packit bc1512
  rsvg_init ();
Packit bc1512
  handle = rsvg_handle_new_from_file (path, &pError);
Packit bc1512
  if (handle == NULL)
Packit bc1512
      return FALSE;
Packit bc1512
Packit bc1512
  vals.resolution = SVG_DEFAULT_RESOLUTION;
Packit bc1512
  vals.width  = *width;
Packit bc1512
  vals.height = *height;
Packit bc1512
Packit bc1512
  rsvg_handle_set_size_callback (handle, load_get_size_callback, &vals, NULL);
Packit bc1512
Packit bc1512
  rsvg_handle_get_dimensions (handle, &dimension_data);
Packit bc1512
Packit bc1512
  rsvg_handle_free (handle);
Packit bc1512
  rsvg_term ();
Packit bc1512
Packit bc1512
  *width  = dimension_data.width;
Packit bc1512
  *height = dimension_data.height;
Packit bc1512
Packit bc1512
  return TRUE;
Packit bc1512
}
Packit bc1512
Packit bc1512
static GeglRectangle
Packit bc1512
get_bounding_box (GeglOperation *operation)
Packit bc1512
{
Packit bc1512
  GeglChantO   *o = GEGL_CHANT_PROPERTIES (operation);
Packit bc1512
  GeglRectangle result = {0,0,0,0};
Packit bc1512
  /*GeglOperationSource *source = GEGL_OPERATION_SOURCE(operation);*/
Packit bc1512
  gint width, height;
Packit bc1512
  gint status;
Packit bc1512
Packit bc1512
  /*if (!strcmp (o->path, "-"))
Packit bc1512
    {
Packit bc1512
      process (operation);
Packit bc1512
      width = source->output->width;
Packit bc1512
      height = source->output->height;
Packit bc1512
    }
Packit bc1512
  else*/
Packit bc1512
    {
Packit bc1512
      width  = o->width;
Packit bc1512
      height = o->height;
Packit bc1512
      status = query_svg (o->path, &width, &height);
Packit bc1512
      if (status == FALSE)
Packit bc1512
        {
Packit bc1512
          g_warning ("get defined region of %s failed", o->path);
Packit bc1512
          width = 0;
Packit bc1512
          height = 0;
Packit bc1512
        }
Packit bc1512
    }
Packit bc1512
Packit bc1512
  result.width  = width;
Packit bc1512
  result.height  = height;
Packit bc1512
  return result;
Packit bc1512
}
Packit bc1512
Packit bc1512
static gboolean
Packit bc1512
process (GeglOperation       *operation,
Packit bc1512
         GeglBuffer          *output,
Packit bc1512
         const GeglRectangle *result_foo,
Packit bc1512
         gint                 level)
Packit bc1512
{
Packit bc1512
  GeglChantO *o = GEGL_CHANT_PROPERTIES (operation);
Packit bc1512
  gint        result;
Packit bc1512
  gint        width, height;
Packit bc1512
Packit bc1512
    width  = o->width;
Packit bc1512
    height = o->height;
Packit bc1512
    result = query_svg (o->path, &width, &height);
Packit bc1512
    if (result == FALSE)
Packit bc1512
      {
Packit bc1512
        g_warning ("%s failed to open file %s for reading.",
Packit bc1512
        G_OBJECT_TYPE_NAME (operation), o->path);
Packit bc1512
        return FALSE;
Packit bc1512
      }
Packit bc1512
Packit bc1512
  result = gegl_buffer_import_svg (output, o->path,
Packit bc1512
                                   width, height, 0, 0, &width, &height);
Packit bc1512
  if (result)
Packit bc1512
    {
Packit bc1512
      g_warning ("%s failed to open file %s for reading.",
Packit bc1512
        G_OBJECT_TYPE_NAME (operation), o->path);
Packit bc1512
      return  FALSE;
Packit bc1512
    }
Packit bc1512
Packit bc1512
  return  TRUE;
Packit bc1512
}
Packit bc1512
Packit bc1512
Packit bc1512
static void
Packit bc1512
gegl_chant_class_init (GeglChantClass *klass)
Packit bc1512
{
Packit bc1512
  GeglOperationClass       *operation_class;
Packit bc1512
  GeglOperationSourceClass *source_class;
Packit bc1512
Packit bc1512
  operation_class = GEGL_OPERATION_CLASS (klass);
Packit bc1512
  source_class    = GEGL_OPERATION_SOURCE_CLASS (klass);
Packit bc1512
Packit bc1512
  source_class->process = process;
Packit bc1512
  operation_class->prepare = prepare;
Packit bc1512
  operation_class->get_bounding_box = get_bounding_box;
Packit bc1512
Packit bc1512
  gegl_operation_class_set_keys (operation_class,
Packit bc1512
    "name"        , "gegl:svg-load",
Packit bc1512
    "categories"  , "input",   /* not hidden because it has extra API */
Packit bc1512
    "description" , _("Load an SVG file using librsvg"),
Packit bc1512
    NULL);
Packit bc1512
Packit bc1512
/*  static gboolean done=FALSE;
Packit bc1512
    if (done)
Packit bc1512
      return; */
Packit bc1512
  gegl_extension_handler_register (".svg", "gegl:svg-load");
Packit bc1512
  gegl_extension_handler_register (".svgz", "gegl:svg-load");
Packit bc1512
/*  done = TRUE; */
Packit bc1512
}
Packit bc1512
Packit bc1512
#endif