This is generally a bit crufty, but for your amusement, see the attached
patch. It breaks drawing the mask layer, cursor and rubber-band lines,
but is a stab at making PCB render (translucent drawing) with GL.

Its frame-rate on my complex power controller board at minimum zoom is
about 2.4 frames per second. This basically matches the frame-rate of my
similarly crufty test implementation with cairo.

Regards,

-- 
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	14 Jun 2008 16:58:47 -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	14 Jun 2008 16:59:20 -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/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	14 Jun 2008 16:59:20 -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	14 Jun 2008 16:59:20 -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/batch/batch.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/hid/batch/batch.c,v
retrieving revision 1.11
diff -U3 -p -r1.11 batch.c
--- src/hid/batch/batch.c	13 Apr 2008 14:15:38 -0000	1.11
+++ src/hid/batch/batch.c	14 Jun 2008 16:59:23 -0000
@@ -329,6 +329,33 @@ batch_stop_timer (hidval timer)
 {
 }
 
+hidval
+batch_watch_file (int fd, unsigned int condition, void (*func) (hidval watch, int fd, unsigned int condition, hidval user_data),
+    hidval user_data)
+{
+  hidval ret;
+  ret.ptr = NULL;
+  return ret;
+}
+
+void
+batch_unwatch_file (hidval data)
+{
+}
+
+static hidval
+batch_add_block_hook (void (*func) (hidval data), hidval user_data )
+{
+  hidval ret;
+  ret.ptr = NULL;
+  return ret;
+}
+
+static void
+batch_stop_block_hook (hidval mlpoll)
+{
+}
+
 static void
 batch_log (const char *fmt, ...)
 {
@@ -454,6 +481,10 @@ HID batch_gui = {
   batch_set_crosshair,
   batch_add_timer,
   batch_stop_timer,
+  batch_watch_file,
+  batch_unwatch_file,
+  batch_add_block_hook,
+  batch_stop_block_hook,
   batch_log,
   batch_logv,
   batch_confirm_dialog,
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	14 Jun 2008 16:59:26 -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	14 Jun 2008 16:59:29 -0000
@@ -32,6 +32,9 @@
 #include <gdk/gdkx.h>
 #endif
 
+#include <gtk/gtkgl.h>
+#include <GL/glut.h>
+
 #ifdef HAVE_LIBDMALLOC
 #include <dmalloc.h>
 #endif
@@ -49,6 +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,44 +480,73 @@ 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;
+
+  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;
+  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;
+
+  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);
+
+      if (w > w_src && h > h_src)
+        interp_type = GDK_INTERP_NEAREST;
+      else
+        interp_type = GDK_INTERP_BILINEAR;
+
+      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);
+}
 
 void
 ghid_invalidate_all ()
 {
+#if 0
   int eleft, eright, etop, ebottom;
   BoxType region;
 
@@ -569,10 +604,13 @@ ghid_invalidate_all ()
 
   hid_expose_callback (&ghid_hid, &region, 0);
   draw_grid ();
+#endif
   if (ghidgui->need_restore_crosshair)
     RestoreCrosshair (FALSE);
   ghidgui->need_restore_crosshair = FALSE;
-  ghid_screen_update ();
+//  ghid_screen_update ();
+  gdk_window_invalidate_rect (gport->drawing_area->window, NULL, 1);
+//  gdk_window_process_updates (gport->drawing_area->window, FALSE);
 }
 
 
@@ -583,8 +621,15 @@ 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;
+#if 0
+    cairo_pop_group_to_source (gport->cr);
+    cairo_paint_with_alpha (gport->cr, 0.7);
+    cairo_push_group (gport->cr);
+#endif
     return /*pinout ? 1 : */ PCB->Data->Layer[idx].On;
