[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