[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&amp;service=WMS&amp;request=GetLegendGraphic&amp;layer=%s&amp;format=%s",  
-                               script_url_encoded,"1.1.1",msEncodeHTMLEntities(lp->name),
-                               mimetype);
+                           sprintf(legendurl, "%sversion=%s&amp;service=WMS&amp;request=GetLegendGraphic&amp;layer=%s&amp;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