+  }
   if (idx < 0)
     {
       switch (SL_TYPE (idx))
@@ -596,6 +641,13 @@ ghid_set_layer (const char *name, int gr
 	    return TEST_FLAG (SHOWMASKFLAG, PCB);
 	  return 0;
 	case SL_SILK:
+          //cairo_pop_group_to_source (gport->cr);
+          //if (gport->trans_lines)
+            //cairo_paint (gport->cr);
+          //else
+            //cairo_paint_with_alpha (gport->cr, 0.7);
+          //cairo_push_group (gport->cr);
+          gport->trans_lines = FALSE;
 	  if (SL_MYSIDE (idx) /*|| pinout */ )
 	    return PCB->ElementOn;
 	  return 0;
@@ -625,6 +677,9 @@ ghid_use_mask (int use_it)
     {
     case HID_MASK_OFF:
       gport->drawable = gport->pixmap;
+      //if (gport->cr) cairo_destroy (gport->cr);
+      //gport->cr = gdk_cairo_create (gport->drawable);
+
       mask_seq = 0;
       break;
 
@@ -636,6 +691,8 @@ ghid_use_mask (int use_it)
       if (!gport->mask)
 	gport->mask = gdk_pixmap_new (0, gport->width, gport->height, 1);
       gport->drawable = gport->mask;
+      //if (gport->cr) cairo_destroy (gport->cr);
+      //gport->cr = gdk_cairo_create (gport->drawable);
       mask_seq = 0;
       if (!gport->mask_gc)
 	{
@@ -647,6 +704,7 @@ ghid_use_mask (int use_it)
 			  gport->width, gport->height);
       color.pixel = 0;
       gdk_gc_set_foreground (gport->mask_gc, &color);
+      printf ("Mask clearing\n");
       break;
 
     case HID_MASK_AFTER:
@@ -656,6 +714,8 @@ ghid_use_mask (int use_it)
       mask_seq = mask_seq_id;
 
       gport->drawable = gport->pixmap;
+      //if (gport->cr) cairo_destroy (gport->cr);
+      //gport->cr = gdk_cairo_create (gport->drawable);
       break;
 
     }
@@ -674,6 +734,9 @@ typedef struct
   GdkColor color;
   int xor_set;
   GdkColor xor_color;
+  double red;
+  double green;
+  double blue;
 } ColorCache;
 
 
@@ -716,11 +779,132 @@ ghid_set_special_colors (HID_Attribute *
     }
 }
 
