On Sun, 2008-06-15 at 19:00 +0200, Bert Timmerman wrote: 
> Hi Peter,
> 
> http://www.xs4all.nl/~ljh4timm/downloads/pcb-OpenGL-screenshot4.png
> 
> Gives a better view (the other side of the board.
> 
> Silk is indeed on top of mask as it should be.

I fixed the mask drawing to work vaguely correctly now. Try the attached
patch. It also features cross-hairs, and construction / rubber-band
lines.

Bling :)

-- 
Peter Clifton

Electrical Engineering Division,
Engineering Department,
University of Cambridge,
9, JJ Thomson Avenue,
Cambridge
CB3 0FA

Tel: +44 (0)7729 980173 - (No signal in the lab!)
Index: configure.ac
===================================================================
RCS file: /cvsroot/pcb/pcb/configure.ac,v
retrieving revision 1.103
diff -U3 -p -r1.103 configure.ac
--- configure.ac	28 Apr 2008 17:10:13 -0000	1.103
+++ configure.ac	15 Jun 2008 21:36:44 -0000
@@ -494,6 +494,16 @@ Please review the following errors:
 $GLIB_PKG_ERRORS])]
 	)
 	GLIB_VERSION=`$PKG_CONFIG glib-2.0 --modversion`
+
+
+# Check for GtkGLExt
+PKG_CHECK_MODULES(GTKGLEXT, gtkglext-1.0 >= 1.0.0, , [AC_MSG_ERROR([
+*** Required version of gtkglext is not installed - please install first ***
+Please review the following errors:
+$GTKGLEXT_PKG_ERRORS])]
+)
+
+GTKGLEXT_VER=`$PKG_CONFIG gtkglext-1.0 --modversion`
 	;;
 
       nelma|png )
@@ -696,8 +706,8 @@ fi
 AC_MSG_RESULT([no])
 ])
 
-CFLAGS="$CFLAGS $X_CFLAGS $DBUS_CFLAGS $GTK_CFLAGS"
-LIBS="$LIBS $XM_LIBS $DBUS_LIBS $X_LIBS $GTK_LIBS $DMALLOC_LIBS $GD_LIBS $INTLLIBS"
+CFLAGS="$CFLAGS $X_CFLAGS $DBUS_CFLAGS $GTK_CFLAGS $GTKGLEXT_CFLAGS"
+LIBS="$LIBS $XM_LIBS $DBUS_LIBS $X_LIBS $GTK_LIBS $GTKGLEXT_LIBS $DMALLOC_LIBS $GD_LIBS $INTLLIBS -lglut"
 
 
 # if we have gcc then add -Wall
Index: src/crosshair.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/crosshair.c,v
retrieving revision 1.36
diff -U3 -p -r1.36 crosshair.c
--- src/crosshair.c	13 Apr 2008 16:06:39 -0000	1.36
+++ src/crosshair.c	15 Jun 2008 21:36:46 -0000
@@ -83,7 +83,7 @@ static void XORDrawMoveOrCopyObject (voi
 static void XORDrawAttachedLine (LocationType, LocationType, LocationType,
 				 LocationType, BDimension);
 static void XORDrawAttachedArc (BDimension);
-static void DrawAttached (Boolean);
+/*static*/ void DrawAttached (Boolean);
 
 /* ---------------------------------------------------------------------------
  * creates a tmp polygon with coordinates converted to screen system
@@ -184,8 +184,7 @@ XORDrawAttachedLine (LocationType x1, Lo
     {
       LocationType angle = atan2 ((float) dx, (float) dy) * 57.295779;
       gui->draw_line (Crosshair.GC, x1 - ox, y1 - oy, x2 - ox, y2 - oy);
-      gui->draw_arc (Crosshair.GC,
-		     x1, y1, thick / 2, thick / 2, angle - 180, 180);
+      gui->draw_arc (Crosshair.GC, x1, y1, thick / 2, thick / 2, angle - 180, 180);
       gui->draw_arc (Crosshair.GC, x2, y2, thick / 2, thick / 2, angle, 180);
     }
 }
@@ -575,7 +574,7 @@ XORDrawMoveOrCopyObject (void)
 /* ---------------------------------------------------------------------------
  * draws additional stuff that follows the crosshair
  */
-static void
+/*static*/ void
 DrawAttached (Boolean BlockToo)
 {
   BDimension s;
@@ -746,7 +745,7 @@ HideCrosshair (Boolean BlockToo)
   CrosshairStack[CrosshairStackLocation] = Crosshair.On;
   CrosshairStackLocation++;
 
-  CrosshairOff (BlockToo);
+//  CrosshairOff (BlockToo);
 }
 
 /* ---------------------------------------------------------------------------
@@ -766,11 +765,11 @@ RestoreCrosshair (Boolean BlockToo)
 
   if (CrosshairStack[CrosshairStackLocation])
     {
-      CrosshairOn (BlockToo);
+//      CrosshairOn (BlockToo);
     }
   else
     {
-      CrosshairOff (BlockToo);
+//      CrosshairOff (BlockToo);
     }
 }
 
@@ -782,6 +781,7 @@ FitCrosshairIntoGrid (LocationType X, Lo
 {
   LocationType x2, y2, x0, y0;
   void *ptr1, *ptr2, *ptr3;
+  float nearest, sq_dist;
   int ans;
 
   x0 = 0;
@@ -791,41 +791,6 @@ FitCrosshairIntoGrid (LocationType X, Lo
   Crosshair.X = MIN (Crosshair.MaxX, MAX (Crosshair.MinX, X));
   Crosshair.Y = MIN (Crosshair.MaxY, MAX (Crosshair.MinY, Y));
 
-  if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB))
-    {
-      ans =
-	SearchScreen (Crosshair.X, Crosshair.Y,
-		      PAD_TYPE | PIN_TYPE, &ptr1, &ptr2, &ptr3);
-      if (ans == NO_TYPE && !PCB->RatDraw)
-	ans =
-	  SearchScreen (Crosshair.X, Crosshair.Y, VIA_TYPE | LINEPOINT_TYPE,
-			&ptr1, &ptr2, &ptr3);
-      if (ans == NO_TYPE && !PCB->RatDraw)
-	ans =
-	  SearchScreen (Crosshair.X, Crosshair.Y, ELEMENT_TYPE, &ptr1, &ptr2,
-			&ptr3);
-    }
-  else
-    ans = NO_TYPE;
-
-  /* avoid self-snapping */
-  if (Settings.Mode == MOVE_MODE)
-    {
-      switch (Crosshair.AttachedObject.Type)
-	{
-	case ELEMENT_TYPE:
-	  if ((ans & (PAD_TYPE | PIN_TYPE)) &&
-	      ptr1 == Crosshair.AttachedObject.Ptr1)
-	    ans = NO_TYPE;
-	  break;
-	case VIA_TYPE:
-	  /* just avoid snapping to any other vias */
-	  if (ans & PIN_TYPES)
-	    ans = NO_TYPE;
-	  break;
-	}
-    }
-
   if (PCB->RatDraw)
     {
       x0 = -600;
@@ -875,82 +840,133 @@ FitCrosshairIntoGrid (LocationType X, Lo
 	}
 
     }
+
+  nearest = -1;
+
+  if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB))
+    ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y,
+                                PAD_TYPE | PIN_TYPE, &ptr1, &ptr2, &ptr3);
+  else
+    ans = NO_TYPE;
+
+  /* Avoid self-snapping when moving */
+  if (Settings.Mode == MOVE_MODE &&
+      Crosshair.AttachedObject.Type == ELEMENT_TYPE)
+    {
+      if ((ans & (PAD_TYPE | PIN_TYPE)) &&
+           ptr1 == Crosshair.AttachedObject.Ptr1)
+        ans = NO_TYPE;
+    }
+
   if (ans & PAD_TYPE)
     {
       PadTypePtr pad = (PadTypePtr) ptr2;
       LocationType px, py;
-      if (SQUARE (pad->Point1.X - Crosshair.X) +
-	  SQUARE (pad->Point1.Y - Crosshair.Y) <
-	  SQUARE (pad->Point2.X - Crosshair.X) + SQUARE (pad->Point2.Y -
-							 Crosshair.Y))
-	{
-	  px = pad->Point1.X;
-	  py = pad->Point1.Y;
-	}
-      else
-	{
-	  px = pad->Point2.X;
-	  py = pad->Point2.Y;
-	}
+      px = (pad->Point1.X + pad->Point2.X) / 2;
+      py = (pad->Point1.Y + pad->Point2.Y) / 2;
 
-      if (!gui->shift_is_pressed()
-	  || (SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) >
-	      SQUARE (px - Crosshair.X) + SQUARE (py - Crosshair.Y)))
-	{
-	  x0 = px;
-	  y0 = py;
-	}
+      sq_dist = SQUARE (px - Crosshair.X) + SQUARE (py - Crosshair.Y);
+
+      if (!gui->shift_is_pressed() ||
+          SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist)
+        {
+          x0 = px;
+          y0 = py;
+          nearest = sq_dist;
+        }
+    }
+  else if (ans & PIN_TYPE)
+    {
+      PinTypePtr pin = (PinTypePtr) ptr2;
+      sq_dist = SQUARE (pin->X - Crosshair.X) + SQUARE (pin->Y - Crosshair.Y);
+      if ((nearest == -1 || sq_dist < nearest) &&
+          (!gui->shift_is_pressed() ||
+           SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist))
+        {
+          x0 = pin->X;
+          y0 = pin->Y;
+          nearest = sq_dist;
+        }
     }
 
