Permalink
Browse files

Use rsvg as an alternative to libsvg-cairo (#4715)

  • Loading branch information...
1 parent e6e2715 commit 731178b623c27966c68ff9ea6ef971c0187f3855 @tbonfort tbonfort committed Jul 26, 2013
Showing with 201 additions and 83 deletions.
  1. +22 −1 CMakeLists.txt
  2. +39 −0 cmake/FindRSVG.cmake
  3. +108 −62 mapcairo.c
  4. +6 −1 maperror.c
  5. +5 −5 maprendering.c
  6. +0 −2 mapscript/php/symbol.c
  7. +1 −0 mapserver-config.h.in
  8. +9 −9 mapsymbol.c
  9. +1 −3 mapsymbol.h
  10. +10 −0 maputil.c
View
@@ -116,7 +116,8 @@ option(WITH_GD "Choose if (old) GD support should be built in" OFF)
option(WITH_FRIBIDI "Choose if FriBidi glyph shaping support should be built in (usefull for left-to-right languages)" ON)
option(WITH_ICONV "Choose if Iconv Internationalization support should be built in" ON)
option(WITH_CAIRO "Choose if CAIRO rendering support should be built in (required for SVG and PDF output)" ON)
-option(WITH_SVGCAIRO "Choose SVG symbology support should be built in (requires cairo, libsvg, libsvg-cairo)" OFF)
+option(WITH_SVGCAIRO "Choose if SVG symbology support (via libsvgcairo) should be built in (requires cairo, libsvg, libsvg-cairo. Incompatible with librsvg)" OFF)
+option(WITH_RSVG "Choose if SVG symbology support (via librsvg) should be built in (requires cairo, librsvg. Incompatible with libsvg-cairo)" OFF)
option(WITH_MYSQL "Choose if MYSQL joining support should be built in" OFF)
option(WITH_FCGI "Choose if FastCGI support should be built in" ON)
option(WITH_GEOS "Choose if GEOS geometry operations support should be built in" ON)
@@ -494,6 +495,9 @@ if(WITH_GDAL)
endif (WITH_GDAL)
if(WITH_SVGCAIRO)
+ if(WITH_RSVG)
+ message(SEND_ERROR "WITH_SVGCAIRO cannot be enabled with WITH_RSVG")
+ endif(WITH_RSVG)
find_package(SVGCairo)
if(SVGCAIRO_FOUND)
include_directories(${SVGCAIRO_INCLUDE_DIR})
@@ -504,6 +508,22 @@ if(WITH_SVGCAIRO)
endif(SVGCAIRO_FOUND)
endif (WITH_SVGCAIRO)
+if(WITH_RSVG)
+ if(WITH_SVGCAIRO)
+ message(SEND_ERROR "WITH_RSVG cannot be enabled with WITH_CAIROSVG")
+ endif(WITH_SVGCAIRO)
+ find_package(RSVG)
+ if(RSVG_FOUND AND GOBJECT_FOUND)
+ include_directories(${RSVG_INCLUDE_DIRS})
+ ms_link_libraries( ${RSVG_LIBRARY} )
+ include_directories(${GOBJECT_INCLUDE_DIRS})
+ ms_link_libraries( ${GOBJECT_LIBRARY} )
+ set (USE_RSVG 1)
+ else(RSVG_FOUND AND GOBJECT_FOUND)
+ report_optional_not_found(RSVG)
+ endif(RSVG_FOUND AND GOBJECT_FOUND)
+endif (WITH_RSVG)
+
if(WITH_OGR)
if(GDAL_FOUND)
set (USE_OGR 1)
@@ -777,6 +797,7 @@ status_optional_component("FRIBIDI" "${USE_FRIBIDI}" "${FRIBIDI_LIBRARY}")
status_optional_component("GIF" "${USE_GIF}" "${GIF_LIBRARY}")
status_optional_component("CAIRO" "${USE_CAIRO}" "${CAIRO_LIBRARY}")
status_optional_component("SVGCAIRO" "${USE_SVG_CAIRO}" "${SVGCAIRO_LIBRARY}")
+status_optional_component("RSVG" "${USE_RSVG}" "${RSVG_LIBRARY}")
status_optional_component("CURL" "${USE_CURL}" "${CURL_LIBRARY}")
status_optional_component("PROJ" "${USE_PROJ}" "${PROJ_LIBRARY}")
status_optional_component("LIBXML2" "${USE_LIBXML2}" "${LIBXML2_LIBRARY}")
View
@@ -0,0 +1,39 @@
+# - Find Rsvg
+# Find the Rsvg includes and libraries
+#
+# Following variables are provided:
+# RSVG_FOUND
+# True if Rsvg has been found
+# RSVG_INCLUDE_DIRS
+# The include directories of Rsvg
+# RSVG_LIBRARIES
+# Rsvg library list
+
+find_package(PkgConfig)
+pkg_check_modules(RSVG QUIET librsvg-2.0>=2.32.0)
+pkg_check_modules(GOBJECT QUIET gobject-2.0>=2.32.0)
+
+find_path(RSVG_INCLUDE_DIR
+ NAMES rsvg-cairo.h
+ HINTS ${RSVG_INCLUDE_DIRS}
+ PATH_SUFFIXES librsvg
+)
+
+find_library(RSVG_LIBRARY
+ NAME rsvg-2
+ HINTS ${RSVG_LIBRARY_DIRS}
+)
+
+find_path(GOBJECT_INCLUDE_DIR
+ NAMES glib-object.h
+ HINTS ${GOBJECT_INCLUDE_DIRS}
+)
+
+find_library(GOBJECT_LIBRARY
+ NAME gobject-2.0
+ HINTS ${GOBJECT_LIBRARY_DIRS}
+)
+
+find_package_handle_standard_args(RSVG DEFAULT_MSG RSVG_LIBRARY RSVG_INCLUDE_DIR)
+find_package_handle_standard_args(GOBJECT DEFAULT_MSG GOBJECT_LIBRARY GOBJECT_INCLUDE_DIR)
+mark_as_advanced(RSVG_LIBRARY RSVG_INCLUDE_DIR RSVG_LIBRARIES RSVG_INCLUDE_DIRS GOBJECT_LIBRARY GOBJECT_INCLUDE_DIR)
View
@@ -41,6 +41,17 @@
#ifdef USE_SVG_CAIRO
#include <svg-cairo.h>
+#else
+#ifdef USE_RSVG
+ #include <librsvg/rsvg.h>
+ #ifndef LIBRSVG_CHECK_VERSION
+ #include <librsvg/librsvg-features.h>
+ #endif
+ #if !LIBRSVG_CHECK_VERSION(2,36,2)
+ #include <librsvg/rsvg-cairo.h>
+ #endif
+ #include <glib-object.h>
+#endif
#endif
#ifdef USE_GDAL
@@ -346,23 +357,26 @@ int renderVectorSymbolCairo(imageObj *img, double x, double y, symbolObj *symbol
return MS_SUCCESS;
}
-#ifdef USE_SVG_CAIRO
+#if defined(USE_SVG_CAIRO) || defined(USE_RSVG)
struct svg_symbol_cache {
- rasterBufferObj pixmap_buffer;
+ rasterBufferObj *pixmap_buffer;
+#ifdef USE_RSVG
+ RsvgHandle *svgc;
+#else
svg_cairo_t *svgc;
+#endif
double scale,rotation;
} ;
#endif
int renderSVGSymbolCairo(imageObj *img, double x, double y, symbolObj *symbol,
symbolStyleObj *style)
{
-#ifdef USE_SVG_CAIRO
+#if defined(USE_SVG_CAIRO) || defined(USE_RSVG)
+ struct svg_symbol_cache *cache;
cairo_renderer *r = CAIRO_RENDERER(img);
- //double ox=symbol->sizex*0.5,oy=symbol->sizey*0.5;
- svg_cairo_status_t status;
- struct svg_symbol_cache *cache;
+
msPreloadSVGSymbol(symbol);
assert(symbol->renderer_cache);
@@ -378,12 +392,23 @@ int renderSVGSymbolCairo(imageObj *img, double x, double y, symbolObj *symbol,
} else
cairo_translate (r->cr, -(int)(symbol->sizex/2), -(int)(symbol->sizey/2));
- status = svg_cairo_render(cache->svgc, r->cr);
+#ifdef USE_SVG_CAIRO
+ {
+ svg_cairo_status_t status;
+ status = svg_cairo_render(cache->svgc, r->cr);
+ if(status != SVG_CAIRO_STATUS_SUCCESS) {
+ cairo_restore(r->cr);
+ return MS_FAILURE;
+ }
+ }
+#else
+ rsvg_handle_render_cairo(cache->svgc, r->cr);
+#endif
+
cairo_restore(r->cr);
- if(status == SVG_CAIRO_STATUS_SUCCESS)
- return MS_SUCCESS;
- else
- return MS_FAILURE;
+
+ return MS_SUCCESS;
+
#else
msSetError(MS_MISCERR, "SVG Symbols requested but is not built with libsvgcairo",
@@ -1042,6 +1067,29 @@ int mergeRasterBufferCairo(imageObj *img, rasterBufferObj *rb, double opacity,
return MS_SUCCESS;
}
+
+void freeSVGCache(symbolObj *s) {
+#if defined(USE_SVG_CAIRO) || defined(USE_RSVG)
+ struct svg_symbol_cache *cache = s->renderer_cache;
+ assert(cache->svgc);
+#ifdef USE_SVG_CAIRO
+ svg_cairo_destroy(cache->svgc);
+#else
+ rsvg_handle_close(cache->svgc, NULL);
+ #if LIBRSVG_CHECK_VERSION(2,36,2)
+ g_object_unref(cache->svgc);
+ #else
+ rsvg_handle_free(cache->svgc);
+ #endif
+#endif
+ if(cache->pixmap_buffer) {
+ msFreeRasterBuffer(cache->pixmap_buffer);
+ free(cache->pixmap_buffer);
+ }
+ msFree(s->renderer_cache);
+#endif
+}
+
int freeSymbolCairo(symbolObj *s)
{
if(!s->renderer_cache)
@@ -1053,15 +1101,9 @@ int freeSymbolCairo(symbolObj *s)
case MS_SYMBOL_PIXMAP:
cairo_surface_destroy(s->renderer_cache);
break;
- case MS_SYMBOL_SVG: {
-#ifdef USE_SVG_CAIRO
- struct svg_symbol_cache *cache = s->renderer_cache;
- assert(cache->svgc);
- svg_cairo_destroy(cache->svgc);
- msFree(s->renderer_cache);
-#endif
- }
- break;
+ case MS_SYMBOL_SVG:
+ freeSVGCache(s);
+ break;
}
s->renderer_cache=NULL;
return MS_SUCCESS;
@@ -1085,58 +1127,54 @@ int initializeRasterBufferCairo(rasterBufferObj *rb, int width, int height, int
int msPreloadSVGSymbol(symbolObj *symbol)
{
-#ifdef USE_SVG_CAIRO
- int status;
- unsigned int svg_width, svg_height;
+#if defined(USE_SVG_CAIRO) || defined(USE_RSVG)
struct svg_symbol_cache *cache;
if(!symbol->renderer_cache) {
cache = msSmallCalloc(1,sizeof(struct svg_symbol_cache));
+ symbol->renderer_free_func = &freeSVGCache;
} else {
cache = symbol->renderer_cache;
}
if(cache->svgc)
return MS_SUCCESS;
- if (!symbol->svg_text) {
- FILE *stream;
- long int file_len;
-
- if ((stream = fopen(symbol->full_pixmap_path, "rb")) == NULL) {
- msSetError(MS_IOERR, "Could not open svg file %s", "msPreloadSVGSymbol()",symbol->full_pixmap_path);
- return (MS_FAILURE);
+#ifdef USE_SVG_CAIRO
+ {
+ unsigned int svg_width, svg_height;
+ int status;
+ status = svg_cairo_create(&cache->svgc);
+ if (status) {
+ msSetError(MS_RENDERERERR, "problem creating cairo svg", "msPreloadSVGSymbol()");
+ return MS_FAILURE;
}
- fseek(stream, 0, SEEK_END);
- file_len = ftell(stream);
- rewind(stream);
- symbol->svg_text = (char*) msSmallMalloc(sizeof (char) * file_len);
- if (1 != fread(symbol->svg_text, file_len, 1, stream)) {
- msSetError(MS_IOERR, "failed to read %lu bytes from svg file %s", "loadSymbol()", file_len, symbol->full_pixmap_path);
- free(symbol->svg_text);
+ status = svg_cairo_parse(cache->svgc, symbol->full_pixmap_path);
+ if (status) {
+ msSetError(MS_RENDERERERR, "problem parsing svg symbol", "msPreloadSVGSymbol()");
+ return MS_FAILURE;
+ }
+ svg_cairo_get_size (cache->svgc, &svg_width, &svg_height);
+ if (svg_width == 0 || svg_height == 0) {
+ msSetError(MS_RENDERERERR, "problem parsing svg symbol", "msPreloadSVGSymbol()");
return MS_FAILURE;
}
- symbol->svg_text[file_len - 1] = '\0';
- fclose(stream);
- }
- status = svg_cairo_create(&cache->svgc);
- if (status) {
- msSetError(MS_RENDERERERR, "problem creating cairo svg", "msPreloadSVGSymbol()");
- return MS_FAILURE;
- }
- status = svg_cairo_parse_buffer(cache->svgc, symbol->svg_text, strlen(symbol->svg_text));
- if (status) {
- msSetError(MS_RENDERERERR, "problem parsing svg symbol", "msPreloadSVGSymbol()");
- return MS_FAILURE;
+ symbol->sizex = svg_width;
+ symbol->sizey = svg_height;
}
- svg_cairo_get_size (cache->svgc, &svg_width, &svg_height);
- if (svg_width == 0 || svg_height == 0) {
- msSetError(MS_RENDERERERR, "problem parsing svg symbol", "msPreloadSVGSymbol()");
- return MS_FAILURE;
+#else
+ {
+ RsvgDimensionData dim;
+ cache->svgc = rsvg_handle_new_from_file(symbol->full_pixmap_path,NULL);
+ if(!cache->svgc) {
+ msSetError(MS_RENDERERERR,"failed to load svg file %s", "msPreloadSVGSymbol()", symbol->full_pixmap_path);
+ }
+ rsvg_handle_get_dimensions_sub (cache->svgc, &dim, NULL);
+ symbol->sizex = dim.width;
+ symbol->sizey = dim.height;
}
+#endif
- symbol->sizex = svg_width;
- symbol->sizey = svg_height;
symbol->renderer_cache = cache;
return MS_SUCCESS;
@@ -1153,7 +1191,7 @@ int msPreloadSVGSymbol(symbolObj *symbol)
int msRenderRasterizedSVGSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style)
{
-#ifdef USE_SVG_CAIRO
+#if defined(USE_SVG_CAIRO) || defined(USE_RSVG)
struct svg_symbol_cache *svg_cache;
symbolStyleObj pixstyle;
symbolObj pixsymbol;
@@ -1163,18 +1201,22 @@ int msRenderRasterizedSVGSymbol(imageObj *img, double x, double y, symbolObj *sy
return MS_FAILURE;
}
- //already rendered at the right size and scale? return
if(MS_SUCCESS != msPreloadSVGSymbol(symbol))
return MS_FAILURE;
svg_cache = (struct svg_symbol_cache*) symbol->renderer_cache;
+ //already rendered at the right size and scale? return
if(svg_cache->scale != style->scale || svg_cache->rotation != style->rotation) {
cairo_t *cr;
cairo_surface_t *surface;
unsigned char *pb;
int width, height, surface_w, surface_h;
/* need to recompute the pixmap */
- msFreeRasterBuffer(&svg_cache->pixmap_buffer);
+ if(svg_cache->pixmap_buffer) {
+ msFreeRasterBuffer(svg_cache->pixmap_buffer);
+ } else {
+ svg_cache->pixmap_buffer = msSmallCalloc(1,sizeof(rasterBufferObj));
+ }
//increase pixmap size to accomodate scaling/rotation
if (style->scale != 1.0) {
@@ -1200,26 +1242,30 @@ int msRenderRasterizedSVGSymbol(imageObj *img, double x, double y, symbolObj *sy
if (style->scale != 1.0) {
cairo_scale(cr, style->scale, style->scale);
}
+#ifdef USE_SVG_CAIRO
if(svg_cairo_render(svg_cache->svgc, cr) != SVG_CAIRO_STATUS_SUCCESS) {
return MS_FAILURE;
}
+#else
+ rsvg_handle_render_cairo(svg_cache->svgc, cr);
+#endif
pb = cairo_image_surface_get_data(surface);
//set up raster
- initializeRasterBufferCairo(&svg_cache->pixmap_buffer, surface_w, surface_h, 0);
- memcpy(svg_cache->pixmap_buffer.data.rgba.pixels, pb, surface_w * surface_h * 4 * sizeof (unsigned char));
+ initializeRasterBufferCairo(svg_cache->pixmap_buffer, surface_w, surface_h, 0);
+ memcpy(svg_cache->pixmap_buffer->data.rgba.pixels, pb, surface_w * surface_h * 4 * sizeof (unsigned char));
svg_cache->scale = style->scale;
svg_cache->rotation = style->rotation;
cairo_destroy(cr);
cairo_surface_destroy(surface);
}
- assert(svg_cache->pixmap_buffer.height && svg_cache->pixmap_buffer.width);
+ assert(svg_cache->pixmap_buffer->height && svg_cache->pixmap_buffer->width);
pixstyle = *style;
pixstyle.rotation = 0.0;
pixstyle.scale = 1.0;
- pixsymbol.pixmap_buffer = &svg_cache->pixmap_buffer;
+ pixsymbol.pixmap_buffer = svg_cache->pixmap_buffer;
pixsymbol.type = MS_SYMBOL_PIXMAP;
MS_IMAGE_RENDERER(img)->renderPixmapSymbol(img,x,y,&pixsymbol,&pixstyle);
View
@@ -529,8 +529,13 @@ char *msGetVersion()
#ifdef USE_CAIRO
strcat(version, " SUPPORTS=CAIRO");
#endif
-#ifdef USE_SVG_CAIRO
+#if defined(USE_SVG_CAIRO) || defined(USE_RSVG)
strcat(version, " SUPPORTS=SVG_SYMBOLS");
+ #ifdef USE_SVG_CAIRO
+ strcat(version, " SUPPORTS=SVGCAIRO");
+ #else
+ strcat(version, " SUPPORTS=RSVG");
+ #endif
#endif
#ifdef USE_OGL
strcat(version, " SUPPORTS=OPENGL");
Oops, something went wrong.

0 comments on commit 731178b

Please sign in to comment.