Permalink
Browse files

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

  • Loading branch information...
tbonfort committed Jul 26, 2013
1 parent e6e2715 commit 731178b623c27966c68ff9ea6ef971c0187f3855
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.