+static void *cache = 0;
+
+void
+ghid_cairo_set_color (hidGC gc, const char *name)
+{
+  //static void *cache = 0;
+  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 (!gc->gc)
+//    return;
+  if (gport->colormap == 0)
+    gport->colormap = gtk_widget_get_colormap (gport->top_window);
+#if 0
+if (1)
+#else
+  if (strcmp (name, "erase") == 0)
+    {
+//      gdk_cairo_set_source_color (gport->cr, &gport->bg_color);
+      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)
+    {
+//      gdk_cairo_set_source_color (gport->cr, &gport->offlimits_color);
+      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
+#endif
+    {
+      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)
+	    {
+#if 0
+	      cc->xor_color.red = cc->color.red ^ gport->bg_color.red;
+	      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.;
+#endif
+	      cc->xor_set = 1;
+	    }
+//	  gdk_gc_set_foreground (gc->gc, &cc->xor_color);
+//          gdk_cairo_set_source_color (gport->cr, &cc->xor_color);
+//          cairo_set_source_rgb (gport->cr, cc->red, cc->green, cc->blue);
+	}
+      else
+	{
+//	  gdk_gc_set_foreground (gc->gc, &cc->color);
+//          gdk_cairo_set_source_color (gport->cr, &cc->color);
+//          cairo_set_source_rgb (gport->cr, cc->red, cc->green, cc->blue);
+	}
+
+      gc->erase = 0;
+    }
+  if (1) {
+    double maxi, mult;
+//    cairo_pattern_get_rgba (cairo_get_source (gport->cr), &r, &g, &b, &a);
+    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);
+    r = r * mult;
+    g = g * mult;
+    b = b * mult;
+//    cairo_set_source_rgba (gport->cr, r, g, b, a);
+  }
+}
+
 void
 ghid_set_color (hidGC gc, const char *name)
 {
-  static void *cache = 0;
   hidval cval;
+//  if (gport->cr) ghid_cairo_set_color (gc, name);
+#if 0
+  return;
+#else
+  //static void *cache = 0;
 
   if (name == NULL)
     {
@@ -764,6 +948,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 +961,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);
@@ -785,12 +975,35 @@ ghid_set_color (hidGC gc, const char *na
 
       gc->erase = 0;
     }
+#endif
+}
+
+static void
+ghid_cairo_set_line_cap (hidGC gc, EndCapStyle style)
+{
+  switch (style)
+    {
+    case Trace_Cap:
+    case Round_Cap:
+      gc->cairo_cap = CAIRO_LINE_CAP_ROUND;
+      gc->cairo_join = CAIRO_LINE_JOIN_ROUND;
+      break;
+    case Square_Cap:
+    case Beveled_Cap:
+      gc->cairo_cap = CAIRO_LINE_CAP_SQUARE;
+      gc->cairo_join = CAIRO_LINE_JOIN_MITER;
+      break;
+    }
+  // GDK_LINE_SOLID,
+//  cairo_set_line_cap (gport->cr, gc->cairo_cap);
+//  cairo_set_line_join (gport->cr, gc->cairo_join);
 }
 
 void
 ghid_set_line_cap (hidGC gc, EndCapStyle style)
 {
-
+//  if (gport->cr) ghid_cairo_set_line_cap (gc, style);
+#if 1
   switch (style)
     {
     case Trace_Cap:
@@ -804,31 +1017,58 @@ ghid_set_line_cap (hidGC gc, EndCapStyle
       gc->join = GDK_JOIN_MITER;
       break;
     }
+#endif
+#if 0
   if (gc->gc)
     gdk_gc_set_line_attributes (WHICH_GC (gc),
 				Vz (gc->width), GDK_LINE_SOLID,
 				gc->cap, gc->join);
+#endif
+}
+
+static void
+ghid_cairo_set_line_width (hidGC gc, int width)
+{
+  int s_width;
+  gc->width = width;
+  s_width = Vz(gc->width);
+  if (s_width == 0) s_width = 1;
+//  cairo_set_line_width (gport->cr, s_width);
+  // GDK_LINE_SOLID,
+//  cairo_set_line_join (gport->cr, gc->cairo_join);
+  // gc->join
+//  cairo_set_line_cap (gport->cr, gc->cairo_cap);
 }
 
 void
 ghid_set_line_width (hidGC gc, int width)
 {
-
+//  if (gport->cr) ghid_cairo_set_line_width (gc, width);
   gc->width = width;
+#if 0
   if (gc->gc)
     gdk_gc_set_line_attributes (WHICH_GC (gc),
 				Vz (gc->width), GDK_LINE_SOLID,
 				gc->cap, gc->join);
+#endif
+}
+
+static void
+ghid_cairo_set_draw_xor (hidGC gc, int xor)
+{
+//  cairo_set_operator (gport->cr, xor ? CAIRO_OPERATOR_XOR : CAIRO_OPERATOR_OVER);
+//  ghid_cairo_set_color (gc, gc->colorname);
 }
 
 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);
+//  gc->xor = xor;
+//  if (gport->cr) ghid_cairo_set_draw_xor (gc, xor);
+//  if (!gc->gc)
+//    return;
+//  gdk_gc_set_function (gc->gc, xor ? GDK_XOR : GDK_COPY);
+//  ghid_set_color (gc, gc->colorname);
 }
 
 void
