/* * 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 */ #include #include #include #include #include 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; }