/*
* 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;
}
syntax highlighted by Code2HTML, v. 0.9.1