@@ -846,8 +1086,18 @@ ghid_set_line_cap_angle (hidGC gc, int x
 static int
 use_gc (hidGC gc)
 {
-  if (!gport->pixmap)
+  static hidGC last_gc = 0;
+
+  if (last_gc == gc) return 1;
+
+  last_gc = gc;
+#if 0
+  if (!gport->pixmap) {
+    printf ("NULL pixmap\n");
     return 0;
+  }
+#endif
+#if 0
   if (!gc->gc)
     {
       gc->gc = gdk_gc_new (gport->top_window->window);
@@ -856,6 +1106,8 @@ use_gc (hidGC gc)
       ghid_set_line_cap (gc, gc->cap);
       ghid_set_draw_xor (gc, gc->xor);
     }
+#endif
+#if 0
   if (gc->mask_seq != mask_seq)
     {
       if (mask_seq)
@@ -865,25 +1117,135 @@ use_gc (hidGC gc)
       gc->mask_seq = mask_seq;
     }
   gport->u_gc = WHICH_GC (gc);
+#endif
+#if 0
+  ghid_cairo_set_color (gc, gc->colorname);
+  ghid_cairo_set_line_width (gc, gc->width);
+  ghid_cairo_set_line_cap (gc, gc->cap);
+//  ghid_cairo_set_draw_xor (gc, gc->xor);
+#endif
   return 1;
 }
 
+#ifndef CALLBACK
+#define CALLBACK
+#endif
+
+void CALLBACK errorCallback(GLenum errorCode)
+{
+   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;
+  GLUquadricObj *qobj;
+  double width;
 
-  dx1 = Vx ((double)x1);
-  dy1 = Vy ((double)y1);
-  dx2 = Vx ((double)x2);
-  dy2 = Vy ((double)y2);
+  GLfloat mat_ambient[] = { 0.5, 0.5, 0.5, 1.0 };
+  GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
+  GLfloat mat_shininess[] = { 50.0 };
+  GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
+  GLfloat model_ambient[] = { 0.5, 0.5, 0.5, 1.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;
 
-  USE_GC (gc);
-  gdk_draw_line (gport->drawable, gport->u_gc, dx1, dy1, dx2, dy2);
+//  glClearColor(0.0, 0.0, 0.0, 0.0);
+
+//  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+  glShadeModel (GL_SMOOTH);
+
+  glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
+  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
+  glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
+  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
+  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, model_ambient);
+
+  glEnable(GL_LIGHTING);
+  glEnable(GL_LIGHT0);
+  glEnable(GL_DEPTH_TEST);
+
+  dx1 = Vx (x1)+0.5;
+  dy1 = Vy (y1)+0.5;
+  dx2 = Vx (x2)+0.5;
+  dy2 = Vy (y2)+0.5;
+
+  width = Vz (gc->width);
+
+  if (width == 0.0)
+    width = 1.0;
+
+#if 0
+/\
+\ \
+ \ \
+  \ \
+   \ \
+    \/
+ _
+| |
+| |
+| |
+| |
+|_|
+#endif
+
+{
+  float deltax, deltay, length;
+  float wdx, wdy;
+
+  deltax = dx2 - dx1;
+  deltay = dy2 - dy1;
+
+  length = sqrt (deltax * deltax + deltay * deltay);
+
+  wdy = deltax * width / 2 / length;
+  wdx = -deltay * width / 2 / length;
+
+  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 1
+  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);
+  gluDisk (qobj, 0, width / 2, 50, 1);
+  glPopMatrix();
+
+  glPushMatrix();
+  glTranslatef (dx2, dy2, 0.0);
+  gluDisk (qobj, 0, width / 2, 50, 1);
+  glPopMatrix();
+#endif
+
+#if 0
+  ghid_cairo_set_color (gc, gc->colorname);
+  ghid_cairo_set_line_width (gc, gc->width);
+  ghid_cairo_set_line_cap (gc, gc->cap);
+//  ghid_cairo_set_draw_xor (gc, gc->xor);
+#endif
+//  USE_GC (gc);
 }
 
 void
@@ -906,7 +1268,6 @@ ghid_draw_arc (hidGC gc, int cx, int cy,
   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)
@@ -920,9 +1281,18 @@ ghid_draw_arc (hidGC gc, int cx, int cy,
       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);
+  //cairo_new_sub_path (gport->cr);
+
+  //cairo_save (gport->cr);
+  //cairo_translate (gport->cr, Vx(cx) + 0.5, Vy(cy) + 0.5);
+  //cairo_scale (gport->cr, vrx, vry);
+  if (delta_angle < 0) {
+    //cairo_arc (gport->cr, 0., 0., 1., (180 - start_angle) * (M_PI / 180.), (180 - start_angle - delta_angle) * (M_PI / 180.));
+  } else {
+    //cairo_arc_negative (gport->cr, 0., 0., 1., (180 - start_angle) * (M_PI / 180.), (180 - start_angle - delta_angle) * (M_PI / 180.));
+  }
+  //cairo_restore (gport->cr);
+  //cairo_stroke (gport->cr);
 }
 
 void
