Logo Search packages:      
Sourcecode: beryl-plugins version File versions

svg.c

/*
 * Copyright © 2006 Novell, Inc.
 *
 * 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 the Free Software Foundation; either version 2
 * of the License, or (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
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 * Author: David Reveman <davidr@novell.com>
 */

#include <stdlib.h>
#include <string.h>

#include <librsvg/rsvg.h>
#include <librsvg/rsvg-cairo.h>

#include <beryl.h>

static int displayPrivateIndex;

typedef struct _SvgDisplay
{
      FileToImageProc fileToImage;
} SvgDisplay;

#define GET_SVG_DISPLAY(d)                          \
    ((SvgDisplay *) (d)->privates[displayPrivateIndex].ptr)

#define SVG_DISPLAY(d)               \
    SvgDisplay *sd = GET_SVG_DISPLAY (d)


static Bool
readSvgFileToImage(char *file, int *width, int *height, void **data)
{
      cairo_surface_t *surface;
      FILE *fp;
      GError *error = NULL;
      RsvgHandle *svgHandle;
      RsvgDimensionData svgDimension;

      fp = fopen(file, "r");
      if (!fp)
            return FALSE;

      fclose(fp);

      svgHandle = rsvg_handle_new_from_file(file, &error);
      if (!svgHandle)
            return FALSE;

      rsvg_handle_get_dimensions(svgHandle, &svgDimension);

      *width = svgDimension.width;
      *height = svgDimension.height;

      *data = malloc(svgDimension.width * svgDimension.height * 4);
      if (!*data)
      {
            rsvg_handle_free(svgHandle);
            return FALSE;
      }

      surface = cairo_image_surface_create_for_data(*data,
                                                                          CAIRO_FORMAT_ARGB32,
                                                                          svgDimension.width,
                                                                          svgDimension.height,
                                                                          svgDimension.width * 4);
      if (surface)
      {
            cairo_t *cr;

            cr = cairo_create(surface);

            cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
            cairo_paint(cr);
            cairo_set_operator(cr, CAIRO_OPERATOR_OVER);

            rsvg_handle_render_cairo(svgHandle, cr);

            cairo_destroy(cr);
            cairo_surface_destroy(surface);
      }

      rsvg_handle_free(svgHandle);

      return TRUE;
}

static char *svgExtension(const char *name)
{

      if (strlen(name) > 4)
      {
            if (strcasecmp(name + (strlen(name) - 4), ".svg") == 0)
                  return "";
      }

      return ".svg";
}

static Bool
svgFileToImage(CompDisplay * d,
                     const char *path,
                     const char *name,
                     int *width, int *height, int *stride, void **data)
{
      Bool status = FALSE;
      char *extension = svgExtension(name);
      char *file;
      int len;

      SVG_DISPLAY(d);

      len = (path ? strlen(path) : 0) + strlen(name) + strlen(extension) + 2;

      file = malloc(len);
      if (file)
      {
            if (path)
                  sprintf(file, "%s/%s%s", path, name, extension);
            else
                  sprintf(file, "%s%s", name, extension);

            status = readSvgFileToImage(file, width, height, data);

            free(file);

            if (status)
            {
                  *stride = *width * 4;
                  return TRUE;
            }
      }

      UNWRAP(sd, d, fileToImage);
      status = (*d->fileToImage) (d, path, name, width, height, stride, data);
      WRAP(sd, d, fileToImage, svgFileToImage);

      return status;
}

static Bool svgInitDisplay(CompPlugin * p, CompDisplay * d)
{
      SvgDisplay *sd;
      CompScreen *s;

      sd = malloc(sizeof(SvgDisplay));
      if (!sd)
            return FALSE;

      WRAP(sd, d, fileToImage, svgFileToImage);

      d->privates[displayPrivateIndex].ptr = sd;

      for (s = d->screens; s; s = s->next)
            updateDefaultIcon(s);

      return TRUE;
}

static void svgFiniDisplay(CompPlugin * p, CompDisplay * d)
{
      CompScreen *s;

      SVG_DISPLAY(d);

      UNWRAP(sd, d, fileToImage);

      for (s = d->screens; s; s = s->next)
            updateDefaultIcon(s);

      free(sd);
}

static Bool svgInit(CompPlugin * p)
{
      displayPrivateIndex = allocateDisplayPrivateIndex();
      if (displayPrivateIndex < 0)
            return FALSE;

      return TRUE;
}

static void svgFini(CompPlugin * p)
{
      if (displayPrivateIndex >= 0)
            freeDisplayPrivateIndex(displayPrivateIndex);
}

CompPluginFeature svgFeatures[] = {
      {"imageext:svg"}
      ,
      {"imagemime:image/svg+xml"}
      ,
      {"imagemime:image/svg-xml"}
      ,
};

CompPluginVTable svgVTable = {
      "svg",
      N_("Svg"),
      N_("Svg image loader"),
      svgInit,
      svgFini,
      svgInitDisplay,
      svgFiniDisplay,
      0,                                        /* InitScreen */
      0,                                        /* FiniScreen */
      0,                                        /* InitWindow */
      0,                                        /* FiniWindow */
      0,                                        /* GetDisplayOptions */
      0,                                        /* SetDisplayOption */
      0,                                        /* GetScreenOptions */
      0,                                        /* SetScreenOption */
      0,                                        /* Deps */
      0,                                        /* nDeps */
      svgFeatures,                        /* Features */
      sizeof(svgFeatures) / sizeof(svgFeatures[0]),   /* nFeatures */
      BERYL_ABI_INFO,
      "beryl-plugins",
      "imageformat",
      0,
      0,
      True,
};

CompPluginVTable *getCompPluginInfo(void)
{
      return &svgVTable;
}

Generated by  Doxygen 1.6.0   Back to index