[mapserver-commits] r9884 - trunk/mapserver

svn at osgeo.org svn at osgeo.org
Tue Feb 23 12:42:59 EST 2010


Author: sdlime
Date: 2010-02-23 12:42:58 -0500 (Tue, 23 Feb 2010)
New Revision: 9884

Modified:
   trunk/mapserver/mapgd2.c
Log:
GD2 polygon fill works...

Modified: trunk/mapserver/mapgd2.c
===================================================================
--- trunk/mapserver/mapgd2.c	2010-02-23 17:26:42 UTC (rev 9883)
+++ trunk/mapserver/mapgd2.c	2010-02-23 17:42:58 UTC (rev 9884)
@@ -49,6 +49,8 @@
   imageObj *img = NULL;
   gdImagePtr ip;
 
+  fprintf(stderr, "in createImageGD() w=%d h=%d\n", width, height);
+
   img = (imageObj *) calloc(1, sizeof (imageObj));
 
   /* we're only doing PC256 for the moment */
@@ -63,6 +65,8 @@
 {
   gdImagePtr ip;
 
+  fprintf(stderr, "in saveImageGD()\n");
+
   if(!img || !fp) return NULL;
   ip = (gdImagePtr) img->img.plugin;
 
@@ -92,10 +96,196 @@
 /*
 ** GD driver-specific rendering functions.
 */
+#define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
+
+static void setPen(gdImagePtr ip, colorObj *c)
+{
+  if(MS_VALID_COLOR(*c))
+    c->pen = gdImageColorResolve(ip, c->red, c->green, c->blue);
+  else
+    c->pen = -1;
+}
+
+static void imageScanline(gdImagePtr im, int x1, int x2, int y, int c)
+{
+  int x;
+
+  /* TO DO: This fix (adding if/then) was to address circumstances in the polygon fill code */
+  /* where x2 < x1. There may be something wrong in that code, but at any rate this is safer. */
+
+  if(x1 < x2)
+    for(x=x1; x<=x2; x++) gdImageSetPixel(im, x, y, c);
+  else
+    for(x=x2; x<=x1; x++) gdImageSetPixel(im, x, y, c);
+}
+
+/*
+** Polygon fill. Based on "Concave Polygon Scan Conversion" by Paul
+** Heckbert from "Graphics Gems", Academic Press, 1990 
+*/
+static void imageFilledPolygon(gdImagePtr im, shapeObj *p, int c, int offsetx, int offsety)
+{
+  typedef struct {     /* a polygon edge */
+    double x;          /* x coordinate of edge's intersection with current scanline */
+    double dx;         /* change in x with respect to y */
+    int i;             /* point index  */
+    int l;             /* line number */
+    int s;             /* scanline */
+  } pEdge;
+     
+  pointObj *point1, *point2;
+     
+  int k, l, i, j, xl, xr, ymin, ymax, y, n,nvert, nact, m;
+  int wrong_order;
+     
+  pEdge *edge, *temp;
+  pEdge  **active;
+  int *yhist, *edgeindex;
+     
+  if(p->numlines == 0) return;
+  n=0;
+     
+  for(i=0; i<p->numlines; i++) {
+   n += p->line[i].numpoints;
+  }
+     
+  if(n == 0)   return;
+
+  edge = (pEdge *) calloc(n,sizeof(pEdge));           /* All edges in the polygon */
+  edgeindex =  (int *) calloc(n,sizeof(int));         /* Index to edges sorted by scanline */
+  active = (pEdge **) calloc(n,sizeof(pEdge*));       /* Pointers to active edges for current scanline */
+    
+  nvert=0;
+     
+  ymin= (int) ceil(p->line[0].point[0].y-0.5);
+  ymax= (int) floor(p->line[0].point[0].y-0.5);
+     
+  /* populate the edge table */
+  for(l=0; l<p->numlines; l++) {
+    for(i=0; i < p->line[l].numpoints; i++) {
+      j = i < p->line[l].numpoints -1 ? i+1 : 0;
+      if (p->line[l].point[i].y  < p->line[l].point[j].y ) {
+        point1 = &(p->line[l].point[i]);
+        point2 = &(p->line[l].point[j]);
+      } else {
+        point2 = &(p->line[l].point[i]);
+        point1 = &(p->line[l].point[j]);
+      }
+               
+      edge[nvert].dx  = point2->y == point1->y ? 0 :  (point2->x - point1->x) / (point2->y - point1->y);
+      edge[nvert].s = MS_NINT( p->line[l].point[i].y );  /* ceil( p->line[l].point[i].y  - 0.5 ); */
+      edge[nvert].x = point1->x;
+      edge[nvert].i = nvert;
+      edge[nvert].l = l;
+               
+      ymin = MS_MIN(ymin,edge[nvert].s);
+      ymax = MS_MAX(ymax,edge[nvert].s);
+
+      nvert++;
+    }
+  }
+   
+  /* Use histogram sort to create a bucket-sorted edgeindex by scanline */
+  yhist = (int*) calloc(ymax - ymin + 2, sizeof(int));
+  for(i=0;i<nvert;i++) {
+    yhist[ edge[i].s - ymin + 1 ]++;
+  }
+  for(i=0; i<=(ymax - ymin); i++)  {/* Calculate starting point in edgeindex for each scanline */
+    yhist[i+1] += yhist[i]; 
+  }
+  for(i=0;i<nvert;i++){ /* Bucket sort edges into edgeindex */
+    y = edge[i].s;
+    edgeindex[yhist[y-ymin]] = i;
+    yhist[y-ymin]++;
+  }
+  free(yhist);
+   
+  k=0;
+  nact=0;
+
+  for (y=ymin; y<=ymax; y++) { /* step through scanlines */
+    /* scanline y is at y+.5 in continuous coordinates */
+          
+    /* check vertices between previous scanline and current one, if any */
+    for (; k<nvert && edge[edgeindex[k]].s <= y; k++) {
+      i = edge[edgeindex[k]].i;
+               
+      /* vertex previous to i */
+      if(i==0 || edge[i].l != edge[i-1].l)
+        j = i +  p->line[edge[i].l].numpoints - 1;
+      else
+        j = i - 1;
+               
+      if (edge[j].s  <=  y  ) { /* old edge, remove from active list */
+        for (m=0; m<nact && active[m]->i!=j; m++);
+          if (m<nact) {
+            nact--;
+            active[m]=active[nact];
+          }
+      } else if (edge[j].s > y) { /* new edge,  insert into active list */
+        active[nact]= & edge[j];
+        nact++;
+      }
+               
+      /* vertex next  after i */
+      if(i==nvert-1 || edge[i].l != edge[i+1].l)
+        j = i - p->line[edge[i].l].numpoints  + 1;
+      else
+        j = i + 1;
+
+      if (edge[j].s  <=  y - 1 ) {     /* old edge, remove from active list */
+        for (m=0; m<nact && active[m]->i!=i; m++);
+          if (m<nact) {
+            nact--;
+            active[m]=active[nact];
+          }
+      } else if (edge[j].s > y ) { /* new edge, insert into active list */
+        active[nact]= & edge[i];
+        nact++;
+      }
+    }
+          
+    /* Sort active edges by x */
+    do {
+      wrong_order = 0;
+      for(i=0; i < nact-1; i++) {
+        if(active[i]->x > active[i+1]->x) {
+          wrong_order = 1;
+          SWAP(active[i], active[i+1], temp);
+        }
+      }
+    } while(wrong_order);
+
+    /* draw horizontal spans for scanline y */
+    for (j=0; j<nact; j+=2) {	
+      /* j -> j+1 is inside,  j+1 -> j+2 is outside */
+      xl = (int) MS_NINT(active[j]->x );  
+      xr = (int) (active[j+1]->x - 0.5) ;
+
+      if(active[j]->x != active[j+1]->x) 
+        imageScanline(im, xl+offsetx, xr+offsetx, y+offsety, c);
+               
+      active[j]->x += active[j]->dx;	/* increment edge coords */
+      active[j+1]->x += active[j+1]->dx;
+    }
+  }
+     
+  free(active);
+  free(edgeindex);
+  free(edge);
+}
+
 void renderLineGD(imageObj *img, shapeObj *p, strokeStyleObj *stroke) {
 }
 
-void renderPolygonGD(imageObj *img, shapeObj *p, colorObj *c) {
+void renderPolygonGD(imageObj *img, shapeObj *p, colorObj *c) 
+{  
+  gdImagePtr ip;
+  fprintf(stderr, "in renderPolygonGD(), r=%d, g=%d, b=%d\n", c->red, c->green, c->blue);
+  if(!img || !p || !c) return;
+  ip = (gdImagePtr) img->img.plugin;
+  if(c->pen == MS_PEN_UNSET) setPen(ip, c);
+  imageFilledPolygon(ip, p, c->pen, 0, 0);
 }
 
 void renderGlyphsLineGD(imageObj *img, labelPathObj *labelpath, labelStyleObj *style, char *text) {
@@ -145,9 +335,9 @@
 void freeSymbolGD(symbolObj *s) {
 }
 
-inline int populateRendererVTableGD( rendererVTableObj *renderer ) {
+int msPopulateRendererVTableGD( rendererVTableObj *renderer ) {
   renderer->supports_imagecache=0;
-  renderer->supports_pixel_buffer=1;
+  renderer->supports_pixel_buffer=0;
   renderer->supports_transparent_layers = 0;
   renderer->startNewLayer = startNewLayerGD;
   renderer->closeNewLayer = closeNewLayerGD;



More information about the mapserver-commits mailing list