@@ -953,8 +1323,8 @@ ghid_draw_rect (hidGC gc, int x1, int y1
   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);
+  //cairo_rectangle (gport->cr, x1 + 0.5, y1 + 0.5, x2 - x1 + 1, y2 - y1 + 1);
+  //cairo_stroke (gport->cr);
 }
 
 
@@ -973,31 +1343,26 @@ 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);
+
+  //cairo_new_sub_path (gport->cr);
+  //cairo_arc (gport->cr, Vx(cx) + 0.5, Vy(cy) + 0.5, vr, 0, 2 * M_PI);
+  //cairo_fill (gport->cr);
 }
 
 void
 ghid_fill_polygon (hidGC gc, int n_coords, int *x, int *y)
 {
-  static GdkPoint *points = 0;
-  static int npoints = 0;
   int i;
   USE_GC (gc);
 
-  if (npoints < n_coords)
-    {
-      npoints = n_coords + 1;
-      points = MyRealloc (points,
-			  npoints * sizeof (GdkPoint), (char *) __FUNCTION__);
-    }
-  for (i = 0; i < n_coords; i++)
+  g_assert (n_coords > 0);
+  //cairo_move_to (gport->cr, Vx (x[0]) + 0.5, Vy (y[0]) + 0.5);
+  for (i = 1; i < n_coords; i++)
     {
-      points[i].x = Vx (x[i]);
-      points[i].y = Vy (y[i]);
+      //cairo_line_to (gport->cr, Vx (x[i]) + 0.5, Vy (y[i]) + 0.5);
     }
-  gdk_draw_polygon (gport->drawable, gport->u_gc, 1, points, n_coords);
+  //cairo_close_path (gport->cr);
+  //cairo_fill (gport->cr);
 }
 
 void
@@ -1036,8 +1401,8 @@ ghid_fill_rect (hidGC gc, int x1, int y1
       y2 = yy;
     }
   USE_GC (gc);
-  gdk_draw_rectangle (gport->drawable, gport->u_gc, TRUE,
-                      x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+  //cairo_rectangle (gport->cr, x1 + 0.5, y1 + 0.5, x2 - x1 + 1, y2 - y1 + 1);
+  //cairo_fill (gport->cr);
 }
 
 void
