int msPopulateRendererVTableCairoRaster( rendererVTableObj *renderer ) { #ifdef USE_CAIRO renderer->supports_pixel_buffer=1; renderer->supports_transparent_layers = 0; renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY; initializeCache(&MS_RENDERER_CACHE(renderer)); renderer->startLayer = startLayerRasterCairo; renderer->endLayer = closeLayerRasterCairo; renderer->renderLineTiled = NULL; renderer->renderLine=&renderLineCairo; renderer->createImage=&createImageCairo; renderer->saveImage=&saveImageCairo; renderer->getRasterBufferHandle=&getRasterBufferHandleCairo; renderer->getRasterBufferCopy=&getRasterBufferCopyCairo; renderer->renderPolygon=&renderPolygonCairo; renderer->renderGlyphs=&renderGlyphsCairo; renderer->freeImage=&freeImageCairo; renderer->renderEllipseSymbol = &renderEllipseSymbolCairo; renderer->renderVectorSymbol = &renderVectorSymbolCairo; renderer->renderTruetypeSymbol = &renderTruetypeSymbolCairo; renderer->renderPixmapSymbol = &renderPixmapSymbolCairo; renderer->mergeRasterBuffer = &mergeRasterBufferCairo; renderer->getTruetypeTextBBox = &getTruetypeTextBBoxCairo; renderer->renderTile = &renderTileCairo; renderer->loadImageFromFile = &msLoadMSRasterBufferFromFile; renderer->renderPolygonTiled = &renderPolygonTiledCairo; renderer->freeSymbol = &freeSymbolCairo; renderer->cleanup = &cleanupCairo; return MS_SUCCESS; #else msSetError(MS_MISCERR, "Cairo Driver requested but is not built in", "msPopulateRendererVTableCairoRaster()"); return MS_FAILURE; #endif }
int msPopulateRendererVTableAGG(rendererVTableObj * renderer) { renderer->supports_transparent_layers = 0; renderer->supports_pixel_buffer = 1; renderer->use_imagecache = 0; renderer->supports_clipping = 0; renderer->supports_svg = 0; renderer->default_transform_mode = MS_TRANSFORM_SIMPLIFY; agg2InitCache(&(MS_RENDERER_CACHE(renderer))); renderer->cleanup = agg2Cleanup; renderer->renderLine = &agg2RenderLine; renderer->renderPolygon = &agg2RenderPolygon; renderer->renderPolygonTiled = &agg2RenderPolygonTiled; renderer->renderLineTiled = &agg2RenderLineTiled; renderer->renderGlyphs = &agg2RenderGlyphs; renderer->renderGlyphsLine = &agg2RenderGlyphsLine; renderer->renderBitmapGlyphs = &agg2RenderBitmapGlyphs; renderer->renderVectorSymbol = &agg2RenderVectorSymbol; renderer->renderPixmapSymbol = &agg2RenderPixmapSymbol; renderer->renderEllipseSymbol = &agg2RenderEllipseSymbol; renderer->renderTruetypeSymbol = &agg2RenderTruetypeSymbol; renderer->renderTile = &agg2RenderTile; renderer->getRasterBufferHandle = &aggGetRasterBufferHandle; renderer->getRasterBufferCopy = aggGetRasterBufferCopy; renderer->initializeRasterBuffer = aggInitializeRasterBuffer; renderer->mergeRasterBuffer = &agg2MergeRasterBuffer; renderer->loadImageFromFile = msLoadMSRasterBufferFromFile; renderer->createImage = &agg2CreateImage; renderer->saveImage = &agg2SaveImage; renderer->getTruetypeTextBBox = &agg2GetTruetypeTextBBox; renderer->startLayer = &agg2StartNewLayer; renderer->endLayer = &agg2CloseNewLayer; renderer->freeImage = &agg2FreeImage; renderer->freeSymbol = &agg2FreeSymbol; renderer->cleanup = agg2Cleanup; renderer->supports_bitmap_fonts = 1; for(int i=0; i<5; i++) { renderer->bitmapFontMetrics[i] = &(rasterfont_sizes[i]); } return MS_SUCCESS; }
void msFreeOutputFormat( outputFormatObj *format ) { if( format == NULL ) return; if(MS_RENDERER_PLUGIN(format) && format->vtable) { format->vtable->cleanup(MS_RENDERER_CACHE(format->vtable)); free( format->vtable ); } msFree( format->name ); msFree( format->mimetype ); msFree( format->driver ); msFree( format->extension ); msFreeCharArray( format->formatoptions, format->numformatoptions ); msFree( format ); }
int agg2RenderTruetypeSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj * style) { AGG2Renderer *r = AGG_RENDERER(img); aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(MS_IMAGE_RENDERER(img)); if(aggLoadFont(cache,symbol->full_font_path,style->scale) == MS_FAILURE) return MS_FAILURE; int unicode; font_curve_type m_curves(cache->m_fman.path_adaptor()); msUTF8ToUniChar(symbol->character, &unicode); const mapserver::glyph_cache* glyph = cache->m_fman.glyph(unicode); double ox = (glyph->bounds.x1 + glyph->bounds.x2) / 2.; double oy = (glyph->bounds.y1 + glyph->bounds.y2) / 2.; mapserver::trans_affine mtx = mapserver::trans_affine_translation(-ox, -oy); if(style->rotation) mtx *= mapserver::trans_affine_rotation(-style->rotation); mtx *= mapserver::trans_affine_translation(x, y); mapserver::path_storage glyphs; cache->m_fman.init_embedded_adaptors(glyph, 0,0); mapserver::conv_transform<font_curve_type, mapserver::trans_affine> trans_c(m_curves, mtx); glyphs.concat_path(trans_c); if (style->outlinecolor) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); mapserver::conv_contour<mapserver::path_storage> cc(glyphs); cc.auto_detect_orientation(true); cc.width(style->outlinewidth + 1); r->m_rasterizer_aa.add_path(cc); r->m_renderer_scanline.color(aggColor(style->outlinecolor)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } if (style->color) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); r->m_rasterizer_aa.add_path(glyphs); r->m_renderer_scanline.color(aggColor(style->color)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } return MS_SUCCESS; }
int getTruetypeTextBBoxCairo(rendererVTableObj *renderer, char *font, double size, char *text, rectObj *rect, double **advances) { cairoCacheData *cache = MS_RENDERER_CACHE(renderer); faceCacheObj *face = getFontFace(cache,font); char *utfptr=text; int i,has_kerning,unicode; unsigned long previdx=0; int numglyphs = msGetNumGlyphs(text); cairo_glyph_t glyph; cairo_text_extents_t extents; double px=0,py=0; if(face == NULL) { return MS_FAILURE; } cairo_set_font_face(cache->dummycr,face->face); cairo_set_font_size(cache->dummycr,size*96/72.0); has_kerning = FT_HAS_KERNING((face->ftface)); if(advances != NULL) { *advances = (double*)malloc(numglyphs*sizeof(double)); } for(i=0;i<numglyphs;i++) { utfptr+=msUTF8ToUniChar(utfptr, &unicode); glyph.x=px; glyph.y=py; if(unicode=='\n') { py += ceil(size*CAIROLINESPACE); px = 0; previdx=0; continue; } glyph.index = FT_Get_Char_Index(face->ftface, unicode); if( has_kerning && previdx ) { FT_Vector delta; FT_Get_Kerning( face->ftface, previdx, glyph.index, FT_KERNING_DEFAULT, &delta ); px += delta.x / 64.; } cairo_glyph_extents(cache->dummycr,&glyph,1,&extents); if(i==0) { rect->minx = px+extents.x_bearing; rect->miny = py+extents.y_bearing; rect->maxx = px+extents.x_bearing+extents.width; rect->maxy = py+extents.y_bearing+extents.height; } else { rect->minx = MS_MIN(rect->minx,px+extents.x_bearing); rect->miny = MS_MIN(rect->miny,py+extents.y_bearing); rect->maxy = MS_MAX(rect->maxy,py+extents.y_bearing+extents.height); rect->maxx = MS_MAX(rect->maxx,px+extents.x_bearing+extents.width); } if(advances!=NULL) (*advances)[i]=extents.x_advance; px += extents.x_advance; previdx=glyph.index; } /* rect->minx = 0; rect->miny = 0; rect->maxx = 1; rect->maxy = 1; */ return MS_SUCCESS; }
/* helper functions */ int agg2GetTruetypeTextBBox(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *string, rectObj *rect, double **advances,int bAdjustBaseline) { aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(renderer); if(aggLoadFont(cache,fonts[0],size) == MS_FAILURE) return MS_FAILURE; int curfontidx = 0; int unicode, curGlyph = 1, numglyphs = 0; if (advances) { numglyphs = msGetNumGlyphs(string); } const mapserver::glyph_cache* glyph; string += msUTF8ToUniChar(string, &unicode); if(curfontidx != 0) { if(aggLoadFont(cache,fonts[0],size) == MS_FAILURE) return MS_FAILURE; curfontidx = 0; } glyph = cache->m_fman.glyph(unicode); if(!glyph || glyph->glyph_index == 0) { int i; for(i=1; i<numfonts; i++) { if(aggLoadFont(cache,fonts[i],size) == MS_FAILURE) return MS_FAILURE; curfontidx = i; glyph = cache->m_fman.glyph(unicode); if(glyph && glyph->glyph_index != 0) { break; } } } if (glyph) { rect->minx = glyph->bounds.x1; rect->maxx = glyph->bounds.x2; rect->miny = glyph->bounds.y1; rect->maxy = bAdjustBaseline?1:glyph->bounds.y2; } else return MS_FAILURE; if (advances) { *advances = (double*) malloc(numglyphs * sizeof (double)); MS_CHECK_ALLOC(*advances, numglyphs * sizeof (double), MS_FAILURE); (*advances)[0] = glyph->advance_x; } double fx = glyph->advance_x, fy = glyph->advance_y; while (*string) { if (advances) { if (*string == '\r' || *string == '\n') (*advances)[curGlyph++] = -fx; } if (*string == '\r') { fx = 0; string++; continue; } if (*string == '\n') { fx = 0; fy += ceil(size * AGG_LINESPACE); string++; continue; } string += msUTF8ToUniChar(string, &unicode); if(curfontidx != 0) { if(aggLoadFont(cache,fonts[0],size) == MS_FAILURE) return MS_FAILURE; curfontidx = 0; } glyph = cache->m_fman.glyph(unicode); if(!glyph || glyph->glyph_index == 0) { int i; for(i=1; i<numfonts; i++) { if(aggLoadFont(cache,fonts[i],size) == MS_FAILURE) return MS_FAILURE; curfontidx = i; glyph = cache->m_fman.glyph(unicode); if(glyph && glyph->glyph_index != 0) { break; } } } if (glyph) { rect->minx = MS_MIN(rect->minx, fx+glyph->bounds.x1); rect->miny = MS_MIN(rect->miny, fy+glyph->bounds.y1); rect->maxx = MS_MAX(rect->maxx, fx+glyph->bounds.x2); rect->maxy = MS_MAX(rect->maxy, fy+(bAdjustBaseline?1:glyph->bounds.y2)); fx += glyph->advance_x; fy += glyph->advance_y; if (advances) { (*advances)[curGlyph++] = glyph->advance_x; } } } return MS_SUCCESS; }
int agg2RenderGlyphsLine(imageObj *img, labelPathObj *labelpath, labelStyleObj *style, char *text) { AGG2Renderer *r = AGG_RENDERER(img); aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(MS_IMAGE_RENDERER(img)); if(aggLoadFont(cache,style->fonts[0],style->size) == MS_FAILURE) return MS_FAILURE; r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); const mapserver::glyph_cache* glyph; int unicode; int curfontidx = 0; font_curve_type m_curves(cache->m_fman.path_adaptor()); mapserver::path_storage glyphs; for (int i = 0; i < labelpath->path.numpoints; i++) { assert(text); mapserver::trans_affine mtx; mtx *= mapserver::trans_affine_translation(-labelpath->path.point[i].x,-labelpath->path.point[i].y); mtx *= mapserver::trans_affine_rotation(-labelpath->angles[i]); mtx *= mapserver::trans_affine_translation(labelpath->path.point[i].x,labelpath->path.point[i].y); text += msUTF8ToUniChar(text, &unicode); if(curfontidx != 0) { if(aggLoadFont(cache,style->fonts[0],style->size) == MS_FAILURE) return MS_FAILURE; curfontidx = 0; } glyph = cache->m_fman.glyph(unicode); if(!glyph || glyph->glyph_index == 0) { int i; for(i=1; i<style->numfonts; i++) { if(aggLoadFont(cache,style->fonts[i],style->size) == MS_FAILURE) return MS_FAILURE; curfontidx = i; glyph = cache->m_fman.glyph(unicode); if(glyph && glyph->glyph_index != 0) { break; } } } if (glyph) { cache->m_fman.init_embedded_adaptors(glyph, labelpath->path.point[i].x,labelpath->path.point[i].y); mapserver::conv_transform<font_curve_type, mapserver::trans_affine> trans_c(m_curves, mtx); glyphs.concat_path(trans_c); } } if (style->outlinewidth) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); mapserver::conv_contour<mapserver::path_storage> cc(glyphs); cc.width(style->outlinewidth + 1); r->m_rasterizer_aa.add_path(cc); r->m_renderer_scanline.color(aggColor(style->outlinecolor)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } if (style->color) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); r->m_rasterizer_aa.add_path(glyphs); r->m_renderer_scanline.color(aggColor(style->color)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } return MS_SUCCESS; }
int agg2RenderGlyphs(imageObj *img, double x, double y, labelStyleObj *style, char *text) { AGG2Renderer *r = AGG_RENDERER(img); aggRendererCache *cache = (aggRendererCache*)MS_RENDERER_CACHE(MS_IMAGE_RENDERER(img)); if(aggLoadFont(cache,style->fonts[0],style->size) == MS_FAILURE) return MS_FAILURE; r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); int curfontidx = 0; const mapserver::glyph_cache* glyph; int unicode; font_curve_type m_curves(cache->m_fman.path_adaptor()); mapserver::trans_affine mtx; mtx *= mapserver::trans_affine_translation(-x, -y); /*agg angles are antitrigonometric*/ mtx *= mapserver::trans_affine_rotation(-style->rotation); mtx *= mapserver::trans_affine_translation(x, y); double fx = x, fy = y; const char *utfptr = text; mapserver::path_storage glyphs; //first render all the glyphs to a path while (*utfptr) { if (*utfptr == '\r') { fx = x; utfptr++; continue; } if (*utfptr == '\n') { fx = x; fy += ceil(style->size * AGG_LINESPACE); utfptr++; continue; } utfptr += msUTF8ToUniChar(utfptr, &unicode); if(curfontidx != 0) { if(aggLoadFont(cache,style->fonts[0],style->size) == MS_FAILURE) return MS_FAILURE; curfontidx = 0; } glyph = cache->m_fman.glyph(unicode); if(!glyph || glyph->glyph_index == 0) { int i; for(i=1; i<style->numfonts; i++) { if(aggLoadFont(cache,style->fonts[i],style->size) == MS_FAILURE) return MS_FAILURE; curfontidx = i; glyph = cache->m_fman.glyph(unicode); if(glyph && glyph->glyph_index != 0) { break; } } } if (glyph) { //cache->m_fman.add_kerning(&fx, &fy); cache->m_fman.init_embedded_adaptors(glyph, fx, fy); mapserver::conv_transform<font_curve_type, mapserver::trans_affine> trans_c(m_curves, mtx); glyphs.concat_path(trans_c); fx += glyph->advance_x; fy += glyph->advance_y; } } if (style->outlinewidth) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); mapserver::conv_contour<mapserver::path_storage> cc(glyphs); cc.width(style->outlinewidth + 1); r->m_rasterizer_aa.add_path(cc); r->m_renderer_scanline.color(aggColor(style->outlinecolor)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } if (style->color) { r->m_rasterizer_aa.reset(); r->m_rasterizer_aa.filling_rule(mapserver::fill_non_zero); r->m_rasterizer_aa.add_path(glyphs); r->m_renderer_scanline.color(aggColor(style->color)); mapserver::render_scanlines(r->m_rasterizer_aa, r->sl_line, r->m_renderer_scanline); } return MS_SUCCESS; }
int getTruetypeTextBBoxCairo(rendererVTableObj *renderer, char **fonts, int numfonts, double size, char *text, rectObj *rect, double **advances, int bAdjustBaseline) { cairoCacheData *cache = MS_RENDERER_CACHE(renderer); faceCacheObj* face = getFontFace(cache,fonts[0]); int curfontidx = 0; char *utfptr=text; int i,unicode; unsigned long previdx=0; faceCacheObj* prevface = face; int numglyphs = msGetNumGlyphs(text); cairo_glyph_t glyph; cairo_text_extents_t extents; double px=0,py=0; if(face == NULL) { return MS_FAILURE; } cairo_set_font_face(cache->dummycr,face->face); cairo_set_font_size(cache->dummycr,size*96/72.0); if(advances != NULL) { *advances = (double*)malloc(numglyphs*sizeof(double)); } for(i=0; i<numglyphs; i++) { utfptr+=msUTF8ToUniChar(utfptr, &unicode); glyph.x=px; glyph.y=py; if(unicode=='\n') { py += ceil(size*CAIROLINESPACE); px = 0; previdx=0; continue; } if (curfontidx != 0) { face = getFontFace(cache, fonts[0]); cairo_set_font_face(cache->dummycr, face->face); curfontidx = 0; } if (face->ftface->charmap && face->ftface->charmap->encoding == FT_ENCODING_MS_SYMBOL) unicode |= 0xf000; glyph.index = FT_Get_Char_Index(face->ftface, unicode); if (glyph.index == 0) { int j; for (j = 1; j < numfonts; j++) { curfontidx = j; face = getFontFace(cache, fonts[j]); glyph.index = FT_Get_Char_Index(face->ftface, unicode); if (glyph.index != 0) { cairo_set_font_face(cache->dummycr, face->face); break; } } } if( FT_HAS_KERNING((prevface->ftface)) && previdx ) { FT_Vector delta; FT_Get_Kerning( prevface->ftface, previdx, glyph.index, FT_KERNING_DEFAULT, &delta ); px += delta.x / 64.; } cairo_glyph_extents(cache->dummycr,&glyph,1,&extents); if(i==0) { rect->minx = px+extents.x_bearing; rect->miny = py+extents.y_bearing; rect->maxx = px+extents.x_bearing+extents.width; rect->maxy = py+(bAdjustBaseline?1:(extents.y_bearing+extents.height)); } else { rect->minx = MS_MIN(rect->minx,px+extents.x_bearing); rect->miny = MS_MIN(rect->miny,py+extents.y_bearing); rect->maxy = MS_MAX(rect->maxy,py+(bAdjustBaseline?1:(extents.y_bearing+extents.height))); rect->maxx = MS_MAX(rect->maxx,px+extents.x_bearing+extents.width); } if(advances!=NULL) (*advances)[i]=extents.x_advance; px += extents.x_advance; previdx=glyph.index; prevface = face; } return MS_SUCCESS; }