[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