@@ -2160,11 +2525,22 @@ Benchmark (int argc, char **argv, int x,
   region.X2 = PCB->MaxWidth;
   region.Y2 = PCB->MaxHeight;
 
+  
+
   gdk_display_sync (display);
   time (&start);
   do
     {
+      gdk_window_invalidate_rect (gport->drawing_area->window, NULL, 1);
+      gdk_window_process_updates (gport->drawing_area->window, FALSE);
+      
+//      ghid_port_drawing_area_expose_event_cb (gport->drawing_area, NULL, gport);
+#if 0
+      cairo_push_group (gport->cr);
       hid_expose_callback (&ghid_hid, &region, 0);
+      cairo_pop_group_to_source (gport->cr);
+      cairo_paint_with_alpha (gport->cr, 0.7);
+#endif
       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	14 Jun 2008 16:59:29 -0000
@@ -300,12 +300,14 @@ ghid_show_crosshair (gboolean show)
   static GdkGC *xor_gc;
   static GdkColor cross_color;
 
+  return;
+
   if (gport->x_crosshair < 0 || ghidgui->creating || !gport->has_entered)
     return;
 
   if (!xor_gc)
     {
-      xor_gc = gdk_gc_new (ghid_port.drawing_area->window);
+      xor_gc = gdk_gc_new (ghid_port.drawable);
       gdk_gc_copy (xor_gc, ghid_port.drawing_area->style->white_gc);
       gdk_gc_set_function (xor_gc, GDK_XOR);
       /* FIXME: when CrossColor changed from config */
@@ -316,42 +318,32 @@ ghid_show_crosshair (gboolean show)
 
   gdk_gc_set_foreground (xor_gc, &cross_color);
 
+#if 1
   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);
+      gdk_draw_line (gport->drawable, xor_gc, x_prev, 0, x_prev, gport->height);
+      gdk_draw_line (gport->drawable, 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);
-	}
+        {
+          gdk_draw_rectangle (gport->drawable, xor_gc, TRUE, 0, y_prev - VCD, VCD, VCW);
+          gdk_draw_rectangle (gport->drawable, xor_gc, TRUE, gport->width - VCD, y_prev - VCD, VCD, VCW);
+          gdk_draw_rectangle (gport->drawable, xor_gc, TRUE, x_prev - VCD, 0, VCW, VCD);
+          gdk_draw_rectangle (gport->drawable, xor_gc, TRUE, x_prev - VCD, gport->height - VCD, VCW, VCD);
+        }
     }
+#endif
 
   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);
+      gdk_draw_line (gport->drawable, xor_gc, x, 0, x, gport->height);
+      gdk_draw_line (gport->drawable, 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);
-	}
+        {
+          gdk_draw_rectangle (gport->drawable, xor_gc, TRUE, 0, y - VCD, VCD, VCW);
+          gdk_draw_rectangle (gport->drawable, xor_gc, TRUE, gport->width - VCD, y - VCD, VCD, VCW);
+          gdk_draw_rectangle (gport->drawable, xor_gc, TRUE, x - VCD, 0, VCW, VCD);
+          gdk_draw_rectangle (gport->drawable, xor_gc, TRUE, x - VCD, gport->height - VCD, VCW, VCD);
+        }
       x_prev = x;
       y_prev = y;
     }
@@ -757,26 +749,238 @@ ghid_port_drawing_area_configure_event_c
   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;
