Here is a patch for multi-vertex polygon support. This version draws the polygons using scanlines instead of triangles since I've been distracted from my desired changes. If I have more time I might send a new patch with a version that uses FillTriangle, but I'd love for this code to make it in for now since drawing polygons with > 3 sides would really be nice.
diff -r -x configure -x aclocal.m4 -x Makefile.in -x '*.pc' -x '*.o' -x '*.lo' 
-x Makefile -x tests -x demos -upN -x '*.Plo' -x '*.la' -x '*.a' 
gtk+-2.10.3/gdk/directfb/gdkdrawable-directfb.c 
gtk+-2.10.3-with-polygon/gdk/directfb/gdkdrawable-directfb.c
--- gtk+-2.10.3/gdk/directfb/gdkdrawable-directfb.c     2006-08-11 
01:44:46.000000000 -0400
+++ gtk+-2.10.3-with-polygon/gdk/directfb/gdkdrawable-directfb.c        
2006-09-14 10:23:31.000000000 -0400
@@ -38,6 +38,7 @@
 
 #include "gdkdirectfb.h"
 #include "gdkprivate-directfb.h"
+#include "polygon-directfb.h"
 
 #include "gdkinternals.h"
 
@@ -493,42 +494,28 @@ gdk_directfb_draw_polygon (GdkDrawable *
 
   if (filled)
     {
-                if (npoints == 3 ||
-                                (npoints == 4 && 
-                                 points[0].x == points[npoints-1].x &&
-                                 points[0].y == points[npoints-1].y))
-          {
-            GdkDrawableImplDirectFB *impl;
-            GdkRegion               *clip;
-            gint                     i;
-
-            impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
-
-            if (!gdk_directfb_setup_for_drawing (impl, GDK_GC_DIRECTFB (gc)))
-              return;
-
-            clip = gdk_directfb_clip_region (drawable, gc, NULL);
-
-            for (i = 0; i < clip->numRects; i++)
-              {
-                                DFBRegion reg = { clip->rects[i].x1,     
clip->rects[i].y1, 
-                    clip->rects[i].x2 , clip->rects[i].y2  };
-
-                impl->surface->SetClip (impl->surface, &reg);
-                impl->surface->FillTriangle (impl->surface,
-                                             points[0].x, points[0].y,
-                                             points[1].x, points[1].y,
-                                             points[2].x, points[2].y);
-
-              }
-            impl->surface->SetClip (impl->surface, NULL);
-            gdk_region_destroy (clip);
+      GdkDrawableImplDirectFB *impl;
+      GdkRegion               *clip;
+      gint                     i;
 
-            return;
-          }
-                else
-                        g_message ("filled polygons with n > 3 are not yet 
supported, "
-                     "drawing outlines");
+      impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
+
+      if (!gdk_directfb_setup_for_drawing (impl, GDK_GC_DIRECTFB (gc)))
+        return;
+
+      clip = gdk_directfb_clip_region (drawable, gc, NULL);
+
+      for (i = 0; i < clip->numRects; i++)
+        {
+          DFBRegion reg = { clip->rects[i].x1,     clip->rects[i].y1, 
+                            clip->rects[i].x2 , clip->rects[i].y2  };
+
+          impl->surface->SetClip (impl->surface, &reg);
+          directfb_fillPolygon(impl->surface, points, npoints);
+        }
+      impl->surface->SetClip (impl->surface, NULL);
+      gdk_region_destroy (clip);
+      return;
     }
 
   if (points[0].x != points[npoints-1].x ||
diff -r -x configure -x aclocal.m4 -x Makefile.in -x '*.pc' -x '*.o' -x '*.lo' 
-x Makefile -x tests -x demos -upN -x '*.Plo' -x '*.la' -x '*.a' 
gtk+-2.10.3/gdk/directfb/Makefile.am 
gtk+-2.10.3-with-polygon/gdk/directfb/Makefile.am
--- gtk+-2.10.3/gdk/directfb/Makefile.am        2006-04-21 11:09:27.000000000 
-0400
+++ gtk+-2.10.3-with-polygon/gdk/directfb/Makefile.am   2006-09-14 
09:41:46.000000000 -0400
@@ -46,6 +46,7 @@ libgdk_directfb_la_SOURCES =  \
        gdkdirectfb.h           \
        gdkwindow-directfb.c    \
        gdkwindowid.c           \
+       polygon-directfb.c      \
        x-cursors.xbm
 
 libgdkinclude_HEADERS =                \
diff -r -x configure -x aclocal.m4 -x Makefile.in -x '*.pc' -x '*.o' -x '*.lo' 
-x Makefile -x tests -x demos -upN -x '*.Plo' -x '*.la' -x '*.a' 
gtk+-2.10.3/gdk/directfb/polygon-directfb.c 
gtk+-2.10.3-with-polygon/gdk/directfb/polygon-directfb.c
--- gtk+-2.10.3/gdk/directfb/polygon-directfb.c 1969-12-31 19:00:00.000000000 
-0500
+++ gtk+-2.10.3-with-polygon/gdk/directfb/polygon-directfb.c    2006-09-15 
08:12:30.479261872 -0400
@@ -0,0 +1,274 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+
+#include "polygon-directfb.h"
+
+typedef struct _edge edge;
+struct _edge
+{
+       int minY;
+       int maxY;
+       double xPos;    // This value is initialized to the x value 
corresponding the min y value
+       double inverseSlope;
+
+       edge* nextEdge;
+};
+
+typedef struct _edge_list edge_list;
+struct _edge_list
+{
+       edge* start;
+};
+
+static int init_edge(edge* edge, GdkPoint p1, GdkPoint p2)
+{
+       if (p1.y > p2.y) {
+               edge->minY = p2.y;
+               edge->maxY = p1.y;
+               edge->xPos = p2.x;
+               edge->inverseSlope = ((double)(p1.x - p2.x)) / ((double)(p1.y - 
p2.y));
+       } else
+       if (p1.y == p2.y) {
+               // Don't put the edge in this list
+               // because it is horizontal
+               return 0;
+       } else {
+               edge->minY = p1.y;
+               edge->maxY = p2.y;
+               edge->xPos = p1.x;
+               edge->inverseSlope = ((double)(p2.x - p1.x)) / ((double)(p2.y - 
p1.y));
+       }
+
+       edge->nextEdge = NULL;
+
+       return 1;
+}
+
+/**
+ * Initialize the edge list and return the number of edges added.
+ * Only edges with a non-zero slope will be added to the list
+ */
+static int init_edges(GdkPoint* points, gint num, edge* edges)
+{
+       int currentEdge = 0;
+       int point = 0;
+       
+       for (point=1;point < num; point++) {
+               if (init_edge(edges+currentEdge, points[point-1], 
points[point])) {
+                       currentEdge++;
+               }
+       }
+
+       // Connect the last point back to the beginning
+       if (init_edge(edges+currentEdge, points[num-1], points[0])) {
+               currentEdge++;
+       }
+
+       return currentEdge;
+}
+
+static edge_list init_global_edge_table(edge* edges, int num)
+{
+       edge_list global_list;
+       edge start;
+       int currentEdgeOffset = 0;
+
+       if (num == 0) {
+               global_list.start = NULL;
+               return global_list;
+       }
+
+       start.nextEdge = edges;
+       currentEdgeOffset++;
+
+       for (;currentEdgeOffset<num;currentEdgeOffset++) {
+               edge* temp;
+               edge* newEdge = edges+currentEdgeOffset;
+               edge* currentEdge = &start;
+               while (currentEdge->nextEdge != NULL) {
+                       if (currentEdge->nextEdge->minY > newEdge->minY) {
+                               // The new edge should be placed before the 
next edge
+                               break;
+                       } 
+                       if ((currentEdge->nextEdge->minY == newEdge->minY) &&
+                               (newEdge->xPos < currentEdge->nextEdge->xPos)) {
+                                       break;
+                       }
+
+                       currentEdge = currentEdge->nextEdge;
+               }
+
+               temp = currentEdge->nextEdge;
+               currentEdge->nextEdge = newEdge;
+               newEdge->nextEdge = temp;
+       }
+
+       global_list.start = start.nextEdge;
+       return global_list;
+}
+
+static edge_list init_active_list(edge_list* global_list)
+{
+       edge_list active_list;
+       edge* currentEdge;
+
+       active_list.start = global_list->start;
+
+       currentEdge = global_list->start;
+       while ((currentEdge->nextEdge != NULL) && 
+                  (currentEdge->nextEdge->minY == active_list.start->minY)) {
+               currentEdge = currentEdge->nextEdge;
+       }
+
+       global_list->start = currentEdge->nextEdge; // Make the next edge the 
start of the global list
+       currentEdge->nextEdge = NULL; // Make the current edge the end of the 
active list
+
+       return active_list;
+}
+
+static void prune_and_increment_active_list(int currentY, edge_list* 
active_list)
+{
+       edge start;
+       edge* currentEdge = &start;
+       start.nextEdge = active_list->start;
+       
+       while (currentEdge->nextEdge != NULL) {
+               // If the next edge is below the currentY value then
+               // it should not be in the active list
+               if (currentEdge->nextEdge->maxY < currentY) {
+                       // Update the next edge to the next edge's next edge 
and 
+                       // continue to check that the edge should be processed
+                       currentEdge->nextEdge = currentEdge->nextEdge->nextEdge;
+                       continue;
+               }
+
+               // At this point the next edge should definitely stay in the 
+               // active list and it's x position can be incremented
+               currentEdge = currentEdge->nextEdge;
+               currentEdge->xPos += currentEdge->inverseSlope;
+       }
+
+       active_list->start = start.nextEdge;
+}
+
+static void migrate_global_edges(int currentY, edge_list* global_list, 
edge_list* active_list)
+{
+       edge start;
+       edge* currentEdge = &start;
+       start.nextEdge = global_list->start;
+       
+       while ((currentEdge->nextEdge != NULL) &&
+               (currentEdge->nextEdge->minY == currentY)) {
+                       currentEdge = currentEdge->nextEdge;
+       }
+
+       global_list->start = currentEdge->nextEdge;
+
+       // Append the new items to the front of the active list
+       currentEdge->nextEdge = active_list->start;
+       active_list->start = start.nextEdge;
+}
+
+static void sort_active_list(edge_list* active_list)
+{
+       int flips = 1;  // Init the flips to 1 so that the list
+                       // will be checked at least once
+       edge start;
+
+       start.nextEdge = active_list->start;
+
+       // If there are 0 or 1 points then there is nothing to do
+       if (start.nextEdge == NULL) return;
+       if (start.nextEdge->nextEdge == NULL) return;
+
+       while (flips > 0) {
+               edge* currentEdge = &start;
+               flips = 0;
+               while (currentEdge->nextEdge->nextEdge != NULL) {
+                       if (currentEdge->nextEdge->xPos > 
currentEdge->nextEdge->nextEdge->xPos) {
+                               // Flip needed
+                               edge* first = currentEdge->nextEdge;
+                               edge* second = currentEdge->nextEdge->nextEdge;
+
+                               first->nextEdge = second->nextEdge;
+                               second->nextEdge = first;
+
+                               currentEdge->nextEdge = second;
+                               flips++;
+                       }
+                       currentEdge = currentEdge->nextEdge;
+               }
+       }
+
+       active_list->start = start.nextEdge;
+}
+
+static void draw_line_spans(IDirectFBSurface* surface, int currentY, edge_list 
active_list)
+{
+       int parity = 0;
+       edge* currentEdge = active_list.start;
+
+       if (active_list.start == NULL) return;
+
+       while (currentEdge->nextEdge != NULL) {
+               if (parity == 0) {
+                       DFBSpan span;
+
+                       span.x = (int)currentEdge->xPos;
+                       span.w = (unsigned int)(currentEdge->nextEdge->xPos - 
currentEdge->xPos);
+                       surface->FillSpans(surface, currentY, &span, 1);
+               }
+
+               parity = !parity;
+               currentEdge = currentEdge->nextEdge;
+       }
+}
+
+void directfb_fillPolygon(IDirectFBSurface* surface, GdkPoint* points, int num)
+{
+       edge* edges = malloc(sizeof(edge) * num);
+       int edgeCount = init_edges(points, num, edges);
+       if (edgeCount > 0) {
+               edge_list global_list = init_global_edge_table(edges, 
edgeCount);
+               edge_list active_list = init_active_list(&global_list);
+                       
+               int currentY = active_list.start->minY;
+               
+               while (active_list.start != NULL) {
+                       // Draw line spans
+                       draw_line_spans(surface, currentY, active_list);
+
+                       currentY++;
+
+                       // Remove active edges and increment the x position on
+                       // the edges which stay in the list
+                       prune_and_increment_active_list(currentY, &active_list);
+               
+                       // Add edges from  the global table which should be in 
the 
+                       // active table
+                       migrate_global_edges(currentY, &global_list, 
&active_list);
+
+                       // Sort the active list by x position
+                       sort_active_list(&active_list);
+               }
+       }
+
+       free(edges);
+       
+}
diff -r -x configure -x aclocal.m4 -x Makefile.in -x '*.pc' -x '*.o' -x '*.lo' 
-x Makefile -x tests -x demos -upN -x '*.Plo' -x '*.la' -x '*.a' 
gtk+-2.10.3/gdk/directfb/polygon-directfb.h 
gtk+-2.10.3-with-polygon/gdk/directfb/polygon-directfb.h
--- gtk+-2.10.3/gdk/directfb/polygon-directfb.h 1969-12-31 19:00:00.000000000 
-0500
+++ gtk+-2.10.3-with-polygon/gdk/directfb/polygon-directfb.h    2006-09-15 
08:15:02.976078832 -0400
@@ -0,0 +1,26 @@
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __POLYGON_DIRECTFB_H__
+#define __POLYGON_DIRECTFB_H__
+
+#include "gdk.h"
+#include "gdkdirectfb.h"
+
+void directfb_fillPolygon(IDirectFBSurface *surface, GdkPoint* points, int 
num);
+
+#endif /* __POLYGON_DIRECTFB_H__ */
_______________________________________________
directfb-dev mailing list
directfb-dev@directfb.org
http://mail.directfb.org/cgi-bin/mailman/listinfo/directfb-dev

Reply via email to