From 345170c81fdb558d59652a1cae0bb5e206563887 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Wed, 11 Aug 2021 17:21:33 +0200 Subject: [PATCH] Modify renderGlyphs() virtual method to pass the full textSymbolObj, and adapt KML renderer to it (fixes #6174) --- mapagg.cpp | 3 +- mapcairo.c | 3 +- mapkml.cpp | 6 +- mapkmlrenderer.cpp | 13 +- mapkmlrenderer.h | 3 +- maprendering.c | 11 +- mapserver.h | 4 +- maputfgrid.cpp | 3 +- .../wxs/expected/wms_simple_kml_label.kml | 279 ++++++++++++++++++ msautotest/wxs/wms_simple_kml.map | 34 +++ 10 files changed, 339 insertions(+), 20 deletions(-) create mode 100644 msautotest/wxs/expected/wms_simple_kml_label.kml diff --git a/mapagg.cpp b/mapagg.cpp index 661461b48c..0405fb1bdd 100755 --- a/mapagg.cpp +++ b/mapagg.cpp @@ -527,8 +527,9 @@ int agg2RenderPolygonTiled(imageObj *img, shapeObj *p, imageObj * tile) return MS_SUCCESS; } -int agg2RenderGlyphsPath(imageObj *img, textPathObj *tp, colorObj *c, colorObj *oc, int ow, int /*isMarker*/) { +int agg2RenderGlyphsPath(imageObj *img, const textSymbolObj *ts, colorObj *c, colorObj *oc, int ow, int /*isMarker*/) { + const textPathObj *tp = ts->textpath; mapserver::path_storage glyphs; mapserver::trans_affine trans; AGG2Renderer *r = AGG_RENDERER(img); diff --git a/mapcairo.c b/mapcairo.c index 680f9ab7d5..4b0f3d1538 100644 --- a/mapcairo.c +++ b/mapcairo.c @@ -407,7 +407,8 @@ int renderTileCairo(imageObj *img, imageObj *tile, double x, double y) return MS_SUCCESS; } -int renderGlyphs2Cairo(imageObj *img, textPathObj *tp, colorObj *c, colorObj *oc, int ow, int isMarker) { +int renderGlyphs2Cairo(imageObj *img, const textSymbolObj *ts, colorObj *c, colorObj *oc, int ow, int isMarker) { + const textPathObj *tp = ts->textpath; cairo_renderer *r = CAIRO_RENDERER(img); cairoCacheData *cache = MS_IMAGE_RENDERER_CACHE(img); cairoFaceCache *cairo_face = NULL; diff --git a/mapkml.cpp b/mapkml.cpp index 8bfc00addc..388bc9f6e9 100644 --- a/mapkml.cpp +++ b/mapkml.cpp @@ -86,10 +86,10 @@ extern "C" { return MS_SUCCESS; } - int msRenderGlyphsKml(imageObj *img, pointObj *labelpnt, char *text, double angle, colorObj *clr, colorObj *olcolor, int olwidth) + int msRenderGlyphsKml(imageObj *img, const textSymbolObj *ts, colorObj *c, colorObj *oc, int ow, int /*isMarker*/) { KmlRenderer* renderer = getKmlRenderer(img); - renderer->renderGlyphs(img, labelpnt, text, angle, clr, olcolor, olwidth); + renderer->renderGlyphs(img, ts, c, oc, ow); return MS_SUCCESS; } @@ -225,7 +225,7 @@ int msPopulateRendererVTableKML( rendererVTableObj *renderer ) renderer->createImage=&msCreateImageKml; renderer->saveImage=&msSaveImageKml; renderer->renderPolygon=&msRenderPolygonKml; - renderer->renderText=&msRenderGlyphsKml; + renderer->renderGlyphs=&msRenderGlyphsKml; renderer->renderEllipseSymbol = &msRenderEllipseSymbolKml; renderer->renderVectorSymbol = &msRenderVectorSymbolKml; renderer->renderPixmapSymbol = &msRenderPixmapSymbolKml; diff --git a/mapkmlrenderer.cpp b/mapkmlrenderer.cpp index 2125529285..360a51f6f5 100644 --- a/mapkmlrenderer.cpp +++ b/mapkmlrenderer.cpp @@ -666,9 +666,10 @@ void KmlRenderer::addCoordsNode(xmlNodePtr parentNode, pointObj *pts, int numPts xmlNodeAddContent(coordsNode, BAD_CAST "\t"); } -void KmlRenderer::renderGlyphs(imageObj *, pointObj *labelpnt, char *text, double /*angle*/, colorObj *clr, colorObj * /*olcolor*/, int /*olwidth*/) +void KmlRenderer::renderGlyphs(imageObj *, const textSymbolObj *ts, colorObj *clr, colorObj * /*oc*/, int /*ow*/) { - xmlNodePtr node; + if( ts->annotext == NULL || ts->textpath->numglyphs == 0 ) + return; if (PlacemarkNode == NULL) PlacemarkNode = createPlacemarkNode(LayerNode, NULL); @@ -680,12 +681,12 @@ void KmlRenderer::renderGlyphs(imageObj *, pointObj *labelpnt, char *text, doubl SymbologyFlag[Label] = 1; /*there is alaws a default name (layer.shapeid). Replace it*/ - for (node = PlacemarkNode->children; node; node = node->next) { + for (xmlNodePtr node = PlacemarkNode->children; node; node = node->next) { if (node->type != XML_ELEMENT_NODE) continue; if (strcmp((char *)node->name, "name") == 0) { - xmlNodeSetContent(node, BAD_CAST text); + xmlNodeSetContent(node, BAD_CAST ts->annotext); break; } } @@ -696,8 +697,8 @@ void KmlRenderer::renderGlyphs(imageObj *, pointObj *labelpnt, char *text, doubl addAddRenderingSpecifications(geomNode); pointObj pt; - pt.x = labelpnt->x; - pt.y = labelpnt->y; + pt.x = ts->textpath->glyphs[0].pnt.x; + pt.y = ts->textpath->glyphs[0].pnt.y; addCoordsNode(geomNode, &pt, 1); } diff --git a/mapkmlrenderer.h b/mapkmlrenderer.h index 8a442c7f5a..59df347e7e 100644 --- a/mapkmlrenderer.h +++ b/mapkmlrenderer.h @@ -133,7 +133,6 @@ class KmlRenderer void renderLineVector(imageObj *img, shapeObj *p, strokeStyleObj *style); void renderPolygonVector(imageObj *img, shapeObj *p, colorObj *color); - void renderGlyphsVector(imageObj *img, double x, double y, labelStyleObj *style, char *text); const char* lookupPlacemarkStyle(); void flushPlacemark(); @@ -160,7 +159,7 @@ class KmlRenderer void renderLine(imageObj *img, shapeObj *p, strokeStyleObj *style); void renderPolygon(imageObj *img, shapeObj *p, colorObj *color); - void renderGlyphs(imageObj *img, pointObj *labelpnt, char *text, double angle, colorObj *clr, colorObj *olcolor, int olwidth); + void renderGlyphs(imageObj *img, const textSymbolObj *ts, colorObj *c, colorObj *oc, int ow); // Symbols void renderPixmapSymbol(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); diff --git a/maprendering.c b/maprendering.c index 0365c01ca9..3ba67652b7 100755 --- a/maprendering.c +++ b/maprendering.c @@ -179,7 +179,7 @@ tileCacheObj *addTileCache(imageObj *img, } /* helper function to center glyph on the desired point */ -int WARN_UNUSED drawGlyphMarker(imageObj *img, face_element *face, glyph_element *glyphc, double px, double py, int size, double rotation, +static int drawGlyphMarker(imageObj *img, face_element *face, glyph_element *glyphc, double px, double py, int size, double rotation, colorObj *clr, colorObj *oclr, int olwidth) { double ox, oy; @@ -210,7 +210,10 @@ int WARN_UNUSED drawGlyphMarker(imageObj *img, face_element *face, glyph_element glyph.pnt.x = px - ox; glyph.pnt.y = py + oy; } - return renderer->renderGlyphs(img, &path, clr, oclr, olwidth, MS_TRUE); + textSymbolObj ts; + memset(&ts, 0, sizeof(ts)); + ts.textpath = &path; + return renderer->renderGlyphs(img, &ts, clr, oclr, olwidth, MS_TRUE); } @@ -1045,7 +1048,7 @@ int msDrawTextSymbol(mapObj *map, imageObj *image, pointObj labelPnt, textSymbol ts_shadow->textpath->glyphs[g].pnt.y += oy; } - ret = renderer->renderGlyphs(image,ts_shadow->textpath,&ts->label->shadowcolor,NULL,0, MS_FALSE); + ret = renderer->renderGlyphs(image,ts_shadow,&ts->label->shadowcolor,NULL,0, MS_FALSE); freeTextSymbol(ts_shadow); msFree(ts_shadow); if( ret != MS_SUCCESS ) @@ -1057,7 +1060,7 @@ int msDrawTextSymbol(mapObj *map, imageObj *image, pointObj labelPnt, textSymbol if(MS_VALID_COLOR(ts->label->outlinecolor)) oc = &ts->label->outlinecolor; ow = MS_NINT((double)ts->label->outlinewidth * ((double)ts->textpath->glyph_size / (double)ts->label->size)); - return renderer->renderGlyphs(image,ts->textpath,c,oc,ow, MS_FALSE); + return renderer->renderGlyphs(image,ts,c,oc,ow, MS_FALSE); } diff --git a/mapserver.h b/mapserver.h index 44162b0c39..0ed208fade 100755 --- a/mapserver.h +++ b/mapserver.h @@ -3211,8 +3211,8 @@ extern "C" { int WARN_UNUSED (*renderPolygonTiled)(imageObj *img, shapeObj *p, imageObj *tile); int WARN_UNUSED (*renderLineTiled)(imageObj *img, shapeObj *p, imageObj *tile); - int WARN_UNUSED (*renderGlyphs)(imageObj *img, textPathObj *tp, colorObj *clr, colorObj *olcolor, int olwidth, int isMarker); - int WARN_UNUSED (*renderText)(imageObj *img, pointObj *labelpnt, char *text, double angle, colorObj *clr, colorObj *olcolor, int olwidth); + /* only ts->textpath is guaranteed to be populated. Other fields might be 0/NULL */ + int WARN_UNUSED (*renderGlyphs)(imageObj *img, const textSymbolObj *ts, colorObj *clr, colorObj *olcolor, int olwidth, int isMarker); int WARN_UNUSED (*renderVectorSymbol)(imageObj *img, double x, double y, symbolObj *symbol, symbolStyleObj *style); diff --git a/maputfgrid.cpp b/maputfgrid.cpp index 55328de822..33fae7d464 100644 --- a/maputfgrid.cpp +++ b/maputfgrid.cpp @@ -688,8 +688,9 @@ int utfgridRenderEllipseSymbol(imageObj *img, double x, double y, symbolObj *sym } static -int utfgridRenderGlyphs(imageObj *img, textPathObj *tp, colorObj * /*c*/, colorObj * /*oc*/, int /*ow*/, int isMarker) { +int utfgridRenderGlyphs(imageObj *img, const textSymbolObj *ts, colorObj * /*c*/, colorObj * /*oc*/, int /*ow*/, int isMarker) { + const textPathObj *tp = ts->textpath; const UTFGridRenderer *r = UTFGRID_RENDERER(img); /* If it's not a marker then it's a label or other thing and we dont diff --git a/msautotest/wxs/expected/wms_simple_kml_label.kml b/msautotest/wxs/expected/wms_simple_kml_label.kml new file mode 100644 index 0000000000..42239975cc --- /dev/null +++ b/msautotest/wxs/expected/wms_simple_kml_label.kml @@ -0,0 +1,279 @@ + + + + + + + + WMS_TEST + + + popplace + 1 + #LayerFolder_check + + "Tignish + #style_label_ff000000 + + + -64.05235541,46.98084305 + + + + + 'Cheticamp + #style_label_ff000000 + + + -60.98103788,46.68932288 + + + + + Sheet Harbour + #style_label_ff000000 + + + -62.51307844,44.91180032 + + + + + 'Souris' + #style_label_ff000000 + + + -62.27242993,46.37327164 + + + + + "Canso" + #style_label_ff000000 + + + -61.03874329,45.31128627 + + + + + Port Hawkesbury + #style_label_ff000000 + + + -61.37997660,45.65230747 + + + + + Antigonish + #style_label_ff000000 + + + -61.99737466,45.63945856 + + + + + Springhill + #style_label_ff000000 + + + -64.10962754,45.62796308 + + + + + "Wind"sor + #style_label_ff000000 + + + -64.19005686,44.97154750 + + + + + Lunenburg + #style_label_ff000000 + + + -64.33357666,44.37579449 + + + + + Liverpool + #style_label_ff000000 + + + -64.73281556,44.02035866 + + + + + Middleton + #style_label_ff000000 + + + -65.11482838,44.93816141 + + + + + Digby + #style_label_ff000000 + + + -65.81602426,44.61104869 + + + + + Shelburne + #style_label_ff000000 + + + -65.31837062,43.74011817 + + + + + Summerside + #style_label_ff000000 + + + -63.83197912,46.43127112 + + + + + New Glasgow + #style_label_ff000000 + + + -62.69300570,45.58942182 + + + + + Tr"uro + #style_label_ff000000 + + + -63.33519337,45.34330165 + + + + + Amherst + #style_label_ff000000 + + + -64.24404418,45.81894901 + + + + + Kentville + #style_label_ff000000 + + + -64.56907366,45.06472860 + + + + + Bridgewater + #style_label_ff000000 + + + -64.56321843,44.36519508 + + + + + Yarmouth + #style_label_ff000000 + + + -66.15895655,43.79770276 + + + + + Sydney Mines + #style_label_ff000000 + + + -60.28066115,46.27689752 + + + + + Sydney + #style_label_ff000000 + + + -60.21496347,46.12332205 + + + + + Dartmouth + #style_label_ff000000 + + + -63.57003995,44.68279156 + + + + + Fatima + #style_label_ff000000 + + + -61.90309910,47.40477005 + + + + + Charlottetown + #style_label_ff000000 + + + -63.16701651,46.29119095 + + + + + Halifax + #style_label_ff000000 + + + -63.69201127,44.61558257 + + + + + + diff --git a/msautotest/wxs/wms_simple_kml.map b/msautotest/wxs/wms_simple_kml.map index ac6d00431a..f43328c9fe 100644 --- a/msautotest/wxs/wms_simple_kml.map +++ b/msautotest/wxs/wms_simple_kml.map @@ -9,6 +9,8 @@ # Same with KMZ output # RUN_PARMS: wms_get_map_polygon.kmz [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.1.0&REQUEST=GetMap&SRS=EPSG:4326&BBOX=-67.5725,42.3683,-58.9275,48.13&FORMAT=kmz&WIDTH=300&HEIGHT=200&STYLES=&LAYERS=road" > [RESULT_DEMIME] +# RUN_PARMS: wms_simple_kml_label.kml [MAPSERV] QUERY_STRING="map=[MAPFILE]&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&CRS=EPSG%3A4326&BBOX=40,-70,50,-60&WIDTH=400&HEIGHT=400&LAYERS=popplace&STYLES=&FORMAT=kml" > [RESULT_DEMIME] + MAP NAME WMS_TEST @@ -98,4 +100,36 @@ LAYER END END # Layer +LAYER + NAME popplace + DATA popplace + METADATA + "wms_title" "popplace" + "wms_description" "Cities of I.P.E." + "wms_result_fields" "NAME" + "gml_NAME_alias" "NAME_ALIAS" + END + TYPE POINT + STATUS ON + PROJECTION + "init=epsg:3978" + END + + LabelItem "Name" + CLASSITEM "Capital" + + CLASS + NAME "Cities" + LABEL + COLOR 0 0 0 + FONT Vera + TYPE truetype + SIZE 8 + POSITION AUTO + PARTIALS FALSE + OUTLINECOLOR 255 255 255 + END + END +END # Layer + END # Map File