+  GdkDrawable *save_drawable;
+  GdkGLContext* pGlContext = gtk_widget_get_gl_context (widget);
+  GdkGLDrawable* pGlDrawable = gtk_widget_get_gl_drawable (widget);
+  GLuint auiColorBuffer;
+  cairo_surface_t *dsurf;
+  /* Should be elsewhere */
+  static guchar *surface_data;
+  /* Should be elsewhere */
+
+  save_drawable = gport->drawable;
+  gport->drawable = widget->window;
+
   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)) {
+    printf ("FUBAR\n");
+    return FALSE;
+  }
+
+//  glEnable (GL_BLEND);
+//  glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+//  glShadeModel (GL_FLAT);
+
+#if 0
+  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+
+  glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB,
+                   GL_TEXTURE_MIN_FILTER,
+                   GL_LINEAR_MIPMAP_LINEAR);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB,
+                   GL_TEXTURE_MAG_FILTER,
+                   GL_LINEAR);
+#endif
+
+  glViewport (0, 0, ev->area.width, ev->area.height);
+
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+//  gluPerspective (2.0f * FOVY_2, (GLfloat) ev->area.width / (GLfloat) ev->area.height, 0.0f, 50.0f);
+  glOrtho (0, ev->area.width, ev->area.height, 0, 0, 100);
+//  glOrtho(-2.5, 2.5, -2.5, 2.5, -10.0, 10.0);
+
+  glMatrixMode (GL_MODELVIEW);
+  glLoadIdentity ();
+#if 0
+  gluLookAt (0.0f, 0.0f, Z_NEAR,
+             0.0f, 0.0f, 0.0f,
+             0.0f, 1.0f, 0.0f);
+#endif
+  glTranslatef (0.0f, 0.0f, -Z_NEAR);
+
+  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+#if 0
+//  if (surface_data == NULL)
+    g_free (surface_data);
+    surface_data = g_malloc0 (4 * ev->area.width * ev->area.height);
+
+  dsurf = cairo_image_surface_create_for_data (surface_data, CAIRO_FORMAT_ARGB32,
+                                               ev->area.width, ev->area.height,
+                                               4 * ev->area.width);
+
+  if (gport->cr) cairo_destroy (gport->cr);
+  gport->cr = cairo_create (dsurf);
+#endif
+
+  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));
+
+//  cairo_push_group (gport->cr);
+
+  hid_expose_callback (&ghid_hid, &region, 0);
+#if 0
+  cairo_pop_group_to_source (gport->cr);
+  cairo_paint_with_alpha (gport->cr, 0.7);
+  draw_grid ();
+
+  DrawAttached (TRUE);
   ghid_show_crosshair (TRUE);
+
+  gport->drawable = save_drawable;
+
+  glGenTextures (1, &auiColorBuffer);
+
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, auiColorBuffer);
+  glTexImage2D (GL_TEXTURE_RECTANGLE_ARB,
+                0, GL_RGBA, ev->area.width, ev->area.height,
+                0, GL_BGRA, GL_UNSIGNED_BYTE,
+                surface_data);
+#endif
+
+#if 0
+  {
+    float GLhwidth;
+    GLhwidth = 1.0 * (float)ev->area.width / (float)ev->area.height;
+
+    glBegin (GL_QUADS);
+    glNormal3f (0.0f, 0.0f, 1.0f);
+    glTexCoord2f ((GLfloat) ev->area.width, 0.0f);
+    glVertex3f (GLhwidth, 1.0f, 0.0f);
+    glTexCoord2f (0.0f, 0.0f);
+    glVertex3f (-GLhwidth, 1.0f, 0.0f);
+    glTexCoord2f (0.0f, (GLfloat) ev->area.height);
+    glVertex3f (-GLhwidth, -1.0f, 0.0f);
+    glTexCoord2f ((GLfloat) ev->area.width, (GLfloat) ev->area.height);
+    glVertex3f (GLhwidth, -1.0f, 0.0f);
+    glEnd ();
+  }
+#endif
+
+if (0)  {
+  GLUquadricObj *qobj;
+
+  GLfloat mat_ambient[] = { 0.5, 0.5, 0.5, 1.0 };
+  GLfloat mat_specular[] = { 1.0, 1.0, 1.0, 1.0 };
+  GLfloat mat_shininess[] = { 50.0 };
+  GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
+  GLfloat model_ambient[] = { 0.5, 0.5, 0.5, 1.0 };
+
+//  glClearColor(0.0, 0.0, 0.0, 0.0);
+
+//  glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+  glPushMatrix();
+
+  glShadeModel (GL_SMOOTH);
+//  glTranslatef(-1.0, -1.0, 0.0);
+
+  glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
+  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
+  glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
+  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
+  glLightModelfv(GL_LIGHT_MODEL_AMBIENT, model_ambient);
+
+  glEnable(GL_LIGHTING);
+  glEnable(GL_LIGHT0);
+  glEnable(GL_DEPTH_TEST);
+
+  glTranslatef (0, 0, 0);
+
+#if 1
+  qobj = gluNewQuadric();
+
+  gluQuadricDrawStyle(qobj, GLU_FILL); /* smooth shaded */
+  gluQuadricNormals(qobj, GLU_SMOOTH);
+  gluSphere(qobj, 1, 15, 10);
+#endif
+
+//  glutSolidTeapot(1.0);
+
+  glPopMatrix();
+
+  }
+
+//  glPopMatrix ();
+
+  if (gdk_gl_drawable_is_double_buffered (pGlDrawable))
+    gdk_gl_drawable_swap_buffers (pGlDrawable);
+  else
+    glFlush ();
+
+//  glDeleteTextures (1, &auiColorBuffer);
+
+  /* end drawing to current GL-context */
+  gdk_gl_drawable_gl_end (pGlDrawable);
+
   return FALSE;
 }
 
