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, ®);
- 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, ®);
+ 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