[mapserver-commits] r13176 - sandbox/tb-labels

svn at osgeo.org svn at osgeo.org
Mon Feb 27 14:07:16 EST 2012


Author: tbonfort
Date: 2012-02-27 11:07:16 -0800 (Mon, 27 Feb 2012)
New Revision: 13176

Modified:
   sandbox/tb-labels/mapdraw.c
   sandbox/tb-labels/mapfile.c
   sandbox/tb-labels/maplabel.c
   sandbox/tb-labels/mapprimitive.c
   sandbox/tb-labels/mapserver.h
   sandbox/tb-labels/maputil.c
Log:
refactor msTestLabelCacheCollisions

use NULL labelObj->annotext for empty text

set labelcache_edge_buffer in labelcacheObj->gutter

add a boundingbox test to speed up labelInImage

limit memory allocations when copying shapeObjs in the labelcache phase

dont't test for text bounding boxes if the current label has no characters




Modified: sandbox/tb-labels/mapdraw.c
===================================================================
--- sandbox/tb-labels/mapdraw.c	2012-02-27 14:40:03 UTC (rev 13175)
+++ sandbox/tb-labels/mapdraw.c	2012-02-27 19:07:16 UTC (rev 13176)
@@ -1862,14 +1862,13 @@
 
     for(j=0; j<shape->numlines;j++) {
       for(i=0; i<shape->line[j].numpoints;i++) {
-	point = &(shape->line[j].point[i]);
+         point = &(shape->line[j].point[i]);
+         if(layer->transform == MS_TRUE) {
+            if(!msPointInRect(point, &map->extent)) continue; /* next point */
+            msTransformPoint(point, &map->extent, map->cellsize, image);
+         } else
+            msOffsetPointRelativeTo(point, layer);
 
-	if(layer->transform == MS_TRUE) {
-	  if(!msPointInRect(point, &map->extent)) continue; /* next point */
-          msTransformPoint(point, &map->extent, map->cellsize, image);
-	} else
-          msOffsetPointRelativeTo(point, layer);
-
         for(s=0; s<layer->class[c]->numstyles; s++) {
           if(msScaleInBounds(map->scaledenom, layer->class[c]->styles[s]->minscaledenom, layer->class[c]->styles[s]->maxscaledenom))
             msDrawMarkerSymbol(&map->symbolset, image, point, layer->class[c]->styles[s], layer->scalefactor);
@@ -1877,7 +1876,7 @@
 
         if(layer->labelcache) {
           if(msAddLabelGroup(map, layer->index, c, shape, point, -1) != MS_SUCCESS) return (MS_FAILURE);
-	} else {
+        } else {
           for(l=0; l<layer->class[c]->numlabels; l++)
             msDrawLabel(map, image, *point, layer->class[c]->labels[l]->annotext, layer->class[c]->labels[l], layer->scalefactor);
         }
@@ -2381,8 +2380,7 @@
       cachePtr->leaderbbox->maxy = cachePtr->leaderline->point[0].y;
       cachePtr->leaderbbox->miny = cachePtr->point.y;
    }
-   cachePtr->status = msTestLabelCacheCollisions(&(map->labelcache), &(cachePtr->labels[0]), image->width, image->height, 0 /* todo map_edge_buffer */,
-         cachePtr, priority, -label_idx, 0, 0);
+   cachePtr->status = msTestLabelCacheCollisions(map, cachePtr, 0,0,0);
    if(cachePtr->status) {
       int ll;
       for(ll=0;ll<cachePtr->numlabels;ll++) {
@@ -2395,14 +2393,12 @@
 int msDrawOffsettedLabels(imageObj *image, mapObj *map, int priority) {
    assert(MS_RENDERER_PLUGIN(image->format));
    int retval = MS_SUCCESS;
-   int l,map_edge_buffer;
+   int l;
+   labelCacheObj *labelcache = &(map->labelcache);
    labelCacheSlotObj *cacheslot;
    labelCacheMemberObj *cachePtr;
-   cacheslot = &(map->labelcache.slots[priority]);
+   cacheslot = &(labelcache->slots[priority]);
    char *value;
-   if((value = msLookupHashTable(&(map->web.metadata), "labelcache_map_edge_buffer")) != NULL) {
-      map_edge_buffer = atoi(value);
-   }
    for(l=cacheslot->numlabels-1; l>=0; l--) {
       cachePtr = &(cacheslot->labels[l]); /* point to right spot in the label cache */
       if(cachePtr->status == MS_FALSE && !cachePtr->labelpath) {
@@ -2410,10 +2406,10 @@
          classObj *classPtr = (GET_CLASS(map,cachePtr->layerindex,cachePtr->classindex));
          layerObj *layerPtr = (GET_LAYER(map,cachePtr->layerindex));
          if(classPtr->leader.maxdistance) { /* only test labels that can be offsetted */
-            if(cachePtr->point.x <= -map_edge_buffer ||
-                  cachePtr->point.y <= -map_edge_buffer ||
-                  cachePtr->point.x >= image->width + map_edge_buffer ||
-                  cachePtr->point.y >= image->height + map_edge_buffer) {
+            if(cachePtr->point.x < labelcache->gutter ||
+                  cachePtr->point.y < labelcache->gutter ||
+                  cachePtr->point.x >= image->width - labelcache->gutter ||
+                  cachePtr->point.y >= image->height - labelcache->gutter) {
                /* don't look for leaders if point is in edge buffer as the leader line would end up chopped off */
                continue;
             }
@@ -2437,8 +2433,13 @@
 #define y0 (cachePtr->leaderline->point[0].y)
 #define gridstepsc (classPtr->leader.gridstep)
 
-#define otest(ox,oy) offsetAndTest(image,map,cachePtr,(ox),(oy),priority,l,&origPoly); \
-               if(cachePtr->status) break;
+#define otest(ox,oy) if((x0+(ox)) >= labelcache->gutter &&\
+                  (y0+(oy)) >= labelcache->gutter &&\
+                  (x0+(ox)) < image->width + labelcache->gutter &&\
+                  (y0+(oy)) < image->height + labelcache->gutter) {\
+                     offsetAndTest(image,map,cachePtr,(ox),(oy),priority,l,&origPoly); \
+                     if(cachePtr->status) break;\
+                  }
 
             /* loop through possible offsetted positions */
             for(i=1;i<=steps;i++) {
@@ -2562,6 +2563,7 @@
                         }
                      }
                   }
+                  if(labelPtr->annotext)
                   msDrawText(image, labelPtr->annopoint, labelPtr->annotext, labelPtr, &(map->fontset), layerPtr->scalefactor); /* actually draw the label */
                }
 
@@ -2609,6 +2611,42 @@
 
 } 
 
+/* add "to"'s geometry to "from", without unnecessary allocations.
+ * the ownership of "from"'s geometry is transfered to "to"
+ */
+static void transferLabelShape(shapeObj *from, shapeObj *to) {
+  int i,copybounds=0;
+
+  if(!from || !to) return;
+
+  if(to->numlines <= 0) copybounds=1;
+  if( to->numlines <= 0 ) {
+      to->line = (lineObj *) msSmallMalloc(from->numlines * sizeof(lineObj));
+      to->numlines = 0;
+  }
+  else {
+      to->line = (lineObj *) msSmallRealloc(to->line, (to->numlines+from->numlines)*sizeof(lineObj));
+  }
+  for(i=0; i<from->numlines; i++) {
+     to->line[to->numlines].point = from->line[i].point;
+     to->line[to->numlines].numpoints = from->line[i].numpoints;
+     to->numlines++;
+     from->line[i].point = NULL;
+     from->line[i].numpoints = 0;
+  }
+  if(copybounds) {
+     to->bounds.minx = from->bounds.minx;
+     to->bounds.miny = from->bounds.miny;
+     to->bounds.maxx = from->bounds.maxx;
+     to->bounds.maxy = from->bounds.maxy;
+  } else {
+     to->bounds.minx = MS_MIN(to->bounds.minx,from->bounds.minx);
+     to->bounds.miny = MS_MIN(to->bounds.miny,from->bounds.miny);
+     to->bounds.maxx = MS_MAX(to->bounds.maxx,from->bounds.maxx);
+     to->bounds.maxy = MS_MAX(to->bounds.maxy,from->bounds.maxy);
+  }
+}
+
 int msDrawLabelCache(imageObj *image, mapObj *map)
 {
   int nReturnVal = MS_SUCCESS;
@@ -2618,6 +2656,8 @@
       int i, l, ll, priority;
       rectObj r;
 
+      shapeObj poly; /* hold label polygon for one label, cachePtr->poly holds label polygon for the whole group */
+      msInitShape(&poly);
       markerCacheMemberObj *markerPtr=NULL; /* for santity */
       labelCacheMemberObj *cachePtr=NULL;
       layerObj *layerPtr=NULL;
@@ -2644,8 +2684,8 @@
        * map image where labels can't fall
        */
       if((value = msLookupHashTable(&(map->web.metadata), "labelcache_map_edge_buffer")) != NULL) {
-        map_edge_buffer = MS_ABS(atoi(value));
-        if(map->debug) msDebug("msDrawLabelCache(): labelcache_map_edge_buffer = %d\n", map_edge_buffer);
+        map->labelcache.gutter = MS_ABS(atoi(value));
+        if(map->debug) msDebug("msDrawLabelCache(): labelcache_map_edge_buffer = %d\n", map->labelcache.gutter);
       }
 
       for(priority=MS_MAX_LABEL_PRIORITY-1; priority>=0; priority--) {
@@ -2661,11 +2701,12 @@
           layerPtr = (GET_LAYER(map, cachePtr->layerindex)); /* set a couple of other pointers, avoids nasty references */
           classPtr = (GET_CLASS(map, cachePtr->layerindex, cachePtr->classindex));
 
+          /* TODO: classes with a labelpath do not respect multi label rendering */
           if(cachePtr->labelpath) { /* path-based label */
             labelPtr = &(cachePtr->labels[0]);
 
             if(labelPtr->status != MS_ON) continue; /* skip this label */
-            if(!labelPtr->annotext || strlen(labelPtr->annotext) == 0) continue; /* skip this label, nothing to with curved labels when there is nothing to draw */
+            if(!labelPtr->annotext) continue; /* skip this label, nothing to with curved labels when there is nothing to draw */
 
             /* path-following labels *must* be TRUETYPE */
             size = labelPtr->size * layerPtr->scalefactor;
@@ -2673,49 +2714,25 @@
             size = MS_MIN(size, labelPtr->maxsize*image->resolutionfactor);
             scalefactor = size / labelPtr->size;
 
-            if(msGetLabelSize(map, labelPtr, labelPtr->annotext, size, &r, NULL) != MS_SUCCESS)
-              return MS_FAILURE;
-        
-            /* adjust the baseline (see #1449) (RFC 77 TODO - is this relevant for path following labels?) */
-            if(labelPtr->type == MS_TRUETYPE) {
-              int nNewlines = msCountChars(labelPtr->annotext,'\n');
-              if(!nNewlines) {
-                labelPtr->offsety += ((((r.miny + r.maxy) + size) / 2.0)/scalefactor);
-                labelPtr->offsetx += ((r.minx / 2)/scalefactor);
-              } else {
-                rectObj rect2; /* bbox of first line only */
-                char *firstLine = msGetFirstLine(labelPtr->annotext);
-                msGetLabelSize(map, labelPtr, firstLine, size, &rect2, NULL);
-                labelPtr->offsety += ((((rect2.miny+rect2.maxy) + size) / 2))/scalefactor;
-                labelPtr->offsetx += ((rect2.minx / 2))/scalefactor;
-                free(firstLine);
-              }
-            }
-   
-            label_offset_x = labelPtr->offsetx*scalefactor;
-            label_offset_y = labelPtr->offsety*scalefactor;
             label_buffer = (labelPtr->buffer*image->resolutionfactor);
             label_mindistance = (labelPtr->mindistance*image->resolutionfactor);
 
             /* copy the bounds into the cache's polygon */
-            msCopyShape(&(cachePtr->labelpath->bounds), cachePtr->poly);
-            msFreeShape(&(cachePtr->labelpath->bounds));
+            transferLabelShape(&(cachePtr->labelpath->bounds), cachePtr->poly);
    
             /* compare against image bounds, rendered labels and markers (sets cachePtr->status), if FORCE=TRUE then skip it */
             cachePtr->status = MS_TRUE;
             if(!labelPtr->force)
-              cachePtr->status = msTestLabelCacheCollisions(&(map->labelcache), labelPtr, image->width, image->height, (map_edge_buffer-label_buffer), cachePtr, priority, l, label_mindistance, (r.maxx-r.minx));             
-
+              cachePtr->status = msTestLabelCacheCollisions(map,cachePtr,label_mindistance,priority,l);
+            msFreeShape(&(cachePtr->labelpath->bounds));
+            
             if(!cachePtr->status)
               continue;
 
             msDrawTextLine(image, labelPtr->annotext, labelPtr, cachePtr->labelpath, &(map->fontset), layerPtr->scalefactor); /* Draw the curved label */
 
           } else { /* point-based label */
-            shapeObj *poly=NULL; /* hold label polygon for one label, cachePtr->poly holds label polygon for the whole group */
             shapeObj *tmppoly;
-            poly = (shapeObj *) msSmallMalloc(sizeof(shapeObj));
-            msInitShape(poly);
 
             marker_offset_x = marker_offset_y = 0; /* assume no marker */
             marker_width = marker_height = 0;
@@ -2747,27 +2764,24 @@
             */
             cachePtr->status = MS_OFF; /* assume this cache element *can't* be placed */
             for(ll=0; ll<cachePtr->numlabels; ll++) { /* RFC 77 TODO: Still may want to step through backwards... */
-              int drawLabelText = MS_TRUE;
-              msFreeShape(poly);
+              msFreeShape(&poly);
               labelPtr = &(cachePtr->labels[ll]);
               labelPtr->status = MS_OFF;
 
-              if(!labelPtr->annotext || strlen(labelPtr->annotext) == 0) {
+              if(!labelPtr->annotext) {
                  int s;
                  for(s=0;s<labelPtr->numstyles;s++) {
                     if(labelPtr->styles[s]->_geomtransform.type == MS_GEOMTRANSFORM_LABELPOINT)
                        break;
                  }
                  if(s == labelPtr->numstyles) {
-                  labelPtr->status = MS_ON; /* TODO TBT, check for marker only */
-                  continue; /* skip this label (RFC 77 TODO: ok to bail here?) */
+                  /* no label text, and no markers to render, skip this label */
+                  labelPtr->status = MS_ON; 
+                  continue;
                  }
-              } else {
-                 drawLabelText = MS_TRUE;
               }
-                 drawLabelText = MS_TRUE;
 
-              if(drawLabelText) {
+              if(labelPtr->annotext) {
                  /* compute label size */
                  if(labelPtr->type == MS_TRUETYPE) {
                     size = labelPtr->size * layerPtr->scalefactor;
@@ -2846,7 +2860,7 @@
                 label_marker_rect.maxy = (cachePtr->point.y + label_marker_offset_y + t_marker_offset_y ) + labelPtr->buffer; // marker_rect.miny + (marker_height-1) + labelPtr->buffer; 
               }
               
-              if(labelPtr->position == MS_AUTO) {
+              if(labelPtr->annotext && labelPtr->position == MS_AUTO) {
                 int positions[MS_POSITIONS_LENGTH], npositions=0;
    
                 /*
@@ -2865,28 +2879,28 @@
                 }
    
                 if(label_marker_width > 0 && label_marker_height > 0)
-                  msRectToPolygon(label_marker_rect, poly); /* save marker bounding polygon */
+                  msRectToPolygon(label_marker_rect, &poly); /* save marker bounding polygon */
 
                 for(i=0; i<npositions; i++) {
                   // RFC 77 TODO: take label_marker_offset_x/y into account
-                  labelPtr->annopoint = get_metrics(&(cachePtr->point), positions[i], r, (MS_MAX(label_marker_offset_x, marker_offset_x) + label_offset_x), (MS_MAX(label_marker_offset_y, marker_offset_y) + label_offset_y), labelPtr->angle, label_buffer, poly);
+                  labelPtr->annopoint = get_metrics(&(cachePtr->point), positions[i], r, (MS_MAX(label_marker_offset_x, marker_offset_x) + label_offset_x), (MS_MAX(label_marker_offset_y, marker_offset_y) + label_offset_y), labelPtr->angle, label_buffer, &poly);
 
                   if(labelPtr->force == MS_OFF) {
                      /* check for collisions inside the label group */
 
                      /* if cachePtr->status we're still working on the first valid label with a valid status value */
                      /* was: if((ll != 0) && intersectLabelPolygons(poly, cachePtr->poly) == MS_TRUE) */
-                     if(ll && intersectLabelPolygons(poly, cachePtr->poly) == MS_TRUE) {                  
+                     if(ll && intersectLabelPolygons(&poly, cachePtr->poly) == MS_TRUE) {                  
                         /* there was a self intersection, remove the label bbox added by get_metrics ? */
-                        msShapeDeleteLine(poly, poly->numlines-1);
-                        msComputeBounds(poly);
+                        msShapeDeleteLine(&poly, poly.numlines-1);
+                        msComputeBounds(&poly);
                         continue; /* next position, labelPtr->status is left to MS_OFF */
                      }
                   }
 
                   tmppoly = cachePtr->poly;
-                  cachePtr->poly = poly;
-                  labelPtr->status = msTestLabelCacheCollisions(&(map->labelcache), labelPtr, image->width, image->height, (map_edge_buffer-label_buffer), cachePtr, priority, l, label_mindistance, (r.maxx-r.minx));
+                  cachePtr->poly = &poly;
+                  labelPtr->status = msTestLabelCacheCollisions(map, cachePtr, label_mindistance,priority, l);
                   cachePtr->poly = tmppoly;
 
                   /* found a suitable place for this label */
@@ -2898,8 +2912,8 @@
                     /* TB->SDL: this block seemed wrong, shouldn't the marker be deleted only once *all* auto positions have been tested? */
 
                     /* there was a collision with a previous label, remove current label bbox before trying another position */
-                    msShapeDeleteLine(poly, poly->numlines-1);
-                    msComputeBounds(poly);
+                    msShapeDeleteLine(&poly, poly.numlines-1);
+                    msComputeBounds(&poly);
                   }
                 } /* next position */
 
@@ -2910,35 +2924,37 @@
 
               } else { /* explicit position */
 
-                if(labelPtr->position == MS_CC) { /* don't need the marker_offset */
-                  labelPtr->annopoint = get_metrics(&(cachePtr->point), labelPtr->position, r, label_offset_x, label_offset_y, labelPtr->angle, label_buffer, poly);
-                  if(labelPtr->annopoly) get_metrics_line(&(cachePtr->point), labelPtr->position, r, label_offset_x, label_offset_y, labelPtr->angle, 1, labelPtr->annopoly->line);
-                } else {
-                  labelPtr->annopoint = get_metrics(&(cachePtr->point), labelPtr->position, r, (MS_MAX(label_marker_offset_x, marker_offset_x) + label_offset_x), (MS_MAX(label_marker_offset_y, marker_offset_y) + label_offset_y), labelPtr->angle, label_buffer, poly);
-                  if(labelPtr->annopoly) get_metrics_line(&(cachePtr->point), labelPtr->position, r, (MS_MAX(label_marker_offset_x, marker_offset_x) + label_offset_x), (MS_MAX(label_marker_offset_y, marker_offset_y) + label_offset_y), labelPtr->angle, 1, labelPtr->annopoly->line);
+                if(labelPtr->annotext) {
+                   if(labelPtr->position == MS_CC) { /* don't need the marker_offset */
+                      labelPtr->annopoint = get_metrics(&(cachePtr->point), labelPtr->position, r, label_offset_x, label_offset_y, labelPtr->angle, label_buffer, &poly);
+                      if(labelPtr->annopoly) get_metrics_line(&(cachePtr->point), labelPtr->position, r, label_offset_x, label_offset_y, labelPtr->angle, 1, labelPtr->annopoly->line);
+                   } else {
+                      labelPtr->annopoint = get_metrics(&(cachePtr->point), labelPtr->position, r, (MS_MAX(label_marker_offset_x, marker_offset_x) + label_offset_x), (MS_MAX(label_marker_offset_y, marker_offset_y) + label_offset_y), labelPtr->angle, label_buffer, &poly);
+                      if(labelPtr->annopoly) get_metrics_line(&(cachePtr->point), labelPtr->position, r, (MS_MAX(label_marker_offset_x, marker_offset_x) + label_offset_x), (MS_MAX(label_marker_offset_y, marker_offset_y) + label_offset_y), labelPtr->angle, 1, labelPtr->annopoly->line);
+                   }
                 }
 
                 if(label_marker_width > 0 && label_marker_height > 0)
-                  msRectToPolygon(label_marker_rect, poly); /* save marker bounding polygon, part of overlap tests */
+                  msRectToPolygon(label_marker_rect, &poly); /* save marker bounding polygon, part of overlap tests */
 
                 if(labelPtr->force == MS_TRUE) {
-                  msCopyShape(poly, cachePtr->poly);
+                  transferLabelShape(&poly, cachePtr->poly);
                   labelPtr->status = MS_TRUE;
                 } else {
                   if(labelPtr->force == MS_OFF) {
                     /* check for collisions inside the label group unless the label is FORCE GROUP */
 
                     /* if cachePtr->status we're still working on the first valid label with a valid status value */
-                    if(ll && intersectLabelPolygons(poly, cachePtr->poly) == MS_TRUE) {
+                    if(ll && intersectLabelPolygons(&poly, cachePtr->poly) == MS_TRUE) {
                       break; /* collision within the group */
                     }
                   }
                   tmppoly = cachePtr->poly;
-                  cachePtr->poly = poly;
+                  cachePtr->poly = &poly;
                   /* TODO: in case we have leader lines and multiple labels, there's no use in testing for labelcache collisions
                    * once a first collision has been found. we only need to know that the label group has collided, and the 
                    * poly of the whole label group: if(label_group) testLabelCacheCollisions */
-                  labelPtr->status = msTestLabelCacheCollisions(&(map->labelcache), labelPtr, image->width, image->height, (map_edge_buffer-label_buffer), cachePtr, priority, l, label_mindistance, (r.maxx-r.minx));
+                  labelPtr->status = msTestLabelCacheCollisions(map, cachePtr, label_mindistance, priority, l);
                   cachePtr->poly = tmppoly;
                 }
               } /* end POSITION AUTO vs Fixed POSITION */
@@ -2947,7 +2963,7 @@
                 break; /* no point looking at more labels, unless their is a leader defined, in which
                 case we still want to compute the full cachePtr->poly to be used for offset tests */
               } else {
-                msCopyShape(poly, cachePtr->poly);
+                transferLabelShape(&poly, cachePtr->poly);
               }
             } /* next label in the group */
             
@@ -2986,8 +3002,8 @@
                   }
                 }
               }
-   
-              msDrawText(image, labelPtr->annopoint, labelPtr->annotext, labelPtr, &(map->fontset), layerPtr->scalefactor); /* actually draw the label */
+              if(labelPtr->annotext) 
+               msDrawText(image, labelPtr->annopoint, labelPtr->annotext, labelPtr, &(map->fontset), layerPtr->scalefactor); /* actually draw the label */
             }
 
            /* 
@@ -3006,10 +3022,9 @@
             msDrawLineSymbol(&map->symbolset, image, cachePtr->poly, &tstyle, layerPtr->scalefactor);
             */
 
-            msFreeShape(poly); /* clean up label polygon */
-            msFree(poly);
           } /* end else */
         } /* next label(group) from cacheslot */
+        msFreeShape(&poly); /* clean up label polygon */
         msDrawOffsettedLabels(image, map, priority);
       } /* next priority */
 

Modified: sandbox/tb-labels/mapfile.c
===================================================================
--- sandbox/tb-labels/mapfile.c	2012-02-27 14:40:03 UTC (rev 13175)
+++ sandbox/tb-labels/mapfile.c	2012-02-27 19:07:16 UTC (rev 13176)
@@ -1680,6 +1680,7 @@
    for(i=0;i<leader->numstyles;i++) {
       msFree(leader->styles[i]);
    }
+   msFree(leader->styles);
 
    return MS_SUCCESS;
 }
@@ -5445,6 +5446,11 @@
 
       for(j=0;j<cacheslot->labels[i].numstyles; j++) freeStyle(&(cacheslot->labels[i].styles[j]));
       msFree(cacheslot->labels[i].styles);
+      if(cacheslot->labels[i].leaderline) {
+         msFree(cacheslot->labels[i].leaderline->point);
+         msFree(cacheslot->labels[i].leaderline);
+         msFree(cacheslot->labels[i].leaderbbox);
+      }
     }
   }
   msFree(cacheslot->labels);
@@ -5508,6 +5514,7 @@
           return MS_FAILURE;
   }
   cache->numlabels = 0;
+  cache->gutter = 0;
 
   return MS_SUCCESS;
 }