-  else if (ans & (PIN_TYPE | VIA_TYPE))
+  if (TEST_FLAG (SNAPPINFLAG, PCB))
+    ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y,
+                                VIA_TYPE | LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3);
+  else
+    ans = NO_TYPE;
+
+  /* Avoid snapping vias to any other vias */
+  if (Settings.Mode == MOVE_MODE &&
+      Crosshair.AttachedObject.Type == VIA_TYPE)
+    {
+        if (ans & PIN_TYPES)
+          ans = NO_TYPE;
+    }
+
+  if (ans & VIA_TYPE)
     {
       PinTypePtr pin = (PinTypePtr) ptr2;
-      if (!gui->shift_is_pressed()
-	  || (SQUARE (x0 - Crosshair.X) +
-	      SQUARE (y0 - Crosshair.Y) >
-	      SQUARE (pin->X - Crosshair.X) + SQUARE (pin->Y - Crosshair.Y)))
-	{
-	  x0 = pin->X;
-	  y0 = pin->Y;
-	}
+      sq_dist = SQUARE (pin->X - Crosshair.X) + SQUARE (pin->Y - Crosshair.Y);
+      if ((nearest == -1 || sq_dist < nearest) &&
+          (!gui->shift_is_pressed() ||
+           SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist))
+        {
+          x0 = pin->X;
+          y0 = pin->Y;
+          nearest = sq_dist;
+        }
     }
   else if (ans & LINEPOINT_TYPE)
     {
       PointTypePtr pnt = (PointTypePtr) ptr3;
-      if (((x0 - Crosshair.X) * (x0 - Crosshair.X) +
-	   (y0 - Crosshair.Y) * (y0 - Crosshair.Y)) >
-	  ((pnt->X - Crosshair.X) * (pnt->X - Crosshair.X) +
-	   (pnt->Y - Crosshair.Y) * (pnt->Y - Crosshair.Y)))
-	{
-	  x0 = pnt->X;
-	  y0 = pnt->Y;
-	}
+      sq_dist = SQUARE (pnt->X - Crosshair.X) + SQUARE (pnt->Y - Crosshair.Y);
+      if ((nearest == -1 || sq_dist < nearest) &&
+          (!gui->shift_is_pressed() ||
+           SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist))
+        {
+          x0 = pnt->X;
+          y0 = pnt->Y;
+          nearest = sq_dist;
+        }
     }
-  else if (ans & ELEMENT_TYPE)
+
+
+  if (PCB->RatDraw || TEST_FLAG (SNAPPINFLAG, PCB))
+    ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y,
+                                ELEMENT_TYPE, &ptr1, &ptr2, &ptr3);
+  else
+    ans = NO_TYPE;
+
+  if (ans & ELEMENT_TYPE)
     {
       ElementTypePtr el = (ElementTypePtr) ptr1;
-      if (SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) >
-	  SQUARE (el->MarkX - Crosshair.X) + SQUARE (el->MarkY - Crosshair.Y))
-	{
-	  x0 = el->MarkX;
-	  y0 = el->MarkY;
-	}
+      sq_dist = SQUARE (el->MarkX - Crosshair.X) + SQUARE (el->MarkY - Crosshair.Y);
+      if ((nearest == -1 || sq_dist < nearest) &&
+//          (!gui->shift_is_pressed() ||
+           SQUARE (x0 - Crosshair.X) + SQUARE (y0 - Crosshair.Y) > sq_dist)
+        {
+          x0 = el->MarkX;
+          y0 = el->MarkY;
+          nearest = sq_dist;
+        }
     }
+
   if (x0 >= 0 && y0 >= 0)
     {
       Crosshair.X = x0;
       Crosshair.Y = y0;
     }
+
   if (Settings.Mode == ARROW_MODE)
     {
-	ans =
-	  SearchScreen (Crosshair.X, Crosshair.Y, LINEPOINT_TYPE,
-			&ptr1, &ptr2, &ptr3);
-	if (ans == NO_TYPE)
-	  hid_action("PointCursor");
-	else if (!TEST_FLAG(SELECTEDFLAG, (LineType *)ptr2))
-	  hid_actionl("PointCursor","True", NULL);
+      ans = SearchScreenGridSlop (Crosshair.X, Crosshair.Y,
+                                  LINEPOINT_TYPE, &ptr1, &ptr2, &ptr3);
+      if (ans == NO_TYPE)
+        hid_action("PointCursor");
+      else if (!TEST_FLAG(SELECTEDFLAG, (LineType *)ptr2))
+        hid_actionl("PointCursor","True", NULL);
     }
+
   if (Settings.Mode == LINE_MODE
       && Crosshair.AttachedLine.State != STATE_FIRST
       && TEST_FLAG (AUTODRCFLAG, PCB))
Index: src/draw.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/draw.c,v
retrieving revision 1.87
diff -U3 -p -r1.87 draw.c
--- src/draw.c	10 Dec 2007 03:29:55 -0000	1.87
+++ src/draw.c	15 Jun 2008 21:36:47 -0000
@@ -355,7 +355,7 @@ static int
 lowvia_callback (const BoxType * b, void *cl)
 {
   PinTypePtr via = (PinTypePtr) b;
-  if (!via->Mask)
+//  if (!via->Mask)
     DrawPlainVia (via, False);
   return 1;
 }
@@ -473,25 +473,9 @@ DrawEverything (BoxTypePtr drawn_area)
     }
   if (TEST_FLAG (CHECKPLANESFLAG, PCB) && gui->gui)
     return;
-
   /* draw vias below silk */
   if (PCB->ViaOn && gui->gui)
     r_search (PCB->Data->via_tree, drawn_area, NULL, lowvia_callback, NULL);
-  /* Draw the solder mask if turned on */
-  if (gui->set_layer ("componentmask", SL (MASK, TOP)))
-    {
-      int save_swap = SWAP_IDENT;
-      SWAP_IDENT = 0;
-      DrawMask (drawn_area);
-      SWAP_IDENT = save_swap;
-    }
-  if (gui->set_layer ("soldermask", SL (MASK, BOTTOM)))
-    {
-      int save_swap = SWAP_IDENT;
-      SWAP_IDENT = 1;
-      DrawMask (drawn_area);
-      SWAP_IDENT = save_swap;
-    }
   /* Draw pins, pads, vias below silk */
   if (gui->gui)
     DrawTop (drawn_area);
@@ -520,6 +504,21 @@ DrawEverything (BoxTypePtr drawn_area)
 		    &plated);
 	}
     }
+  /* Draw the solder mask if turned on */
+  if (gui->set_layer ("componentmask", SL (MASK, TOP)))
+    {
+      int save_swap = SWAP_IDENT;
+      SWAP_IDENT = 0;
+      DrawMask (drawn_area);
+      SWAP_IDENT = save_swap;
+    }
+  if (gui->set_layer ("soldermask", SL (MASK, BOTTOM)))
+    {
+      int save_swap = SWAP_IDENT;
+      SWAP_IDENT = 1;
+      DrawMask (drawn_area);
+      SWAP_IDENT = save_swap;
+    }
   /* Draw top silkscreen */
   if (gui->set_layer ("topsilk", SL (SILK, TOP)))
     DrawSilk (0, COMPONENT_LAYER, drawn_area);
@@ -625,7 +624,7 @@ static int
 via_callback (const BoxType * b, void *cl)
 {
   PinTypePtr via = (PinTypePtr) b;
-  if (via->Mask)
+//  if (via->Mask)
     DrawPlainVia (via, False);
   return 1;
 }
Index: src/search.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/search.c,v
retrieving revision 1.36
diff -U3 -p -r1.36 search.c
--- src/search.c	23 Nov 2007 06:09:18 -0000	1.36
+++ src/search.c	15 Jun 2008 21:36:47 -0000
@@ -322,6 +322,7 @@ struct arc_info
   ArcTypePtr *Arc, *Dummy;
   jmp_buf env;
   int locked;
+  int smallest_radius;
 };
 
 static int