@@ -789,6 +993,7 @@ ghid_port_window_motion_cb (GtkWidget * 
   static gint x_prev = -1, y_prev = -1;
   gboolean moved;
   GdkModifierType state;
+  GdkDrawable *save_drawable;
 
   state = (GdkModifierType) (ev->state);
   mk = ghid_modifier_keys_state (&state);
@@ -808,9 +1013,14 @@ ghid_port_window_motion_cb (GtkWidget * 
     }
   x_prev = y_prev = -1;
   moved = ghid_note_event_location (ev);
+
+  save_drawable = gport->drawable;
+  gport->drawable = gport->drawing_area->window;
   ghid_show_crosshair (TRUE);
+  gport->drawable = save_drawable;
   if (moved && have_crosshair_attachments ())
     ghid_draw_area_update (gport, NULL);
+
   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	14 Jun 2008 16:59:31 -0000
@@ -2295,6 +2295,13 @@ ghid_build_pcb_top_window (void)
   gtk_box_pack_start (GTK_BOX (hbox), viewport, TRUE, TRUE, 0);
 
   gport->drawing_area = gtk_drawing_area_new ();
+#if 1
+  gtk_widget_set_gl_capability (gport->drawing_area,
+                                gport->glconfig,
+                                NULL,
+                                TRUE,
+                                GDK_GL_RGBA_TYPE);
+#endif
 
   gtk_widget_add_events (gport->drawing_area, GDK_EXPOSURE_MASK
 			 | GDK_LEAVE_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK
@@ -2657,11 +2664,27 @@ ghid_parse_arguments (int *argc, char **
   gtk_disable_setlocale ();
 
   gtk_init (argc, argv);
+#if 1
+  gtk_gl_init(argc, argv);
+  glutInit(argc, *argv);
+#endif
 
   gport = &ghid_port;
   gport->zoom = 300.0;
   pixel_slop = 300;
 
+#if 1
+  /* setup GL-context */
+  gport->glconfig = gdk_gl_config_new_by_mode (GDK_GL_MODE_RGB   |
+                                               GDK_GL_MODE_ALPHA |
+                                               GDK_GL_MODE_DEPTH |
+                                               GDK_GL_MODE_DOUBLE);
+  if (!gport->glconfig) {
+    printf("Could not setup GL-context!\n");
+    return; /* Should we abort? */
+  }
+#endif
+
   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	14 Jun 2008 16:59:31 -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)
@@ -128,6 +132,8 @@ typedef struct hid_gc_struct
   gchar *colorname;
   gint width;
   gint cap, join;
+  cairo_line_cap_t cairo_cap;
+  cairo_line_join_t cairo_join;
   gchar xor;
   gchar erase;
   gint mask_seq;
@@ -197,6 +203,11 @@ typedef struct
   GdkDrawable *drawable;	/* Current drawable for drawing routines */
   gint width, height;
 
+  GdkGLConfig *glconfig;
+
+  cairo_t *cr;
+  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