Modified: sandbox/tb-labels/maplabel.c
===================================================================
--- sandbox/tb-labels/maplabel.c	2012-02-27 14:40:03 UTC (rev 13175)
+++ sandbox/tb-labels/maplabel.c	2012-02-27 19:07:16 UTC (rev 13176)
@@ -362,8 +362,6 @@
 
   /* store the label point and set the labelpath to NULL */
   cachePtr->point = *point; /* the actual label point */
-  cachePtr->point.x = MS_NINT(cachePtr->point.x);
-  cachePtr->point.y = MS_NINT(cachePtr->point.y);
   cachePtr->labelpath = NULL;
   cachePtr->leaderline = NULL;
   cachePtr->leaderbbox = NULL;
@@ -382,8 +380,8 @@
     cachePtr->styles = (styleObj *) msSmallMalloc(sizeof(styleObj)*classPtr->numstyles);
     if (classPtr->numstyles > 0) {
       for(i=0; i<classPtr->numstyles; i++) {
-	initStyle(&(cachePtr->styles[i]));
-	msCopyStyle(&(cachePtr->styles[i]), classPtr->styles[i]);
+         initStyle(&(cachePtr->styles[i]));
+         msCopyStyle(&(cachePtr->styles[i]), classPtr->styles[i]);
       }
     }
   }