@@ -329,16 +330,24 @@ arc_callback (const BoxType * box, void 
 {
   struct arc_info *i = (struct arc_info *) cl;
   ArcTypePtr a = (ArcTypePtr) box;
+  int found_radius;
 
   if (TEST_FLAG (i->locked, a))
     return 0;
 
   if (!IsPointOnArc (PosX, PosY, SearchRadius, a))
     return 0;
-  *i->Arc = a;
-  *i->Dummy = a;
-  longjmp (i->env, 1);
-  return 1;			/* never reached */
+
+  found_radius = ClosestArcPoint (PosX, PosY, a);
+
+  if (i->smallest_radius == -1 || found_radius < i->smallest_radius)
+    {
+      i->smallest_radius = found_radius;
+      *i->Arc = a;
+      *i->Dummy = a;
+    }
+//  longjmp (i->env, 1);
+  return 1;//			/* never reached */
 }
 
 
@@ -351,14 +360,18 @@ SearchArcByLocation (int locked, LayerTy
   info.Arc = Arc;
   info.Dummy = Dummy;
   info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
+  info.smallest_radius = -1;
 
   *Layer = SearchLayer;
-  if (setjmp (info.env) == 0)
-    {
+//  if (setjmp (info.env) == 0)
+//    {
       r_search (SearchLayer->arc_tree, &SearchBox, NULL, arc_callback, &info);
-      return False;
-    }
-  return (True);
+//      return False;
+//    }
+  if (info.smallest_radius > -1)
+    return True;
+  else
+    return False;
 }
 
 static int
@@ -492,7 +505,9 @@ SearchLinePointByLocation (int locked, L
   info.locked = (locked & LOCKED_TYPE) ? 0 : LOCKFLAG;
   if (r_search
       (SearchLayer->line_tree, &SearchBox, NULL, linepoint_callback, &info))
+  {
     return True;
+  }
   return False;
 }
 
@@ -1001,6 +1016,11 @@ IsPointInBox (LocationType X, LocationTy
   return IsPointInPad (X, Y, Radius, &pad);
 }
 
+int ClosestArcPoint (float X, float Y, ArcTypePtr Arc)
+{
+  return 0;
+}
+
 Boolean
 IsPointOnArc (float X, float Y, float Radius, ArcTypePtr Arc)
 {
@@ -1548,3 +1568,17 @@ SearchScreen (LocationType X, LocationTy
 				X, Y, SLOP * pixel_slop);
   return (ans);
 }
+
+/* ---------------------------------------------------------------------------
+ * searches the cursor position for the type 
+ */
+int
+SearchScreenGridSlop (LocationType X, LocationType Y, int Type, void **Result1,
+	      void **Result2, void **Result3)
+{
+  int ans;
+
+  ans = SearchObjectByLocation (Type, Result1, Result2, Result3,
+				X, Y, PCB->Grid / 2);
+  return (ans);
+}
Index: src/search.h
===================================================================
RCS file: /cvsroot/pcb/pcb/src/search.h,v
retrieving revision 1.12
diff -U3 -p -r1.12 search.h
--- src/search.h	23 Nov 2007 06:09:19 -0000	1.12
+++ src/search.h	15 Jun 2008 21:36:47 -0000
@@ -73,6 +73,7 @@
  */
 Boolean IsPointOnLine (float, float, float, LineTypePtr);
 Boolean IsPointOnPin (float, float, float, PinTypePtr);
+int ClosestArcPoint (float, float, ArcTypePtr);
 Boolean IsPointOnArc (float, float, float, ArcTypePtr);
 Boolean IsPointOnLineEnd (LocationType, LocationType, RatTypePtr);
 Boolean IsLineInRectangle (LocationType, LocationType, LocationType,
@@ -85,6 +86,7 @@ Boolean IsPointInBox (LocationType, Loca
 int SearchObjectByLocation (int, void **, void **, void **, LocationType,
 			    LocationType, BDimension);
 int SearchScreen (LocationType, LocationType, int, void **, void **, void **);
+int SearchScreenGridSlop (LocationType, LocationType, int, void **, void **, void **);
 int SearchObjectByID (DataTypePtr, void **, void **, void **, int, int);
 ElementTypePtr SearchElementByName (DataTypePtr, char *);
 
Index: src/hid/common/hidinit.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/hid/common/hidinit.c,v
retrieving revision 1.19
diff -U3 -p -r1.19 hidinit.c
--- src/hid/common/hidinit.c	20 Apr 2007 11:31:14 -0000	1.19
+++ src/hid/common/hidinit.c	15 Jun 2008 21:36:47 -0000
@@ -609,7 +609,7 @@ hid_load_settings ()
   hid_load_settings_1 (Concat ("pcb.settings", NULL));
 }
 
-#define HASH_SIZE 32
+#define HASH_SIZE 31
 
 typedef struct ecache
 {
@@ -636,7 +636,7 @@ copy_color (int set, hidval * cval, hidv
 int
 hid_cache_color (int set, const char *name, hidval * val, void **vcache)
 {
-  int hash;
+  unsigned long hash;
   const char *cp;
   ccache *cache;
   ecache *e;
@@ -651,14 +651,22 @@ hid_cache_color (int set, const char *na
       return 1;
     }
 
+  /* djb2: this algorithm (k=33) was first reported by dan bernstein many
+   * years ago in comp.lang.c. another version of this algorithm (now favored
+   * by bernstein) uses xor: hash(i) = hash(i - 1) * 33 ^ str[i]; the magic
+   * of number 33 (why it works better than many other constants, prime or
+   * not) has never been adequately explained.
+   */
+  hash = 5381;
   for (cp = name, hash = 0; *cp; cp++)
-    hash += (*cp) & 0xff;
+    hash = ((hash << 5) + hash) + (*cp & 0xff); /* hash * 33 + c */
   hash %= HASH_SIZE;
 
   for (e = cache->colors[hash]; e; e = e->next)
     if (strcmp (e->name, name) == 0)
       {
 	copy_color (set, &(e->val), val);
+        cache->lru = e;
 	return 1;
       }
   if (!set)
@@ -670,6 +678,8 @@ hid_cache_color (int set, const char *na
   e->name = strdup (name);
   memcpy (&(e->val), val, sizeof (hidval));
 
+  cache->lru = e;
+
   return 1;
 }
 
Index: src/hid/gtk/gtkhid-main.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/hid/gtk/gtkhid-main.c,v
retrieving revision 1.56
diff -U3 -p -r1.56 gtkhid-main.c
--- src/hid/gtk/gtkhid-main.c	13 Apr 2008 15:29:20 -0000	1.56
+++ src/hid/gtk/gtkhid-main.c	15 Jun 2008 21:36:48 -0000
@@ -32,10 +32,14 @@
 #include <gdk/gdkx.h>
 #endif
 
+#include <gtk/gtkgl.h>
+#include <GL/glut.h>
+
 #ifdef HAVE_LIBDMALLOC
 #include <dmalloc.h>
 #endif
 
+#define PIXELS_PER_CIRCLINE 5.
 
 RCSID ("$Id: gtkhid-main.c,v 1.56 2008/04/13 15:29:20 petercjclifton Exp $");
 
@@ -48,7 +52,7 @@ static void zoom_by (double factor, int 
 
 /* Sets gport->u_gc to the "right" GC to use (wrt mask or window)
 */
-#define USE_GC(gc) if (!use_gc(gc)) return
+#define USE_GC(gc)
 
 static int cur_mask = -1;
 static int mask_seq = 0;
@@ -379,7 +383,7 @@ zoom_by (double factor, int x, int y)
 
 /* ------------------------------------------------------------ */
 
-static void
+/*static*/ void
 draw_grid ()
 {
   static GdkPoint *points = 0;
@@ -387,6 +391,8 @@ draw_grid ()
   int x1, y1, x2, y2, n, i;
   double x, y;
 
+  return;
+
   if (!Settings.DrawGrid)
     return;
   if (Vz (PCB->Grid) < MIN_GRID_DISTANCE)
@@ -474,105 +480,76 @@ ghid_invalidate_lr (int left, int right,
 static void
 ghid_draw_bg_image(void)
 {
-	static GdkPixbuf	*pixbuf;
-	GdkInterpType	interp_type;
-	gint	x, y, w, h, w_src, h_src;
-	static gint	w_scaled, h_scaled;
-
-	if (!ghidgui->bg_pixbuf)
-		return;
-
-	w = PCB->MaxWidth / gport->zoom;
-	h = PCB->MaxHeight / gport->zoom;
-	x = gport->view_x0 / gport->zoom;
-	y = gport->view_y0 / gport->zoom;
-
-	if (w_scaled != w || h_scaled != h)
-		{
-		if (pixbuf)
-			g_object_unref(G_OBJECT(pixbuf));
-
-		w_src = gdk_pixbuf_get_width(ghidgui->bg_pixbuf);
-		h_src = gdk_pixbuf_get_height(ghidgui->bg_pixbuf);
-		if (w > w_src && h > h_src)
-			interp_type = GDK_INTERP_NEAREST;
-		else
-			interp_type = GDK_INTERP_BILINEAR;
-
-		pixbuf = gdk_pixbuf_scale_simple(ghidgui->bg_pixbuf, w, h, interp_type);
-		w_scaled = w;
-		h_scaled = h;
-		}
-	if (pixbuf)
-		gdk_pixbuf_render_to_drawable(pixbuf, gport->drawable, gport->bg_gc,
-            x, y, 0, 0,
-            w - x, h - y, GDK_RGB_DITHER_NORMAL, 0, 0);
-	}
+  static GdkPixbuf *pixbuf = NULL;
+  static gint vw_scaled, vh_scaled, x_cached, y_cached;
+  GdkInterpType interp_type;
+  gint x, y, vw, vh, w, h, w_src, h_src;
+  int bits_per_sample;
+  gboolean has_alpha;
 
-void
-ghid_invalidate_all ()
-{
-  int eleft, eright, etop, ebottom;
-  BoxType region;
+  if (!ghidgui->bg_pixbuf)
+    return;
 
-  if (!gport->pixmap)
+  w = PCB->MaxWidth / gport->zoom;
+  h = PCB->MaxHeight / gport->zoom;
+  x = gport->view_x0 / gport->zoom;
+  y = gport->view_y0 / gport->zoom;
+  vw = gport->view_width / gport->zoom;
+  vh = gport->view_height / gport->zoom;
+
+  if (pixbuf == NULL || vw_scaled != vw || vh_scaled != vh)
+    {
+      if (pixbuf != NULL)
+        g_object_unref(G_OBJECT(pixbuf));
+
+      bits_per_sample = gdk_pixbuf_get_bits_per_sample(ghidgui->bg_pixbuf);
+      has_alpha = gdk_pixbuf_get_has_alpha (ghidgui->bg_pixbuf);
+      pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
+                              has_alpha,
+                              bits_per_sample,
+                              vw, vh);
+    }
+
+  if (pixbuf == NULL)
     return;
 
-  region.X1 = MIN(Px(0), Px(gport->width + 1));
-  region.Y1 = MIN(Py(0), Py(gport->height + 1));
-  region.X2 = MAX(Px(0), Px(gport->width + 1));
-  region.Y2 = MAX(Py(0), Py(gport->height + 1));
-
-  eleft = Vx (0);
-  eright = Vx (PCB->MaxWidth);
-  etop = Vy (0);
-  ebottom = Vy (PCB->MaxHeight);
-  if (eleft > eright)
-    {
-      int tmp = eleft;
-      eleft = eright;
-      eright = tmp;
-    }
-  if (etop > ebottom)
-    {
-      int tmp = etop;
-      etop = ebottom;
-      ebottom = tmp;
-    }
-
-  if (eleft > 0)
-    gdk_draw_rectangle (gport->drawable, gport->offlimits_gc,
-			1, 0, 0, eleft, gport->height);
-  else
-    eleft = 0;
-  if (eright < gport->width)
-    gdk_draw_rectangle (gport->drawable, gport->offlimits_gc,
-			1, eright, 0, gport->width - eright, gport->height);
-  else
-    eright = gport->width;
-  if (etop > 0)
-    gdk_draw_rectangle (gport->drawable, gport->offlimits_gc,
-			1, eleft, 0, eright - eleft + 1, etop);
-  else
-    etop = 0;
-  if (ebottom < gport->height)
-    gdk_draw_rectangle (gport->drawable, gport->offlimits_gc,
-			1, eleft, ebottom, eright - eleft + 1,
-			gport->height - ebottom);
-  else
-    ebottom = gport->height;
+  if (vw_scaled != vw || vh_scaled != vh ||
+       x_cached != x  ||  y_cached != y)
+    {
+      w_src = gdk_pixbuf_get_width(ghidgui->bg_pixbuf);
+      h_src = gdk_pixbuf_get_height(ghidgui->bg_pixbuf);
 
-  gdk_draw_rectangle (gport->drawable, gport->bg_gc, 1,
-		      eleft, etop, eright - eleft + 1, ebottom - etop + 1);
+      if (w > w_src && h > h_src)
+        interp_type = GDK_INTERP_NEAREST;
+      else
+        interp_type = GDK_INTERP_BILINEAR;
 
-  ghid_draw_bg_image();
+      gdk_pixbuf_scale(ghidgui->bg_pixbuf, pixbuf,
+                       0, 0, vw, vh,
+                       (double) -x,
+                       (double) -y,
+                       (double) w / w_src,
+                       (double) h / h_src,
+                       interp_type);
+
+      x_cached = x;
+      y_cached = y;
+      vw_scaled = vw;
+      vh_scaled = vh;
+    }
+
+  if (pixbuf != NULL)
+    gdk_draw_pixbuf(gport->drawable, gport->bg_gc, pixbuf,
+                    0, 0, 0, 0, vw, vh, GDK_RGB_DITHER_NORMAL, 0, 0);
+}
 
-  hid_expose_callback (&ghid_hid, &region, 0);
-  draw_grid ();
+void
+ghid_invalidate_all ()
+{
   if (ghidgui->need_restore_crosshair)
     RestoreCrosshair (FALSE);
   ghidgui->need_restore_crosshair = FALSE;
-  ghid_screen_update ();
+  gdk_window_invalidate_rect (gport->drawing_area->window, NULL, 1);
 }
 
 
@@ -583,8 +560,10 @@ ghid_set_layer (const char *name, int gr
 	     && group <
 	     max_layer) ? PCB->LayerGroups.Entries[group][0] : group;
 
-  if (idx >= 0 && idx < max_layer + 2)
+  if (idx >= 0 && idx < max_layer + 2) {
+    gport->trans_lines = TRUE;
     return /*pinout ? 1 : */ PCB->Data->Layer[idx].On;
+  }
   if (idx < 0)
     {
       switch (SL_TYPE (idx))
@@ -596,6 +575,7 @@ ghid_set_layer (const char *name, int gr
 	    return TEST_FLAG (SHOWMASKFLAG, PCB);
 	  return 0;
 	case SL_SILK:
+          gport->trans_lines = FALSE;
 	  if (SL_MYSIDE (idx) /*|| pinout */ )
 	    return PCB->ElementOn;
 	  return 0;
@@ -609,55 +589,39 @@ ghid_set_layer (const char *name, int gr
   return 0;
 }
 
-#define WHICH_GC(gc) (cur_mask == HID_MASK_CLEAR ? gport->mask_gc : (gc)->gc)
-
 void
 ghid_use_mask (int use_it)
 {
-  static int mask_seq_id = 0;
-  GdkColor color;
-
-  if (!gport->pixmap)
-    return;
   if (use_it == cur_mask)
     return;
+
   switch (use_it)
     {
-    case HID_MASK_OFF:
-      gport->drawable = gport->pixmap;
-      mask_seq = 0;
-      break;
-
     case HID_MASK_BEFORE:
-      printf ("gtk doesn't support mask_before!\n");
-      abort ();
+      /* Write '1' to the stencil buffer where the solder-mask is drawn. */
+      glColorMask (0, 0, 0, 0);                   // Disable writting in color buffer
+      glEnable (GL_STENCIL_TEST);                 // Enable Stencil test
+      glStencilFunc (GL_ALWAYS, 1, 1);            // Test always passes, value written 1
+      glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); // Stencil pass => replace stencil value (with 1)
+      break;
 
     case HID_MASK_CLEAR:
-      if (!gport->mask)
-	gport->mask = gdk_pixmap_new (0, gport->width, gport->height, 1);
-      gport->drawable = gport->mask;
-      mask_seq = 0;
-      if (!gport->mask_gc)
-	{
-	  gport->mask_gc = gdk_gc_new (gport->drawable);
-	}
-      color.pixel = 1;
-      gdk_gc_set_foreground (gport->mask_gc, &color);
-      gdk_draw_rectangle (gport->drawable, gport->mask_gc, TRUE, 0, 0,
-			  gport->width, gport->height);
-      color.pixel = 0;
-      gdk_gc_set_foreground (gport->mask_gc, &color);
+      /* Drawing operations clear the stencil buffer to '0' */
+      glStencilFunc (GL_ALWAYS, 0, 1);            // Test always passes, value written 0
+      glStencilOp (GL_KEEP, GL_KEEP, GL_REPLACE); // Stencil pass => replace stencil value (with 0)
       break;
 
     case HID_MASK_AFTER:
-      mask_seq_id++;
-      if (!mask_seq_id)
-	mask_seq_id = 1;
-      mask_seq = mask_seq_id;
-
-      gport->drawable = gport->pixmap;
+      /* Drawing operations as masked to areas where the stencil buffer is '1' */
+      glColorMask (1, 1, 1, 1);                   // Enable drawing of r, g, b & a
+      glStencilFunc (GL_EQUAL, 1, 1);             // Draw only where stencil buffer is 1
+      glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);    // Stencil buffer read only
       break;
 
+    case HID_MASK_OFF:
+      /* Disable stenciling */
+      glDisable (GL_STENCIL_TEST);                // Disable Stencil test
+      break;
     }
   cur_mask = use_it;
 }
@@ -674,6 +638,9 @@ typedef struct
   GdkColor color;
   int xor_set;
   GdkColor xor_color;
+  double red;
+  double green;
+  double blue;
 } ColorCache;
 
 
@@ -716,11 +683,103 @@ ghid_set_special_colors (HID_Attribute *
     }
 }
 
+static void *cache = 0;
+
+void
+ghid_gl_set_color (hidGC gc, const char *name)
+{
+  hidval cval;
+  ColorCache *cc;
+  double alpha_mult = 1.0;
+  double r, g, b, a;
+  a = 1.0;
+
+  if (name == NULL)
+    {
+      fprintf (stderr, "%s():  name = NULL, setting to magenta\n",
+               __FUNCTION__);
+      name = "magenta";
+    }
+
+  gc->colorname = (char *) name;
+
+  if (gport->colormap == 0)
+    gport->colormap = gtk_widget_get_colormap (gport->top_window);
+  if (strcmp (name, "erase") == 0)
+    {
+      gc->erase = 1;
+      r = gport->bg_color.red   / 65535.;
+      g = gport->bg_color.green / 65535.;
+      b = gport->bg_color.blue  / 65535.;
+    }
+  else if (strcmp (name, "drill") == 0)
+    {
+      gc->erase = 0;
+      alpha_mult = 0.85;
+      r = gport->offlimits_color.red   / 65535.;
+      g = gport->offlimits_color.green / 65535.;
+      b = gport->offlimits_color.blue  / 65535.;
+
+    }
+  else
+    {
+      alpha_mult = 0.7;
+      if (hid_cache_color (0, name, &cval, &cache))
+        cc = (ColorCache *) cval.ptr;
+      else
+        {
+          cc = (ColorCache *) malloc (sizeof (ColorCache));
+          memset (cc, 0, sizeof (*cc));
+          cval.ptr = cc;
+          hid_cache_color (1, name, &cval, &cache);
+        }
+
+      if (!cc->color_set)
+        {
+          if (gdk_color_parse (name, &cc->color))
+            gdk_color_alloc (gport->colormap, &cc->color);
+          else
+            gdk_color_white (gport->colormap, &cc->color);
+          cc->red   = cc->color.red   / 65535.;
+          cc->green = cc->color.green / 65535.;
+          cc->blue  = cc->color.blue  / 65535.;
+          cc->color_set = 1;
+        }
+      r = cc->red;
+      g = cc->green;
+      b = cc->blue;
+      if (gc->xor)
+        {
+          if (!cc->xor_set)
+            {
+              cc->xor_set = 1;
+            }
+        }
+
+      gc->erase = 0;
+    }
+  if (1) {
+    double maxi, mult;
+    if (gport->trans_lines)
+      a = a * alpha_mult;
+    maxi = r;
+    if (g > maxi) maxi = g;
+    if (b > maxi) maxi = b;
+    mult = MIN (1 / alpha_mult, 1 / maxi);
+#if 1
+    r = r * mult;
+    g = g * mult;
+    b = b * mult;
+#endif
+  }
+  glColor4d (r, g, b, a);
+}
+
 void
 ghid_set_color (hidGC gc, const char *name)
 {
-  static void *cache = 0;
   hidval cval;
+  ghid_gl_set_color (gc, name);
 
   if (name == NULL)
     {
@@ -764,6 +823,9 @@ ghid_set_color (hidGC gc, const char *na
 	    gdk_color_alloc (gport->colormap, &cc->color);
 	  else
 	    gdk_color_white (gport->colormap, &cc->color);
+          cc->red   = cc->color.red   / 65535.;
+          cc->green = cc->color.green / 65535.;
+          cc->blue  = cc->color.blue  / 65535.;
 	  cc->color_set = 1;
 	}
       if (gc->xor)
@@ -774,6 +836,9 @@ ghid_set_color (hidGC gc, const char *na
 	      cc->xor_color.green = cc->color.green ^ gport->bg_color.green;
 	      cc->xor_color.blue = cc->color.blue ^ gport->bg_color.blue;
 	      gdk_color_alloc (gport->colormap, &cc->xor_color);
+              cc->red   = cc->color.red   / 65535.;
+              cc->green = cc->color.green / 65535.;
+              cc->blue  = cc->color.blue  / 65535.;
 	      cc->xor_set = 1;
 	    }
 	  gdk_gc_set_foreground (gc->gc, &cc->xor_color);
@@ -790,7 +855,6 @@ ghid_set_color (hidGC gc, const char *na
 void
 ghid_set_line_cap (hidGC gc, EndCapStyle style)
 {
-
   switch (style)
     {
     case Trace_Cap:
@@ -804,31 +868,18 @@ ghid_set_line_cap (hidGC gc, EndCapStyle
       gc->join = GDK_JOIN_MITER;
       break;
     }
-  if (gc->gc)
-    gdk_gc_set_line_attributes (WHICH_GC (gc),
-				Vz (gc->width), GDK_LINE_SOLID,
-				gc->cap, gc->join);
 }
 
 void
 ghid_set_line_width (hidGC gc, int width)
 {
-
   gc->width = width;
-  if (gc->gc)
-    gdk_gc_set_line_attributes (WHICH_GC (gc),
-				Vz (gc->width), GDK_LINE_SOLID,
-				gc->cap, gc->join);
 }
 
 void
 ghid_set_draw_xor (hidGC gc, int xor)
 {
-  gc->xor = xor;
-  if (!gc->gc)
-    return;
-  gdk_gc_set_function (gc->gc, xor ? GDK_XOR : GDK_COPY);
-  ghid_set_color (gc, gc->colorname);
+  /* NOT IMPLEMENTED */
 }
 
 void
@@ -843,56 +894,127 @@ ghid_set_line_cap_angle (hidGC gc, int x
   printf ("ghid_set_line_cap_angle() -- not implemented\n");
 }
 
-static int
-use_gc (hidGC gc)
+#ifndef CALLBACK
+#define CALLBACK
+#endif
+
+void CALLBACK errorCallback(GLenum errorCode)
 {
-  if (!gport->pixmap)
-    return 0;
-  if (!gc->gc)
-    {
-      gc->gc = gdk_gc_new (gport->top_window->window);
-      ghid_set_color (gc, gc->colorname);
-      ghid_set_line_width (gc, gc->width);
-      ghid_set_line_cap (gc, gc->cap);
-      ghid_set_draw_xor (gc, gc->xor);
-    }
-  if (gc->mask_seq != mask_seq)
-    {
-      if (mask_seq)
-	gdk_gc_set_clip_mask (gc->gc, gport->mask);
-      else
-	gdk_gc_set_clip_mask (gc->gc, NULL);
-      gc->mask_seq = mask_seq;
-    }
-  gport->u_gc = WHICH_GC (gc);
-  return 1;
+   const GLubyte *estring;
+
+   estring = gluErrorString(errorCode);
+   fprintf(stderr, "Quadric Error: %s\n", estring);
+   exit(0);
 }
 
+
 void
 ghid_draw_line (hidGC gc, int x1, int y1, int x2, int y2)
 {
   double dx1, dy1, dx2, dy2;
+  double width, angle;
+  float deltax, deltay, length;
+  float wdx, wdy;
+  int slices;
+  int circular_caps = 0;
+  GLUquadricObj *qobj;
 
-  dx1 = Vx ((double)x1);
-  dy1 = Vy ((double)y1);
-  dx2 = Vx ((double)x2);
-  dy2 = Vy ((double)y2);
-
+#if 0
   if (! ClipLine (0, 0, gport->width, gport->height,
-		  &dx1, &dy1, &dx2, &dy2, gc->width / gport->zoom))
+                  &dx1, &dy1, &dx2, &dy2, gc->width / gport->zoom))
     return;
+#endif
 
-  USE_GC (gc);
-  gdk_draw_line (gport->drawable, gport->u_gc, dx1, dy1, dx2, dy2);
+  dx1 = Vx (x1);
+  dy1 = Vy (y1);
+  dx2 = Vx (x2);
+  dy2 = Vy (y2);
+
+  width = Vz (gc->width);
+
+  if (width == 0.0)
+    width = 1.0;
+
+  deltax = dx2 - dx1;
+  deltay = dy2 - dy1;
+
+  length = sqrt (deltax * deltax + deltay * deltay);
+
+  wdy = deltax * width / 2 / length;
+  wdx = -deltay * width / 2 / length;
+
+  if (deltay == 0.)
+    angle = (deltax < 0) ? 270. : 90.;
+  else
+    angle = 180. / M_PI * atanl (deltax / deltay);
+
+  if (deltay < 0)
+    angle += 180.;
+
+  slices = M_PI * width / PIXELS_PER_CIRCLINE;
+
+  if (slices < 2)
+    slices = 2;
+
+  switch (gc->cap) {
+    case Trace_Cap:
+    case Round_Cap:
+      circular_caps = 1;
+      break;
+
+    case Square_Cap:
+    case Beveled_Cap:
+      dx1 -= deltax * width / 2 / length;
+      dy1 -= deltay * width / 2 / length;
+      dx2 += deltax * width / 2 / length;
+      dy2 += deltay * width / 2 / length;
+      break;
+  }
+
+  glBegin (GL_QUADS);
+//  glBegin (GL_LINE_LOOP);
+  glNormal3f (0.0f, 0.0f, 1.0f);
+  glVertex3f (dx1 - wdx, dy1 - wdy, 0.0f);
+  glVertex3f (dx2 - wdx, dy2 - wdy, 0.0f);
+  glVertex3f (dx2 + wdx, dy2 + wdy, 0.0f);
+  glVertex3f (dx1 + wdx, dy1 + wdy, 0.0f);
+  glEnd ();
+
+  if (circular_caps) {
+    qobj = gluNewQuadric ();
+    gluQuadricCallback (qobj, GLU_ERROR, errorCallback);
+    gluQuadricDrawStyle (qobj, GLU_FILL); /* smooth shaded */
+//  gluQuadricDrawStyle (qobj, GLU_LINE); /* smooth shaded */
+    gluQuadricNormals (qobj, GLU_SMOOTH);
+
+    glPushMatrix ();
+    glTranslatef (dx1, dy1, 0.0);
+    gluPartialDisk (qobj, 0, width / 2, slices, 1, angle + 90., 180);
+    glPopMatrix ();
+
+    glPushMatrix ();
+    glTranslatef (dx2, dy2, 0.0);
+    gluPartialDisk (qobj, 0, width / 2, slices, 1, angle + 270., 180);
+    glPopMatrix ();
+
+    gluDeleteQuadric (qobj);
+  }
 }
 
 void
 ghid_draw_arc (hidGC gc, int cx, int cy,
-	       int xradius, int yradius, int start_angle, int delta_angle)
+               int xradius, int yradius, int start_angle, int delta_angle)
 {
   gint vrx, vry;
-  gint w, h, radius;
-  
+  gint w, h, radius, slices;
+  double width;
+  GLUquadricObj *qobj;
+
+  width = Vz (gc->width);
+
+  if (width == 0.0)
+    width = 1.0;
+
   w = gport->width * gport->zoom;
   h = gport->height * gport->zoom;
   radius = (xradius > yradius) ? xradius : yradius;
@@ -901,12 +1023,11 @@ ghid_draw_arc (hidGC gc, int cx, int cy,
       || SIDE_Y (cy) < gport->view_y0 - radius 
       || SIDE_Y (cy) > gport->view_y0 + h + radius)
     return;
-  
+
   USE_GC (gc);
   vrx = Vz (xradius);
   vry = Vz (yradius);
 
-
   /* make sure we fall in the -180 to +180 range */
   start_angle = (start_angle + 360 + 180) % 360 - 180;
   if (ghid_flip_x)
@@ -917,12 +1038,48 @@ ghid_draw_arc (hidGC gc, int cx, int cy,
   if (ghid_flip_y)
     {
       start_angle = - start_angle;
-      delta_angle = - delta_angle;					
+      delta_angle = - delta_angle;
     }
 
-  gdk_draw_arc (gport->drawable, gport->u_gc, 0,
-		Vx (cx) - vrx, Vy (cy) - vry,
-		vrx * 2, vry * 2, (start_angle + 180) * 64, delta_angle * 64);
+  if (delta_angle < 0) {
+    start_angle += delta_angle;
+    delta_angle = - delta_angle;
+  }
+
+  slices = M_PI * (vrx + width / 2.) / PIXELS_PER_CIRCLINE;
+
+  if (slices < 2)
+    slices = 2;
+
+  qobj = gluNewQuadric ();
+  gluQuadricCallback (qobj, GLU_ERROR, errorCallback);
+  gluQuadricDrawStyle (qobj, GLU_FILL); /* smooth shaded */
+//gluQuadricDrawStyle (qobj, GLU_LINE); /* smooth shaded */
+  gluQuadricNormals (qobj, GLU_SMOOTH);
+
+  glPushMatrix ();
+  glTranslatef (Vx (cx), Vy (cy), 0.0);
+  gluPartialDisk (qobj, vrx - width / 2, vrx + width / 2, slices, 1, 270 + start_angle, delta_angle);
+  glPopMatrix ();
+
+  slices = M_PI * width / PIXELS_PER_CIRCLINE;
+
+  if (slices < 2)
+    slices = 2;
+
+  glPushMatrix ();
+  glTranslatef (Vx (cx) + vrx * -cos (M_PI / 180. * start_angle),
+                Vy (cy) + vrx *  sin (M_PI / 180. * start_angle), 0.0);
+  gluPartialDisk (qobj, 0, width / 2, slices, 1, start_angle + 90., 180);
+  glPopMatrix ();
+
+  glPushMatrix ();
+  glTranslatef (Vx (cx) + vrx * -cos (M_PI / 180. * (start_angle + delta_angle)),
+                Vy (cy) + vrx *  sin (M_PI / 180. * (start_angle + delta_angle)), 0.0);
+  gluPartialDisk (qobj, 0, width / 2, slices, 1, start_angle + delta_angle + 270., 180);
+  glPopMatrix ();
+
+  gluDeleteQuadric (qobj);
 }
 
 void
@@ -949,20 +1106,23 @@ ghid_draw_rect (hidGC gc, int x1, int y1
   x2 = Vx (x2);
   y2 = Vy (y2);
 
-  if (x1 > x2) { gint xt = x1; x1 = x2; x2 = xt; }
-  if (y1 > y2) { gint yt = y1; y1 = y2; y2 = yt; }
-
   USE_GC (gc);
-  gdk_draw_rectangle (gport->drawable, gport->u_gc, FALSE,
-		      x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+
+  glBegin (GL_LINE_LOOP);
+  glNormal3f (0.0f, 0.0f, 1.0f);
+  glVertex3f (x1, y1, 0.0f);
+  glVertex3f (x1, y2, 0.0f);
+  glVertex3f (x2, y2, 0.0f);
+  glVertex3f (x2, y1, 0.0f);
+  glEnd ();
 }
 
 
 void
 ghid_fill_circle (hidGC gc, int cx, int cy, int radius)
 {
-  gint w, h, vr;
-
+  gint w, h, vr, slices;
+  GLUquadricObj *qobj;
   w = gport->width * gport->zoom;
   h = gport->height * gport->zoom;
   if (SIDE_X (cx) < gport->view_x0 - radius
@@ -973,37 +1133,98 @@ ghid_fill_circle (hidGC gc, int cx, int 
 
   USE_GC (gc);
   vr = Vz (radius);
-  gdk_draw_arc (gport->drawable, gport->u_gc, TRUE,
-		Vx (cx) - vr, Vy (cy) - vr,
-		vr * 2, vr * 2, 0, 360 * 64);
+
+  slices = M_PI * 2 * radius / PIXELS_PER_CIRCLINE;
+
+  if (slices < 2)
+    slices = 2;
+
+  qobj = gluNewQuadric ();
+  gluQuadricCallback (qobj, GLU_ERROR, errorCallback);
+  gluQuadricDrawStyle (qobj, GLU_FILL); /* smooth shaded */
+//gluQuadricDrawStyle (qobj, GLU_LINE); /* smooth shaded */
+  gluQuadricNormals (qobj, GLU_SMOOTH);
+
+  glPushMatrix ();
+  glTranslatef (Vx(cx), Vy(cy), 0.0);
+  gluDisk (qobj, 0, vr, slices, 1);
+  glPopMatrix ();
+
+  gluDeleteQuadric (qobj);
+}
+
+void
+myError (GLenum errno)
+{
+  printf ("gluTess error: %s\n", gluErrorString (errno));
+}
+
+/* TODO: Structure for storing pointers for combined memory,
+ *       so we can free it.
+ */
+
+void
+myFreeCombined ()
+{
+
+}
+
+void
+myCombine ( GLdouble coords[3], void *vertex_data[4], GLfloat weight[4], void **dataOut )
+{
+  GLdouble *new_vertex;
+
+  new_vertex = malloc (3 * sizeof (GLdouble));
+  new_vertex[0] = coords[0];
+  new_vertex[1] = coords[1];
+  new_vertex[2] = coords[2];
+
+  *dataOut = new_vertex;
 }
 
 void
 ghid_fill_polygon (hidGC gc, int n_coords, int *x, int *y)
 {
-  static GdkPoint *points = 0;
-  static int npoints = 0;
   int i;
+  GLUtesselator *tobj;
+  GLdouble *vertices;
+
   USE_GC (gc);
 
-  if (npoints < n_coords)
-    {
-      npoints = n_coords + 1;
-      points = MyRealloc (points,
-			  npoints * sizeof (GdkPoint), (char *) __FUNCTION__);
-    }
+  g_assert (n_coords > 0);
+
+  vertices = malloc (sizeof(GLdouble) * n_coords * 3);
+
+  tobj = gluNewTess ();
+  gluTessCallback(tobj, GLU_TESS_BEGIN, glBegin);
+  gluTessCallback(tobj, GLU_TESS_VERTEX, glVertex3dv);
+  gluTessCallback(tobj, GLU_TESS_END, glEnd);
+  gluTessCallback(tobj, GLU_TESS_COMBINE, myCombine);
+  gluTessCallback(tobj, GLU_TESS_ERROR, myError);
+
+  gluTessBeginPolygon (tobj, NULL);
+  gluTessBeginContour (tobj);
+
   for (i = 0; i < n_coords; i++)
     {
-      points[i].x = Vx (x[i]);
-      points[i].y = Vy (y[i]);
+      vertices [0 + i * 3] = Vx (x[i]);
+      vertices [1 + i * 3] = Vy (y[i]);
+      vertices [2 + i * 3] = 0.;
+      gluTessVertex (tobj, &vertices [i * 3], &vertices [i * 3]);
     }
-  gdk_draw_polygon (gport->drawable, gport->u_gc, 1, points, n_coords);
+
+  gluTessEndContour (tobj);
+  gluTessEndPolygon (tobj);
+  gluDeleteTess (tobj);
+
+  myFreeCombined ();
+  free (vertices);
 }
 
 void
 ghid_fill_rect (hidGC gc, int x1, int y1, int x2, int y2)
 {
-  gint w, h, lw, xx, yy;
+  gint w, h, lw;
 
   lw = gc->width;
   w = gport->width * gport->zoom;
@@ -1023,21 +1244,15 @@ ghid_fill_rect (hidGC gc, int x1, int y1
   y1 = Vy (y1);
   x2 = Vx (x2);
   y2 = Vy (y2);
-  if (x2 < x1)
-    {
-      xx = x1;
-      x1 = x2;
-      x2 = xx;
-    }
-  if (y2 < y1)
-    {
-      yy = y1;
-      y1 = y2;
-      y2 = yy;
-    }
+
   USE_GC (gc);
-  gdk_draw_rectangle (gport->drawable, gport->u_gc, TRUE,
-                      x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+  glBegin (GL_QUADS);
+  glNormal3f (0.0f, 0.0f, 1.0f);
+  glVertex3f (x1, y1, 0.0f);
+  glVertex3f (x1, y2, 0.0f);
+  glVertex3f (x2, y2, 0.0f);
+  glVertex3f (x2, y1, 0.0f);
+  glEnd ();
 }
 
 void
@@ -1527,7 +1742,7 @@ HID ghid_hid = {
   1,				/* gui */
   0,				/* printer */
   0,				/* exporter */
-  0,				/* poly before */
+  1,				/* poly before */
   1,				/* poly after */
   0,				/* poly dicer */
 
@@ -2160,11 +2375,14 @@ Benchmark (int argc, char **argv, int x,
   region.X2 = PCB->MaxWidth;
   region.Y2 = PCB->MaxHeight;
 
+  
+
   gdk_display_sync (display);
   time (&start);
   do
     {
-      hid_expose_callback (&ghid_hid, &region, 0);
+      gdk_window_invalidate_rect (gport->drawing_area->window, NULL, 1);
+      gdk_window_process_updates (gport->drawing_area->window, FALSE);
       gdk_display_sync (display);
       time (&end);
       i++;
Index: src/hid/gtk/gui-output-events.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/hid/gtk/gui-output-events.c,v
retrieving revision 1.26
diff -U3 -p -r1.26 gui-output-events.c
--- src/hid/gtk/gui-output-events.c	13 Apr 2008 16:06:39 -0000	1.26
+++ src/hid/gtk/gui-output-events.c	15 Jun 2008 21:36:48 -0000
@@ -300,63 +300,103 @@ ghid_show_crosshair (gboolean show)
   static GdkGC *xor_gc;
   static GdkColor cross_color;
 
-  if (gport->x_crosshair < 0 || ghidgui->creating || !gport->has_entered)
+  if (gport->x_crosshair < 0 || ghidgui->creating) {// || !gport->has_entered) {
+    printf ("Returning\n");
     return;
+  }
 
   if (!xor_gc)
     {
-      xor_gc = gdk_gc_new (ghid_port.drawing_area->window);
-      gdk_gc_copy (xor_gc, ghid_port.drawing_area->style->white_gc);
-      gdk_gc_set_function (xor_gc, GDK_XOR);
+      xor_gc = (GdkGC *)1;
       /* FIXME: when CrossColor changed from config */
       ghid_map_color_string (Settings.CrossColor, &cross_color);
     }
   x = DRAW_X (gport->x_crosshair);
   y = DRAW_Y (gport->y_crosshair);
 
-  gdk_gc_set_foreground (xor_gc, &cross_color);
+  glEnable (GL_COLOR_LOGIC_OP);
+  glLogicOp (GL_XOR);
+
+  glColor3f (cross_color.red / 65535.,
+             cross_color.green / 65535.,
+             cross_color.blue / 65535.);
+
+  glBegin (GL_LINES);
 
   if (x_prev >= 0)
     {
-      gdk_draw_line (gport->drawing_area->window, xor_gc,
-		     x_prev, 0, x_prev, gport->height);
-      gdk_draw_line (gport->drawing_area->window, xor_gc,
-		     0, y_prev, gport->width, y_prev);
-      if (ghidgui->auto_pan_on && have_crosshair_attachments ())
-	{
-	  gdk_draw_rectangle (gport->drawing_area->window, xor_gc, TRUE,
-			      0, y_prev - VCD, VCD, VCW);
-	  gdk_draw_rectangle (gport->drawing_area->window, xor_gc, TRUE,
-			      gport->width - VCD, y_prev - VCD, VCD, VCW);
-	  gdk_draw_rectangle (gport->drawing_area->window, xor_gc, TRUE,
-			      x_prev - VCD, 0, VCW, VCD);
-	  gdk_draw_rectangle (gport->drawing_area->window, xor_gc, TRUE,
-			      x_prev - VCD, gport->height - VCD, VCW, VCD);
-	}
+      glVertex2i (x_prev, 0);
+      glVertex2i (x_prev, gport->height);
+      glVertex2i (0, y_prev);
+      glVertex2i (gport->width, y_prev);
+    }
+
+  if (x >= 0 && show)
+    {
+      glVertex2i (x, 0);
+      glVertex2i (x, gport->height);
+      glVertex2i (0, y);
+      glVertex2i (gport->width, y);
+    }
+
+  glEnd ();
+
+  if (ghidgui->auto_pan_on && have_crosshair_attachments ())
+    {
+      glBegin (GL_QUADS);
+
+      if (x_prev >= 0)
+        {
+          glVertex2i (0,                  y_prev - VCD);
+          glVertex2i (0,                  y_prev - VCD + VCW);
+          glVertex2i (VCD,                y_prev - VCD + VCW);
+          glVertex2i (VCD,                y_prev - VCD);
+          glVertex2i (gport->width,       y_prev - VCD);
+          glVertex2i (gport->width,       y_prev - VCD + VCW);
+          glVertex2i (gport->width - VCD, y_prev - VCD + VCW);
+          glVertex2i (gport->width - VCD, y_prev - VCD);
+          glVertex2i (x_prev - VCD,       0);
+          glVertex2i (x_prev - VCD,       VCD);
+          glVertex2i (x_prev - VCD + VCW, VCD);
+          glVertex2i (x_prev - VCD + VCW, 0);
+          glVertex2i (x_prev - VCD,       gport->height - VCD);
+          glVertex2i (x_prev - VCD,       gport->height);
+          glVertex2i (x_prev - VCD + VCW, gport->height);
+          glVertex2i (x_prev - VCD + VCW, gport->height - VCD);
+        }
+
+      if (x >= 0 && show)
+        {
+          glVertex2i (0,                  y - VCD);
+          glVertex2i (0,                  y - VCD + VCW);
+          glVertex2i (VCD,                y - VCD + VCW);
+          glVertex2i (VCD,                y - VCD);
+          glVertex2i (gport->width,       y - VCD);
+          glVertex2i (gport->width,       y - VCD + VCW);
+          glVertex2i (gport->width - VCD, y - VCD + VCW);
+          glVertex2i (gport->width - VCD, y - VCD);
+          glVertex2i (x - VCD,            0);
+          glVertex2i (x - VCD,            VCD);
+          glVertex2i (x - VCD + VCW,      VCD);
+          glVertex2i (x - VCD + VCW,      0);
+          glVertex2i (x - VCD,            gport->height - VCD);
+          glVertex2i (x - VCD,            gport->height);
+          glVertex2i (x - VCD + VCW,      gport->height);
+          glVertex2i (x - VCD + VCW,      gport->height - VCD);
+        }
+
+      glEnd ();
     }
 
   if (x >= 0 && show)
     {
-      gdk_draw_line (gport->drawing_area->window, xor_gc,
-		     x, 0, x, gport->height);
-      gdk_draw_line (gport->drawing_area->window, xor_gc,
-		     0, y, gport->width, y);
-      if (ghidgui->auto_pan_on && have_crosshair_attachments ())
-	{
-	  gdk_draw_rectangle (gport->drawing_area->window, xor_gc, TRUE,
-			      0, y - VCD, VCD, VCW);
-	  gdk_draw_rectangle (gport->drawing_area->window, xor_gc, TRUE,
-			      gport->width - VCD, y - VCD, VCD, VCW);
-	  gdk_draw_rectangle (gport->drawing_area->window, xor_gc, TRUE,
-			      x - VCD, 0, VCW, VCD);
-	  gdk_draw_rectangle (gport->drawing_area->window, xor_gc, TRUE,
-			      x - VCD, gport->height - VCD, VCW, VCD);
-	}
       x_prev = x;
       y_prev = y;
     }
   else
     x_prev = y_prev = -1;
+
+  glDisable (GL_COLOR_LOGIC_OP);
 }
 
 static gboolean
@@ -746,37 +786,127 @@ ghid_port_drawing_area_configure_event_c
       first_time_done = TRUE;
       PCBChanged (0, NULL, 0, 0);
     }
-  if (gport->mask)
-    {
-      gdk_pixmap_unref (gport->mask);
-      gport->mask = gdk_pixmap_new (0, gport->width, gport->height, 1);
-    }
+//  if (gport->mask)
+//    {
+//      gdk_pixmap_unref (gport->mask);
+//      gport->mask = gdk_pixmap_new (0, gport->width, gport->height, 1);
+//    }
   ghid_port_ranges_scale (FALSE);
   ghid_invalidate_all ();
   RestoreCrosshair (TRUE);
   return 0;
 }
 
+static inline int
+Px (int x)
+{
+  int rv = x * gport->zoom + gport->view_x0;
+  if (ghid_flip_x)
+    rv = PCB->MaxWidth - (x * gport->zoom + gport->view_x0);
+  return  rv;
+}
+
+static inline int
+Py (int y)
+{
+  int rv = y * gport->zoom + gport->view_y0;
+  if (ghid_flip_y)
+    rv = PCB->MaxHeight - (y * gport->zoom + gport->view_y0);
+  return  rv;
+}
+
+static inline int
+Vx (int x)
+{
+  int rv;
+  if (ghid_flip_x) 
+    rv = (PCB->MaxWidth - x - gport->view_x0) / gport->zoom + 0.5;
+  else
+    rv = (x - gport->view_x0) / gport->zoom + 0.5;
+  return rv;
+}
+
+static inline int
+Vy (int y)
+{
+  int rv;
+  if (ghid_flip_y)
+    rv = (PCB->MaxHeight - y - gport->view_y0) / gport->zoom + 0.5;
+  else
+    rv = (y - gport->view_y0) / gport->zoom + 0.5;
+  return rv;
+}
 
 void
 ghid_screen_update (void)
 {
-
+#if 0
   ghid_show_crosshair (FALSE);
   gdk_draw_drawable (gport->drawing_area->window, gport->bg_gc, gport->pixmap,
 		     0, 0, 0, 0, gport->width, gport->height);
   ghid_show_crosshair (TRUE);
+#endif
 }
 
+void DrawAttached (Boolean);
+void draw_grid ();
+
+#define Z_NEAR 3.0
+#define FOVY_2 20.0
 gboolean
 ghid_port_drawing_area_expose_event_cb (GtkWidget * widget,
 					GdkEventExpose * ev, GHidPort * port)
 {
+  BoxType region;
+  extern HID ghid_hid;
+  GdkGLContext* pGlContext = gtk_widget_get_gl_context (widget);
+  GdkGLDrawable* pGlDrawable = gtk_widget_get_gl_drawable (widget);
+
   ghid_show_crosshair (FALSE);
-  gdk_draw_drawable (widget->window, port->bg_gc, port->pixmap,
-		     ev->area.x, ev->area.y, ev->area.x, ev->area.y,
-		     ev->area.width, ev->area.height);
+
+  /* make GL-context "current" */
+  if (!gdk_gl_drawable_gl_begin (pGlDrawable, pGlContext)) {
+    return FALSE;
+  }
+
+  glEnable (GL_BLEND);
+  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+  glViewport (0, 0, ev->area.width, ev->area.height);
+
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+  glOrtho (0, ev->area.width, ev->area.height, 0, 0, 100);
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
+  glTranslatef (0.0f, 0.0f, -Z_NEAR);
+
+  glClearColor (gport->bg_color.red / 65535.,
+                gport->bg_color.green / 65535.,
+                gport->bg_color.blue / 65535.,
+                1.);
+
+  glClear (GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);// | GL_DEPTH_BUFFER_BIT);
+
+  region.X1 = MIN(Px(0), Px(gport->width + 1));
+  region.Y1 = MIN(Py(0), Py(gport->height + 1));
+  region.X2 = MAX(Px(0), Px(gport->width + 1));
+  region.Y2 = MAX(Py(0), Py(gport->height + 1));
+
+  hid_expose_callback (&ghid_hid, &region, 0);
+
+  draw_grid ();
+  DrawAttached (TRUE);
   ghid_show_crosshair (TRUE);
+
+  if (gdk_gl_drawable_is_double_buffered (pGlDrawable))
+    gdk_gl_drawable_swap_buffers (pGlDrawable);
+  else
+    glFlush ();
+
+  /* end drawing to current GL-context */
+  gdk_gl_drawable_gl_end (pGlDrawable);
+
   return FALSE;
 }
 
@@ -789,6 +919,13 @@ ghid_port_window_motion_cb (GtkWidget * 
   static gint x_prev = -1, y_prev = -1;
   gboolean moved;
   GdkModifierType state;
+  GdkGLContext* pGlContext = gtk_widget_get_gl_context (widget);
+  GdkGLDrawable* pGlDrawable = gtk_widget_get_gl_drawable (widget);
+
+  /* make GL-context "current" */
+  if (!gdk_gl_drawable_gl_begin (pGlDrawable, pGlContext)) {
+    return FALSE;
+  }
 
   state = (GdkModifierType) (ev->state);
   mk = ghid_modifier_keys_state (&state);
@@ -808,9 +945,18 @@ ghid_port_window_motion_cb (GtkWidget * 
     }
   x_prev = y_prev = -1;
   moved = ghid_note_event_location (ev);
+
   ghid_show_crosshair (TRUE);
   if (moved && have_crosshair_attachments ())
     ghid_draw_area_update (gport, NULL);
+
+  if (gdk_gl_drawable_is_double_buffered (pGlDrawable))
+    gdk_gl_drawable_swap_buffers (pGlDrawable);
+  else
+    glFlush ();
+
+  /* end drawing to current GL-context */
+  gdk_gl_drawable_gl_end (pGlDrawable);
   return FALSE;
 }
 
Index: src/hid/gtk/gui-top-window.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/hid/gtk/gui-top-window.c,v
retrieving revision 1.54
diff -U3 -p -r1.54 gui-top-window.c
--- src/hid/gtk/gui-top-window.c	31 Jan 2008 01:23:09 -0000	1.54
+++ src/hid/gtk/gui-top-window.c	15 Jun 2008 21:36:51 -0000
@@ -2295,6 +2295,11 @@ ghid_build_pcb_top_window (void)
   gtk_box_pack_start (GTK_BOX (hbox), viewport, TRUE, TRUE, 0);
 
   gport->drawing_area = gtk_drawing_area_new ();
+  gtk_widget_set_gl_capability (gport->drawing_area,
+                                gport->glconfig,
+                                NULL,
+                                TRUE,
+                                GDK_GL_RGBA_TYPE);
 
   gtk_widget_add_events (gport->drawing_area, GDK_EXPOSURE_MASK
 			 | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
@@ -2657,11 +2662,23 @@ ghid_parse_arguments (int *argc, char **
   gtk_disable_setlocale ();
 
   gtk_init (argc, argv);
+  gtk_gl_init(argc, argv);
 
   gport = &ghid_port;
   gport->zoom = 300.0;
   pixel_slop = 300;
 
+  /* setup GL-context */
+  gport->glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB   |
+                                               GDK_GL_MODE_ALPHA |
+                                               GDK_GL_MODE_STENCIL |
+//                                               GDK_GL_MODE_DEPTH |
+                                               GDK_GL_MODE_DOUBLE);
+  if (!gport->glconfig) {
+    printf("Could not setup GL-context!\n");
+    return; /* Should we abort? */
+  }
+
   ghid_config_files_read (argc, argv);
 
   Settings.AutoPlace = 0;
Index: src/hid/gtk/gui.h
===================================================================
RCS file: /cvsroot/pcb/pcb/src/hid/gtk/gui.h,v
retrieving revision 1.25
diff -U3 -p -r1.25 gui.h
--- src/hid/gtk/gui.h	13 Apr 2008 14:15:38 -0000	1.25
+++ src/hid/gtk/gui.h	15 Jun 2008 21:36:52 -0000
@@ -35,6 +35,10 @@
 
 #include <gtk/gtk.h>
 
+#include <gtk/gtkgl.h>
+#include <GL/glu.h>
+//#include <GL/glut.h>
+
 /* Internationalization support.
 */
 #if defined (ENABLE_NLS)
@@ -197,6 +201,10 @@ typedef struct
   GdkDrawable *drawable;	/* Current drawable for drawing routines */
   gint width, height;
 
+  GdkGLConfig *glconfig;
+
+  gint trans_lines;
+
   GdkGC *bg_gc, *offlimits_gc, *mask_gc, *u_gc, *grid_gc;
 
   GdkColor bg_color, offlimits_color, grid_color;

_______________________________________________
geda-dev mailing list
[email protected]
http://www.seul.org/cgi-bin/mailman/listinfo/geda-dev

Reply via email to