diff --git a/mapagg.cpp b/mapagg.cpp index 0deca64272..114f115330 100644 --- a/mapagg.cpp +++ b/mapagg.cpp @@ -78,6 +78,7 @@ typedef mapserver::rgba8 color_type; typedef mapserver::pixel32_type pixel_type; typedef mapserver::blender_rgba_pre blender_pre; + typedef mapserver::pixfmt_alpha_blend_rgba pixel_format; typedef mapserver::rendering_buffer rendering_buffer; typedef mapserver::renderer_base renderer_base; @@ -565,39 +566,10 @@ int agg2RenderVectorSymbol(imageObj *img, double x, double y, int agg2RenderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style) { AGG2Renderer *r = AGG_RENDERER(img); - pixel_format pf; - rendering_buffer b; rasterBufferObj *pixmap = symbol->pixmap_buffer; assert(pixmap->type == MS_BUFFER_BYTE_RGBA); - if(!symbol->renderer_cache) { - band_type *data = (band_type*)msSmallMalloc(pixmap->width*pixmap->height*4*sizeof(band_type)); - for(unsigned int row=0; rowheight;row++) { - unsigned char *a = pixmap->data.rgba.a + row * pixmap->data.rgba.row_step; - unsigned char *r = pixmap->data.rgba.r + row * pixmap->data.rgba.row_step; - unsigned char *g = pixmap->data.rgba.g + row * pixmap->data.rgba.row_step; - unsigned char *b = pixmap->data.rgba.b + row * pixmap->data.rgba.row_step; - band_type* pixptr = data + row * pixmap->width * 4; - for(unsigned int col=0;colwidth;col++) { - pixptr[band_order::A] = *a; - pixptr[band_order::G] = *g; - pixptr[band_order::B] = *b; - pixptr[band_order::R] = *r; - pixptr+=4; - a += pixmap->data.rgba.pixel_step; - r += pixmap->data.rgba.pixel_step; - g += pixmap->data.rgba.pixel_step; - b += pixmap->data.rgba.pixel_step; - } - } - //memcpy(data,pixmap->data.rgba.pixels,pixmap->width*pixmap->height*4); - rendering_buffer *b = new rendering_buffer(data, pixmap->width, pixmap->height, (int)pixmap->width*4); - symbol->renderer_cache = (void*)b; - pf.attach(*b); - pf.premultiply(); - } else { - rendering_buffer *b = (rendering_buffer*)symbol->renderer_cache; - pf.attach(*b); - } + rendering_buffer b(pixmap->data.rgba.pixels,pixmap->width,pixmap->height,pixmap->data.rgba.row_step); + pixel_format pf(b); r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); @@ -951,19 +923,7 @@ int agg2FreeImage(imageObj * image) { } int agg2FreeSymbol(symbolObj * symbol) { - switch(symbol->type) { - case MS_SYMBOL_PIXMAP: - case MS_SYMBOL_SVG: - if(symbol->renderer_cache) { - rendering_buffer *rb = (rendering_buffer*)symbol->renderer_cache; - free(rb->buf()); - delete (rendering_buffer*)symbol->renderer_cache; - } - symbol->renderer_cache = NULL; - break; - } return MS_SUCCESS; - } int agg2InitCache(void **vcache) { diff --git a/mapcairo.c b/mapcairo.c index 23fd63c705..fac33afe12 100644 --- a/mapcairo.c +++ b/mapcairo.c @@ -328,55 +328,39 @@ int renderVectorSymbolCairo(imageObj *img, double x, double y, symbolObj *symbol return MS_SUCCESS; } +#ifdef USE_SVG_CAIRO +struct svg_symbol_cache{ + rasterBufferObj pixmap_buffer; + svg_cairo_t *svgc; + double scale,rotation; +} ; +#endif + int renderSVGSymbolCairo(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style) { #ifdef USE_SVG_CAIRO cairo_renderer *r = CAIRO_RENDERER(img); //double ox=symbol->sizex*0.5,oy=symbol->sizey*0.5; - unsigned int svg_width, svg_height; svg_cairo_status_t status; - svg_cairo_t *svgc; - double scale; - - //use cache for svg surface - if(!symbol->renderer_cache) { - status = svg_cairo_create(&svgc); - status = svg_cairo_parse_buffer(svgc, symbol->svg_text, strlen(symbol->svg_text)); - if (status) { - msSetError(MS_RENDERERERR, "problem creating cairo svg", "renderSVGSymbolCairo()"); - return MS_FAILURE; - } - symbol->renderer_cache = svgc; - } - assert(symbol->renderer_cache); - svgc=(svg_cairo_t *)symbol->renderer_cache; + struct svg_symbol_cache *cache; - svg_cairo_get_size (svgc, &svg_width, &svg_height); + msPreloadSVGSymbol(symbol); + assert(symbol->renderer_cache); + cache = symbol->renderer_cache; - //scale such that the SVG is rendered at the desired size in pixels - scale = style->scale; - /* - if (style->scale != 1) { - scale = MS_MIN(style->scale / (double) svg_width, - style->scale / (double) svg_height); - } else { - scale = style->scale; - } - */ - cairo_save(r->cr); cairo_translate(r->cr,x,y); - cairo_scale(r->cr,scale,scale); + cairo_scale(r->cr,style->scale,style->scale); if (style->rotation != 0) { cairo_rotate(r->cr, -style->rotation); - cairo_translate (r->cr, -(int)svg_width/2, -(int)svg_height/2); + cairo_translate (r->cr, -(int)(symbol->sizex/2), -(int)(symbol->sizey/2)); } else - cairo_translate (r->cr, -(int)svg_width/2, -(int)svg_height/2); + cairo_translate (r->cr, -(int)(symbol->sizex/2), -(int)(symbol->sizey/2)); - status = svg_cairo_render(svgc, r->cr); + status = svg_cairo_render(cache->svgc, r->cr); cairo_restore(r->cr); return MS_SUCCESS; @@ -1006,12 +990,17 @@ int freeSymbolCairo(symbolObj *s) { cairo_path_destroy(s->renderer_cache); break; case MS_SYMBOL_PIXMAP: - case MS_SYMBOL_SVG: - if (s->renderer_cache) { - //cairo_surface_finish(s->renderer_cache); - cairo_surface_destroy(s->renderer_cache); - } - break; + 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; } s->renderer_cache=NULL; return MS_SUCCESS; @@ -1031,30 +1020,36 @@ int initializeRasterBufferCairo(rasterBufferObj *rb, int width, int height, int return MS_SUCCESS; } + int msPreloadSVGSymbol(symbolObj *symbol) { #ifdef USE_SVG_CAIRO - svg_cairo_t *svgc; int status; unsigned int svg_width, svg_height; - - if(symbol->svg_cairo_surface) + struct svg_symbol_cache *cache; + + if(!symbol->renderer_cache) { + cache = msSmallCalloc(1,sizeof(struct svg_symbol_cache)); + } else { + cache = symbol->renderer_cache; + } + if(cache->svgc) return MS_SUCCESS; if(!symbol->svg_text) return MS_FAILURE; - status = svg_cairo_create(&svgc); + status = svg_cairo_create(&cache->svgc); if (status) { msSetError(MS_RENDERERERR, "problem creating cairo svg", "msPreloadSVGSymbol()"); return MS_FAILURE; } - status = svg_cairo_parse_buffer(svgc, symbol->svg_text, strlen(symbol->svg_text)); + 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; } - svg_cairo_get_size (svgc, &svg_width, &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()"); @@ -1063,9 +1058,8 @@ int msPreloadSVGSymbol(symbolObj *symbol) symbol->sizex = svg_width; symbol->sizey = svg_height; + symbol->renderer_cache = cache; - symbol->svg_cairo_surface = (void *)svgc; - return MS_SUCCESS; #else @@ -1075,110 +1069,76 @@ int msPreloadSVGSymbol(symbolObj *symbol) #endif } -int msRenderSVGToPixmap(symbolObj *symbol, symbolStyleObj *style) { + + +int msRenderRasterizedSVGSymbol(imageObj *img, double x, double y, 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; + struct svg_symbol_cache *svg_cache; + symbolStyleObj pixstyle; + symbolObj pixsymbol; //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); - } + if(MS_SUCCESS != msPreloadSVGSymbol(symbol)) + return MS_FAILURE; + svg_cache = (struct svg_symbol_cache*) symbol->renderer_cache; + + 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); + + //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 = 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); + 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;rowheight;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;colwidth;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; + 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); + } + if(svg_cairo_render(svg_cache->svgc, cr) != SVG_CAIRO_STATUS_SUCCESS) { + return MS_FAILURE; + } + 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; - rb->scale = style->scale; - rb->rotation = style->rotation; - cairo_destroy(cr); - cairo_surface_destroy(surface); + pixsymbol.pixmap_buffer = &svg_cache->pixmap_buffer; + pixsymbol.type = MS_SYMBOL_PIXMAP; + MS_IMAGE_RENDERER(img)->renderPixmapSymbol(img,x,y,&pixsymbol,&pixstyle); + MS_IMAGE_RENDERER(img)->freeSymbol(&pixsymbol); return MS_SUCCESS; #else msSetError(MS_MISCERR, "SVG Symbols requested but MapServer is not built with libsvgcairo", diff --git a/mapimageio.c b/mapimageio.c index 094b3f2076..e7e49fff97 100644 --- a/mapimageio.c +++ b/mapimageio.c @@ -719,6 +719,7 @@ int msLoadGDRasterBufferFromFile(char *path, rasterBufferObj *rb) { int readPNG(char *path, rasterBufferObj *rb) { png_uint_32 width,height,row_bytes; + unsigned char *a,*r,*g,*b; int bit_depth,color_type,i; unsigned char **row_pointers; png_structp png_ptr = NULL; @@ -757,10 +758,10 @@ int readPNG(char *path, rasterBufferObj *rb) { row_pointers = (unsigned char**)malloc(height*sizeof(unsigned char*)); rb->data.rgba.pixel_step=4; rb->data.rgba.row_step = width*4; - rb->data.rgba.b = &rb->data.rgba.pixels[0]; - rb->data.rgba.g = &rb->data.rgba.pixels[1]; - rb->data.rgba.r = &rb->data.rgba.pixels[2]; - rb->data.rgba.a = &rb->data.rgba.pixels[3]; + b = rb->data.rgba.b = &rb->data.rgba.pixels[0]; + g = rb->data.rgba.g = &rb->data.rgba.pixels[1]; + r = rb->data.rgba.r = &rb->data.rgba.pixels[2]; + a = rb->data.rgba.a = &rb->data.rgba.pixels[3]; for(i=0;idata.rgba.pixels[i*rb->data.rgba.row_step]); @@ -797,6 +798,21 @@ int readPNG(char *path, rasterBufferObj *rb) { row_pointers=NULL; png_read_end(png_ptr,NULL); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + /*premultiply data*/ + for(i=0;i> 8; + *g = (*g * *a + 255) >> 8; + *b = (*b * *a + 255) >> 8; + } + } + a+=4;b+=4;g+=4;r+=4; + } fclose(stream); return MS_SUCCESS; diff --git a/maprendering.c b/maprendering.c index 164625ae48..c2ea908c3b 100644 --- a/maprendering.c +++ b/maprendering.c @@ -188,9 +188,6 @@ imageObj *getTile(imageObj *img, symbolObj *symbol, symbolStyleObj *s, int widt if(tile==NULL) { imageObj *tileimg; double p_x,p_y; -#ifdef USE_SVG_CAIRO - double scale, rotation; -#endif tileimg = msImageCreate(width,height,img->format,NULL,NULL,img->resolution, img->resolution, NULL); if(!seamlessmode) { p_x = width/2.0; @@ -217,18 +214,14 @@ imageObj *getTile(imageObj *img, symbolObj *symbol, symbolStyleObj *s, int widt if(msPreloadSVGSymbol(symbol) != MS_SUCCESS) { return NULL; //failed to load image, renderer should have set the error message } - if (renderer->supports_svg) - renderer->renderSVGSymbol(tileimg, p_x, p_y, symbol, s); - else - { - if (msRenderSVGToPixmap(symbol, s) == MS_SUCCESS){ - scale = s->scale; - rotation = s->rotation; - s->scale = 1.0; - s->rotation = 0; - renderer->renderPixmapSymbol(tileimg, p_x, p_y, symbol, s); - s->scale = scale; - s->rotation = rotation; + if (renderer->supports_svg) { + if(renderer->renderSVGSymbol(tileimg, p_x, p_y, symbol, s) != MS_SUCCESS) { + return NULL; + } + } + else { + if (msRenderRasterizedSVGSymbol(tileimg,p_x,p_y,symbol, s) != MS_SUCCESS){ + return NULL; } } #else @@ -278,15 +271,7 @@ imageObj *getTile(imageObj *img, symbolObj *symbol, symbolStyleObj *s, int widt if (renderer->supports_svg) { renderer->renderSVGSymbol(tile3img, p_x, p_y, symbol, s); } else { - if (msRenderSVGToPixmap(symbol, s) == MS_SUCCESS){ - scale = s->scale; - rotation = s->rotation; - s->scale = 1.0; - s->rotation = 0; - renderer->renderPixmapSymbol(tile3img, p_x, p_y, symbol, s); - s->scale = scale; - s->rotation = rotation; - } + msRenderRasterizedSVGSymbol(tile3img,p_x,p_y,symbol, s); } #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "getTile()"); @@ -836,7 +821,7 @@ int msDrawMarkerSymbol(symbolSetObj *symbolset,imageObj *image, pointObj *p, sty case (MS_SYMBOL_SVG): { #ifdef USE_SVG_CAIRO - if (!symbol->svg_cairo_surface) { + if (!symbol->renderer_cache) { if (MS_SUCCESS != msPreloadSVGSymbol(symbol)) return MS_FAILURE; } @@ -933,17 +918,7 @@ int msDrawMarkerSymbol(symbolSetObj *symbolset,imageObj *image, pointObj *p, sty ret = renderer->renderSVGSymbol(image, p_x, p_y, symbol, &s); } else { #ifdef USE_SVG_CAIRO - if (msRenderSVGToPixmap(symbol, &s) == MS_SUCCESS){ - //store style, render pixmap then reset style - double scale, rotation; - scale = s.scale; - rotation = s.rotation; - s.scale = 1.0; - s.rotation = 0; - ret = renderer->renderPixmapSymbol(image,p_x,p_y,symbol,&s); - s.scale = scale; - s.rotation = rotation; - } + ret = msRenderRasterizedSVGSymbol(image, p_x,p_y, symbol, &s); #else msSetError(MS_SYMERR, "SVG symbol support is not enabled.", "msDrawMarkerSymbol()"); return MS_FAILURE; @@ -953,10 +928,9 @@ int msDrawMarkerSymbol(symbolSetObj *symbolset,imageObj *image, pointObj *p, sty break; default: break; - //} + } return ret; } - } else if( MS_RENDERER_IMAGEMAP(image->format) ) msDrawMarkerSymbolIM(symbolset, image, p, style, scalefactor); diff --git a/mapserver.h b/mapserver.h index f5dcb4f62f..a7fcddbd57 100644 --- a/mapserver.h +++ b/mapserver.h @@ -2811,6 +2811,7 @@ struct rendererVTableObj { int (*freeSymbol)(symbolObj *symbol); int (*cleanup)(void *renderer_data); } ; +MS_DLL_EXPORT int msRenderRasterizedSVGSymbol(imageObj* img, double x, double y, symbolObj* symbol, symbolStyleObj* style); #endif /* SWIG */ diff --git a/mapsymbol.c b/mapsymbol.c index eb3cd349f1..f1eb152526 100644 --- a/mapsymbol.c +++ b/mapsymbol.c @@ -68,10 +68,6 @@ void freeImageCache(struct imageCacheObj *ic) */ double msSymbolGetDefaultSize(symbolObj *s) { double size; -#ifdef USE_SVG_CAIRO - unsigned int svg_width, svg_height; -#endif - if(s == NULL) return 1; @@ -87,10 +83,8 @@ double msSymbolGetDefaultSize(symbolObj *s) { case(MS_SYMBOL_SVG): size = 1; #ifdef USE_SVG_CAIRO - assert(s->svg_cairo_surface != NULL); - if(s->svg_cairo_surface == NULL) return 1; //FIXME - svg_cairo_get_size(s->svg_cairo_surface, &svg_width, &svg_height); - size = (double)svg_height; + assert(s->renderer_cache != NULL); + size = s->sizey; #endif break; default: /* vector and ellipses, scalable */ @@ -128,7 +122,6 @@ void initSymbol(symbolObj *s) s->anchorpoint_x = s->anchorpoint_y = 0.5; s->svg_text = NULL; - s->svg_cairo_surface=NULL; } @@ -147,10 +140,6 @@ int msFreeSymbol(symbolObj *s) { free(s->pixmap_buffer); } -#ifdef USE_SVG_CAIRO - if(s->svg_cairo_surface) - svg_cairo_destroy(s->svg_cairo_surface); -#endif if(s->font) free(s->font); msFree(s->full_font_path); diff --git a/mapsymbol.h b/mapsymbol.h index 9b5d1cf62b..eeea4ec056 100644 --- a/mapsymbol.h +++ b/mapsymbol.h @@ -78,9 +78,6 @@ typedef struct { typedef struct { int type; unsigned int width,height; -#ifdef USE_SVG_CAIRO - double scale, rotation; -#endif union { rgbaArrayObj rgba; paletteArrayObj palette; @@ -192,7 +189,6 @@ typedef struct { void *renderer_cache; char *full_font_path; char *full_pixmap_path; - void *svg_cairo_surface; #endif /* SWIG */ #ifdef SWIG