int msRenderRasterizedSVGSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { #if defined(USE_SVG_CAIRO) || defined(USE_RSVG) struct svg_symbol_cache *svg_cache; symbolStyleObj pixstyle; symbolObj pixsymbol; int status; 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 */ 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) { width = surface_w = (symbol->sizex * style->scale + 0.5); height = surface_h = (symbol->sizey * style->scale + 0.5); } else { width = surface_w = symbol->sizex; height = surface_h = symbol->sizey; } if (style->rotation != 0) { surface_w = surface_h = MS_NINT(MS_MAX(height, width) * 1.415); } surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, surface_w, surface_h); cr = cairo_create(surface); if (style->rotation != 0) { cairo_translate(cr, surface_w / 2, surface_h / 2); cairo_rotate(cr, -style->rotation); cairo_translate(cr, -width / 2, -height / 2); } 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)); 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); pixstyle = *style; pixstyle.rotation = 0.0; pixstyle.scale = 1.0; pixsymbol.pixmap_buffer = svg_cache->pixmap_buffer; pixsymbol.type = MS_SYMBOL_PIXMAP; status = MS_IMAGE_RENDERER(img)->renderPixmapSymbol(img,x,y,&pixsymbol,&pixstyle); MS_IMAGE_RENDERER(img)->freeSymbol(&pixsymbol); return status; #else msSetError(MS_MISCERR, "SVG Symbols requested but MapServer is not built with libsvgcairo", "renderSVGSymbolCairo()"); return MS_FAILURE; #endif }
int msRenderSVGToPixmap(symbolObj *symbol, symbolStyleObj *style) { #ifdef USE_SVG_CAIRO unsigned int svg_width, svg_height; svg_cairo_status_t status; cairo_t *cr; svg_cairo_t *svgc; cairo_surface_t *surface; unsigned char *pb; rasterBufferObj *rb; //rendering_buffer *rc; int width, height, surface_w, surface_h,row; double scale; //already rendered at the right size and scale? return if (symbol->pixmap_buffer) { if (style->scale == symbol->pixmap_buffer->scale && style->rotation == symbol->pixmap_buffer->rotation) { return MS_SUCCESS; } else { if(symbol->renderer!=NULL) symbol->renderer->freeSymbol(symbol); msFreeRasterBuffer(symbol->pixmap_buffer); } } if (!symbol->svg_cairo_surface ) msPreloadSVGSymbol(symbol); if (!symbol->svg_cairo_surface) return MS_FAILURE; //set up raster svgc =symbol->svg_cairo_surface; svg_cairo_get_size (svgc, &svg_width, &svg_height); width = surface_w = svg_width; height = surface_h = svg_height; //scale such that the SVG is rendered at the desired size in pixels scale = style->scale; /*MS_MIN(style->scale / (double) svg_width, style->scale / (double) svg_height);*/ //increase pixmap size to accomodate scaling/rotation if (scale != 1.0 && style->scale != 1.0) { width = surface_w = (svg_width * scale + 0.5); height = surface_h = (svg_height * scale + 0.5); } if (style->rotation != 0) { surface_w = MS_NINT(width * 1.415); surface_h = MS_NINT(height * 1.415); } surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, surface_w, surface_h); cr = cairo_create(surface); if (style->rotation != 0) { cairo_translate (cr, surface_w/2, surface_h/2); cairo_rotate(cr, -style->rotation); cairo_translate (cr, -width/2, -height/2); } if (style->scale != 1.0) { cairo_scale(cr,scale,scale); } status = svg_cairo_render(svgc, cr); pb = cairo_image_surface_get_data(surface); //set up raster symbol->pixmap_buffer = (rasterBufferObj*)calloc(1,sizeof(rasterBufferObj)); MS_CHECK_ALLOC(symbol->pixmap_buffer, sizeof(rasterBufferObj), MS_FAILURE); initializeRasterBufferCairo(symbol->pixmap_buffer, surface_w, surface_h, 0); rb = symbol->pixmap_buffer; memcpy(rb->data.rgba.pixels, pb, surface_w * surface_h * 4 * sizeof(unsigned char)); /* unpremultiply the data */ for(row=0; row<rb->height; row++) { int col; unsigned char *a,*r,*g,*b; r=rb->data.rgba.r+row*rb->data.rgba.row_step; g=rb->data.rgba.g+row*rb->data.rgba.row_step; b=rb->data.rgba.b+row*rb->data.rgba.row_step; a=rb->data.rgba.a+row*rb->data.rgba.row_step; for(col=0; col<rb->width; col++) { if(*a && *a < 255) { double da = *a/255.0; *r/=da; *g/=da; *b/=da; } a+=rb->data.rgba.pixel_step; r+=rb->data.rgba.pixel_step; g+=rb->data.rgba.pixel_step; b+=rb->data.rgba.pixel_step; } } rb->scale = style->scale; rb->rotation = style->rotation; cairo_destroy(cr); cairo_surface_destroy(surface); return MS_SUCCESS; #else msSetError(MS_MISCERR, "SVG Symbols requested but MapServer is not built with libsvgcairo", "renderSVGSymbolCairo()"); return MS_FAILURE; #endif }