@@ -544,8 +542,6 @@
   /* Store the label point or the label path (Bug #1620) */
   if ( point ) {
     cachePtr->point = *point; /* the actual label point */
-    cachePtr->point.x = MS_NINT(cachePtr->point.x);
-    cachePtr->point.y = MS_NINT(cachePtr->point.y);
     cachePtr->labelpath = NULL;
   } else if ( labelpath ) {
     int i;
@@ -640,7 +636,15 @@
 */ 
 static int labelInImage(int width, int height, shapeObj *lpoly, int gutter) 
 { 
-  int i,j; 
+  int i,j;
+
+  /* do a bbox test first */
+  if(lpoly->bounds.minx >= gutter &&
+        lpoly->bounds.miny >= gutter &&
+        lpoly->bounds.maxx < width-gutter &&
+        lpoly->bounds.maxy < height-gutter) {
+     return MS_TRUE;
+  }
 	 
   for(i=0; i<lpoly->numlines; i++) { 
     for(j=1; j<lpoly->line[i].numpoints; j++) { 
@@ -661,24 +665,37 @@
 ** or collides with a marker.
 **
 ** This function is used by the various msDrawLabelCacheXX() implementations.
-*/
+
 int msTestLabelCacheCollisions(labelCacheObj *labelcache, labelObj *labelPtr, 
                                 int mapwidth, int mapheight, int buffer,
                                 labelCacheMemberObj *cachePtr, int current_priority, 
-                                int current_label, int mindistance, double label_size)
-{
+                                int current_label, int mindistance, double label_size);
+*/
+
+int msTestLabelCacheCollisions(mapObj *map, labelCacheMemberObj *cachePtr, int mindistance, 
+      int current_priority, int current_label) {
+   labelCacheObj *labelcache = &(map->labelcache);
   int i, p, ll, pp;
+  double label_width;
   labelCacheMemberObj *curCachePtr=NULL; 
 
-  /* Check against image bounds first 
-  ** Pass mapwidth=-1 to skip this test
+  /*
+   * Check against image bounds first 
    */
-  if(!labelPtr->partials && mapwidth > 0 && mapheight > 0) {
-    if(labelInImage(mapwidth, mapheight, cachePtr->poly, buffer) == MS_FALSE) {
+  if(cachePtr->labels[0].partials) {
+    if(labelInImage(map->width, map->height, cachePtr->poly, labelcache->gutter) == MS_FALSE) {
       return MS_FALSE;
     }
   }
 
+  /* compute start index of first label to test: only test against rendered labels */
+  if(current_label>=0) {
+   i = current_label+1;
+  } else {
+   i = 0;
+   current_label = -current_label;
+  }
+
   /* Compare against all rendered markers from this priority level and higher.
   ** Labels can overlap their own marker and markers from lower priority levels
   */
@@ -686,47 +703,42 @@
     labelCacheSlotObj *markerslot;
     markerslot = &(labelcache->slots[p]);
 
-    for ( i = 0; i < markerslot->nummarkers; i++ ) {
-      if ( !(p == current_priority && (current_label == markerslot->markers[i].id || -current_label == markerslot->markers[i].id) ) ) {  /* labels can overlap their own marker */
-        if ( intersectLabelPolygons(markerslot->markers[i].poly, cachePtr->poly ) == MS_TRUE ) {
+    for ( ll = 0; ll < markerslot->nummarkers; ll++ ) {
+      if ( !(p == current_priority && current_label == markerslot->markers[ll].id ) ) {  /* labels can overlap their own marker */
+        if ( intersectLabelPolygons(markerslot->markers[ll].poly, cachePtr->poly ) == MS_TRUE ) {
           return MS_FALSE;
         }
       }
     }
   }
 
-  /* compare against rendered labels */
-  if(current_label>=0) {
-   i = current_label+1;
-  } else {
-   i = 0;
-  }
+  if(mindistance > 0)
+     label_width = cachePtr->poly->bounds.maxx - cachePtr->poly->bounds.minx;
 
   for(p=current_priority; p<MS_MAX_LABEL_PRIORITY; p++) {
     labelCacheSlotObj *cacheslot;
     cacheslot = &(labelcache->slots[p]);
 
     for(  ; i < cacheslot->numlabels; i++) {
-       if(p == current_priority && (i+current_label)==0) {
-          continue;
-          /* skip testing against ourself */
-       }
       curCachePtr = &(cacheslot->labels[i]);
 
       if(curCachePtr->status == MS_TRUE) { /* compare bounding polygons and check for duplicates */
 
+         /* skip testing against ourself */
+         assert(p!=current_priority || i != current_label);
+
         /* 
-	** Note 1: We add the label_size to the mindistance value when comparing because we do want the mindistance 
+        ** Note 1: We add the label_size to the mindistance value when comparing because we do want the mindistance 
         ** value between the labels and not only from point to point. 
         **
         ** Note 2: We only check the first label (could be multiples (RFC 77)) since that is *by far* the most common
         ** use case. Could change in the future but it's not worth the overhead at this point.
         */
-        if(label_size > 0 && (mindistance != -1) && 
+        if(mindistance >0  && 
           (cachePtr->layerindex == curCachePtr->layerindex) && 
           (cachePtr->classindex == curCachePtr->classindex) && 
           (strcmp(cachePtr->labels[0].annotext, curCachePtr->labels[0].annotext) == 0) &&
-          (msDistancePointToPoint(&(cachePtr->point), &(curCachePtr->point)) <= (mindistance + label_size))) { /* label is a duplicate */
+          (msDistancePointToPoint(&(cachePtr->point), &(curCachePtr->point)) <= (mindistance + label_width))) { /* label is a duplicate */
           return MS_FALSE;
         }
 

Modified: sandbox/tb-labels/mapprimitive.c
===================================================================
--- sandbox/tb-labels/mapprimitive.c	2012-02-27 14:40:03 UTC (rev 13175)
+++ sandbox/tb-labels/mapprimitive.c	2012-02-27 19:07:16 UTC (rev 13176)
@@ -1762,7 +1762,9 @@
   segment_index = max_line_index = 0;
   total_length = max_line_length = 0.0;
 
+  if(!string) return NULL;
 
+
   labelpaths = (labelPathObj **) msSmallMalloc(sizeof(labelPathObj *) * labelpaths_size);
   (*regular_lines) = (int *) msSmallMalloc(sizeof(int) * regular_lines_size);
 

Modified: sandbox/tb-labels/mapserver.h
===================================================================
--- sandbox/tb-labels/mapserver.h	2012-02-27 14:40:03 UTC (rev 13175)
+++ sandbox/tb-labels/mapserver.h	2012-02-27 19:07:16 UTC (rev 13176)
@@ -1151,6 +1151,7 @@
      * The slots[].numlabels are the real values to rely on.
      */
     int numlabels;
+    int gutter; /* space in pixels around the image where labels cannot be placed */
 } labelCacheObj;
 
 /************************************************************************/
@@ -2036,7 +2037,7 @@
 
 MS_DLL_EXPORT int msAddLabel(mapObj *map, labelObj *label, int layerindex, int classindex, shapeObj *shape, pointObj *point, labelPathObj *labelpath, double featuresize);
 MS_DLL_EXPORT int msAddLabelGroup(mapObj *map, int layerindex, int classindex, shapeObj *shape, pointObj *point, double featuresize);
-MS_DLL_EXPORT int __attribute__((warn_unused_result)) msTestLabelCacheCollisions(labelCacheObj *labelcache, labelObj *labelPtr, int mapwidth, int mapheight, int buffer, labelCacheMemberObj *cachePtr, int current_priority, int current_label, int mindistance, double label_size);
+MS_DLL_EXPORT int msTestLabelCacheCollisions(mapObj *map, labelCacheMemberObj *cachePtr, int mindistance, int current_priority, int current_label);
 MS_DLL_EXPORT labelCacheMemberObj *msGetLabelCacheMember(labelCacheObj *labelcache, int i);
 
 MS_DLL_EXPORT gdFontPtr msGetBitmapFont(int size);

Modified: sandbox/tb-labels/maputil.c
===================================================================
--- sandbox/tb-labels/maputil.c	2012-02-27 14:40:03 UTC (rev 13175)
+++ sandbox/tb-labels/maputil.c	2012-02-27 19:07:16 UTC (rev 13176)
@@ -614,6 +614,10 @@
           node = nextNode;
         }
       }
+      if(!strlen(result)) {
+         msFree(result);
+         result = NULL;
+      }
     }
     break;
   case(MS_EXPRESSION):
@@ -639,7 +643,10 @@
   default:
     break;
   }
-
+  if(result && !strlen(result)) {
+     msFree(result);
+     result = NULL;
+  }
   return result;
 }
 
@@ -676,10 +683,10 @@
     } else if(layer->class[i]->text.string) {
       layer->class[i]->labels[j]->annotext = evalTextExpression(&(layer->class[i]->text), shape);
     } else {
-      if (shape->values && layer->labelitemindex >= 0)
+      if (shape->values && layer->labelitemindex >= 0 && shape->values[layer->labelitemindex] && strlen(shape->values[layer->labelitemindex]) )
         layer->class[i]->labels[j]->annotext = msStrdup(shape->values[layer->labelitemindex]);
-      else
-	layer->class[i]->labels[j]->annotext = msStrdup(shape->text); /* last resort but common with iniline features */
+      else if(shape->text)
+        layer->class[i]->labels[j]->annotext = msStrdup(shape->text); /* last resort but common with iniline features */
     }
   }
 



More information about the mapserver-commits mailing list