[mapserver-commits] r7174 - trunk/mapserver
svn at osgeo.org
svn at osgeo.org
Fri Dec 14 14:43:56 EST 2007
Author: Assefa
Date: 2007-12-14 14:43:55 -0500 (Fri, 14 Dec 2007)
New Revision: 7174
Modified:
trunk/mapserver/HISTORY.TXT
trunk/mapserver/maplegend.c
trunk/mapserver/mapserver.h
trunk/mapserver/mapwms.c
Log:
Accurate Calculation of legend size for WMS LegendURL (#2435)
Modified: trunk/mapserver/HISTORY.TXT
===================================================================
--- trunk/mapserver/HISTORY.TXT 2007-12-14 18:39:18 UTC (rev 7173)
+++ trunk/mapserver/HISTORY.TXT 2007-12-14 19:43:55 UTC (rev 7174)
@@ -13,6 +13,8 @@
Current Version (5.1-dev, SVN trunk):
-------------------------------------
+- Accurate Calculation of legend size for WMS LegendURL (#2435)
+
- Converted mapogr.cpp to use OGR C API instead of C++ classes to allow
GDAL/OGR updates without having to recompile MapServer (#545, #697)
Modified: trunk/mapserver/maplegend.c
===================================================================
--- trunk/mapserver/maplegend.c 2007-12-14 18:39:18 UTC (rev 7173)
+++ trunk/mapserver/maplegend.c 2007-12-14 19:43:55 UTC (rev 7174)
@@ -110,6 +110,120 @@
}
/*
+ * Calculates the optimal size for the legend. If the optional layerObj
+ * argument is given, the legend size will be calculated for only that
+ * layer. Otherwise, the legend size is calculated for all layers that
+ * are not MS_OFF or of MS_LAYER_QUERY type.
+ *
+ * Returns one of:
+ * MS_SUCCESS
+ * MS_FAILURE
+ */
+int msLegendCalcSize(mapObj *map, int scale_independent, int *size_x,
+ int *size_y, layerObj *psForLayer) {
+ int i, j;
+ int status, maxwidth=0, nLegendItems=0;
+ char *transformedText; // Label text after applying wrapping,
+ // encoding if necessary
+ layerObj *lp;
+ rectObj rect;
+
+ /* Reset sizes */
+ *size_x = 0;
+ *size_y = 0;
+
+ /* Enable scale-dependent calculations */
+ if (!scale_independent) {
+ map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height);
+ status = msCalculateScale(map->extent, map->units, map->width,
+ map->height, map->resolution, &map->scaledenom);
+ if (status != MS_SUCCESS) return MS_FAILURE;
+ }
+
+
+ /*
+ * step through all map classes, and for each one that will be displayed
+ * calculate the label size
+ */
+ for (i=0; i<map->numlayers; i++)
+ {
+ if (psForLayer)
+ {
+ lp = psForLayer;
+ i = map->numlayers;
+ }
+ else
+ lp = (GET_LAYER(map, map->layerorder[i]));
+
+ if ((lp->status == MS_OFF) || (lp->type == MS_LAYER_QUERY)) /* skip it */
+ continue;
+
+ if (!scale_independent && map->scaledenom > 0) {
+ if ((lp->maxscaledenom > 0) && (map->scaledenom > lp->maxscaledenom))
+ continue;
+ if ((lp->minscaledenom > 0) && (map->scaledenom <= lp->minscaledenom))
+ continue;
+ }
+
+ for (j=lp->numclasses-1; j>=0; j--)
+ {
+ if (!lp->class[j]->name) continue; /* skip it */
+
+ /* Verify class scale */
+ if (!scale_independent && map->scaledenom > 0) {
+ if ( (lp->class[j]->maxscaledenom > 0)
+ && (map->scaledenom > lp->class[j]->maxscaledenom))
+ continue;
+
+ if ( (lp->class[j]->minscaledenom > 0)
+ && (map->scaledenom <= lp->class[j]->minscaledenom))
+ continue;
+ }
+
+ /*
+ * apply encoding and line wrapping to the legend label if requested
+ * this is done conditionnally as the text transformation function
+ * does some memory allocations that can be avoided in most cases.
+ * the transformed text must be freed once finished, this must be done
+ * conditionnally by testing if the transformed text pointer is the
+ * same as the class name pointer
+ */
+ if (map->legend.label.encoding || map->legend.label.wrap)
+ transformedText = msTransformLabelText(&map->legend.label,
+ lp->class[j]->name);
+ else
+ transformedText = strdup(lp->class[j]->name);
+
+ if ( transformedText == NULL
+ || msGetLabelSize(transformedText, &map->legend.label,
+ &rect, &(map->fontset), 1.0, MS_FALSE) != 0)
+ { /* something bad happened */
+ if (transformedText)
+ msFree(transformedText);
+
+ return MS_FAILURE;
+ }
+
+ msFree(transformedText);
+ maxwidth = MS_MAX(maxwidth, MS_NINT(rect.maxx - rect.minx));
+ *size_y += MS_MAX(MS_NINT(rect.maxy - rect.miny), map->legend.keysizey);
+ nLegendItems++;
+ }
+ }
+
+ /* Calculate the size of the legend: */
+ /* - account for the Y keyspacing */
+ *size_y += (2*VMARGIN) + ((nLegendItems-1) * map->legend.keyspacingy);
+ /* - determine the legend width */
+ *size_x = (2*HMARGIN) + maxwidth + map->legend.keyspacingx + map->legend.keysizex;
+
+ if (*size_y <=0 || *size_x <=0)
+ return MS_FAILURE;
+
+ return MS_SUCCESS;
+}
+
+/*
** Creates a GD image of a legend for a specific map. msDrawLegend()
** respects the current scale, and classes without a name are not
** added to the legend.
@@ -121,14 +235,11 @@
*/
imageObj *msDrawLegend(mapObj *map, int scale_independent)
{
- int status;
-
gdImagePtr img; /* image data structure */
int i,j; /* loop counters */
pointObj pnt;
int size_x, size_y=0;
layerObj *lp;
- int maxwidth=0,nLegendItems=0;
rectObj rect;
imageObj *image = NULL;
outputFormatObj *format = NULL;
@@ -142,14 +253,12 @@
typedef struct legend_struct legendlabel;
legendlabel *head=NULL,*cur=NULL;
- if (!scale_independent) {
- map->cellsize = msAdjustExtent(&(map->extent), map->width, map->height);
- status = msCalculateScale(map->extent, map->units, map->width, map->height, map->resolution, &map->scaledenom);
- if(status != MS_SUCCESS) return(NULL);
- }
+
if(msValidateContexts(map) != MS_SUCCESS) return NULL; /* make sure there are no recursive REQUIRES or LABELREQUIRES expressions */
+ if(msLegendCalcSize(map, scale_independent, &size_x, &size_y, NULL) != MS_SUCCESS) return NULL;
+
/*
* step through all map classes, and for each one that will be displayed
* keep a reference to its label size and text
@@ -201,19 +310,10 @@
}
return(NULL);
}
- maxwidth = MS_MAX(maxwidth, MS_NINT(rect.maxx - rect.minx));
cur->height = MS_MAX(MS_NINT(rect.maxy - rect.miny), map->legend.keysizey);
- size_y+=cur->height;
- nLegendItems++;
}
}
- /*
- ** Calculate the optimal image size for the legend
- */
- size_y += (2*VMARGIN) + ((nLegendItems-1)*map->legend.keyspacingy); /*initial vertical size*/
- size_x = (2*HMARGIN)+(maxwidth)+(map->legend.keyspacingx)+(map->legend.keysizex);
-
/* ensure we have an image format representing the options for the legend. */
msApplyOutputFormat(&format, map->outputformat, map->legend.transparent, map->legend.interlace, MS_NOOVERRIDE);
Modified: trunk/mapserver/mapserver.h
===================================================================
--- trunk/mapserver/mapserver.h 2007-12-14 18:39:18 UTC (rev 7173)
+++ trunk/mapserver/mapserver.h 2007-12-14 19:43:55 UTC (rev 7174)
@@ -1171,6 +1171,7 @@
#ifdef SWIG
%mutable;
#endif /* SWIG */
+
} layerObj;
/************************************************************************/
@@ -1649,6 +1650,7 @@
MS_DLL_EXPORT void freeImageCache(struct imageCacheObj *ic);
MS_DLL_EXPORT imageObj *msDrawLegend(mapObj *map, int scale_independent); /* in maplegend.c */
+MS_DLL_EXPORT int msLegendCalcSize(mapObj *map, int scale_independent, int *size_x, int *size_y, layerObj *lp);
MS_DLL_EXPORT int msEmbedLegend(mapObj *map, imageObj *img);
MS_DLL_EXPORT int msDrawLegendIcon(mapObj* map, layerObj* lp, classObj* myClass, int width, int height, imageObj *img, int dstX, int dstY);
MS_DLL_EXPORT imageObj *msCreateLegendIcon(mapObj* map, layerObj* lp, classObj* myClass, int width, int height);
Modified: trunk/mapserver/mapwms.c
===================================================================
--- trunk/mapserver/mapwms.c 2007-12-14 18:39:18 UTC (rev 7173)
+++ trunk/mapserver/mapwms.c 2007-12-14 19:43:55 UTC (rev 7174)
@@ -1286,64 +1286,60 @@
}
if (classnameset)
{
- if (map->legend.keysizex > 0)
- sprintf(width, "%d", map->legend.keysizex);
- else
- sprintf(width, "%d", 20);/* default; */
+ int size_x=0, size_y=0;
+ if (msLegendCalcSize(map, 1, &size_x, &size_y, lp) == MS_SUCCESS)
+ {
+ sprintf(width, "%d", size_x);
+ sprintf(height, "%d", size_y);
- if (map->legend.keysizey > 0)
- sprintf(height, "%d", map->legend.keysizey);
- else
- sprintf(height, "%d", 20);/* default; */
-
- legendurl = (char*)malloc(strlen(script_url_encoded)+200);
+ legendurl = (char*)malloc(strlen(script_url_encoded)+200);
#ifdef USE_GD_PNG
- mimetype = strdup("image/png");
+ mimetype = strdup("image/png");
#endif
#ifdef USE_GD_GIF
- if (!mimetype)
- mimetype = strdup("image/gif");
+ if (!mimetype)
+ mimetype = strdup("image/gif");
#endif
#ifdef USE_GD_JPEG
- if (!mimetype)
- mimetype = strdup("image/jpeg");
+ if (!mimetype)
+ mimetype = strdup("image/jpeg");
#endif
#ifdef USE_GD_WBMP
- if (!mimetype)
- mimetype = strdup("image/vnd.wap.wbmp");
+ if (!mimetype)
+ mimetype = strdup("image/vnd.wap.wbmp");
#endif
- if (!mimetype)
- mimetype = MS_IMAGE_MIME_TYPE(map->outputformat);
- mimetype = msEncodeHTMLEntities(mimetype);
+ if (!mimetype)
+ mimetype = MS_IMAGE_MIME_TYPE(map->outputformat);
+ mimetype = msEncodeHTMLEntities(mimetype);
- sprintf(legendurl, "%sversion=%s&service=WMS&request=GetLegendGraphic&layer=%s&format=%s",
- script_url_encoded,"1.1.1",msEncodeHTMLEntities(lp->name),
- mimetype);
+ sprintf(legendurl, "%sversion=%s&service=WMS&request=GetLegendGraphic&layer=%s&format=%s",
+ script_url_encoded,"1.1.1",msEncodeHTMLEntities(lp->name),
+ mimetype);
- msIO_fprintf(stdout, " <Style>\n");
- msIO_fprintf(stdout, " <Name>%s</Name>\n", pszStyle);
- msIO_fprintf(stdout, " <Title>%s</Title>\n", pszStyle);
+ msIO_fprintf(stdout, " <Style>\n");
+ msIO_fprintf(stdout, " <Name>%s</Name>\n", pszStyle);
+ msIO_fprintf(stdout, " <Title>%s</Title>\n", pszStyle);
- msOWSPrintURLType(stdout, NULL,
- "O", "ttt",
- OWS_NOERR, NULL,
- "LegendURL", NULL,
- " width=\"%s\"", " height=\"%s\"",
- ">\n <Format>%s</Format",
- "\n <OnlineResource "
- "xmlns:xlink=\"http://www.w3.org/1999/xlink\""
- " xlink:type=\"simple\" xlink:href=\"%s\"/>\n"
- " ",
- MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE,
- NULL, width, height, mimetype, legendurl, " ");
+ msOWSPrintURLType(stdout, NULL,
+ "O", "ttt",
+ OWS_NOERR, NULL,
+ "LegendURL", NULL,
+ " width=\"%s\"", " height=\"%s\"",
+ ">\n <Format>%s</Format",
+ "\n <OnlineResource "
+ "xmlns:xlink=\"http://www.w3.org/1999/xlink\""
+ " xlink:type=\"simple\" xlink:href=\"%s\"/>\n"
+ " ",
+ MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE, MS_FALSE,
+ NULL, width, height, mimetype, legendurl, " ");
- msIO_fprintf(stdout, " </Style>\n");
- msFree(legendurl);
- msFree(mimetype);
-
+ msIO_fprintf(stdout, " </Style>\n");
+ msFree(legendurl);
+ msFree(mimetype);
+ }
}
}
}
More information about the mapserver-commits
mailing list