[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: gEDA-dev: Faster PCB + GL



On Mon, 2008-06-23 at 00:03 +0000, Kai-Martin Knaak wrote:
> On Sun, 22 Jun 2008 20:26:10 +0100, Peter Clifton wrote:
> 
> >> * The view window blanks at certain events:
> >>     --> If an overlapping window is moved in front of pcb --> When a
> >>     tool tip about a window decoration closes --> When a pcb menu
> >>     closes without selecting an action --> When a sub menu closes -->
> >>     When gnome shows the mouse locator (as mentioned before)
> >>   I'd guess, these are all symptoms of the same redraw illness.
> 
> Another snippet on the redraw problem: If I move a small window above the 
> viewport of pcb, I get an empty viewport plus a rectangle in the lower 
> left  with part of the layout. The dimensions of the rectangle look 
> suspiciously similar to the size of the small window. The layout rendered 
> over there is not quite what should be shown there -- It is taken from 
> the upper left of the viewport.

Turns out my expose events were't setting up the view matrix and
clipping regions. My code only worked for full window expose events.

Try the attached, it should address many of the earlier usability
issues:

  Redraw works
  Component library preview works
  NoHoles polygon contour caches (seem) to update OK
  Grid is reinstated
  Colours from selected objects don't bleed into other via holes

Still to fix:
  Mark / locked indicator drawing
 

Patch is against CVS head.
-- 
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	23 Jun 2008 13:32:18 -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/create.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/create.c,v
retrieving revision 1.42
diff -U3 -p -r1.42 create.c
--- src/create.c	2 May 2007 03:17:58 -0000	1.42
+++ src/create.c	23 Jun 2008 13:32:20 -0000
@@ -600,6 +600,7 @@ CreateNewPolygon (LayerTypePtr Layer, Fl
   polygon->Flags = Flags;
   polygon->ID = ID++;
   polygon->Clipped = NULL;
+  polygon->NoHoles = NULL;
   return (polygon);
 }
 
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	23 Jun 2008 13:32: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/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	23 Jun 2008 13:32:20 -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);
@@ -532,7 +531,7 @@ DrawEverything (BoxTypePtr drawn_area)
 	r_search (PCB->Data->element_tree, drawn_area, NULL, EMark_callback,
 		  NULL);
       /* Draw rat lines on top */
-      if (PCB->RatOn)
+      if (PCB->RatOn && gui->set_layer ("rats", SL (RATS, 0)))
 	DrawRats(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;
 }
@@ -702,6 +701,8 @@ clearPad_callback (const BoxType * b, vo
   return 1;
 }
 
+#define MASK_SUBCOMPOSITE_SILK 0
+
 /* ---------------------------------------------------------------------------
  * Draws silk layer.
  */
@@ -724,11 +725,27 @@ DrawSilk (int new_swap, int layer, BoxTy
       gui->use_mask (HID_MASK_BEFORE);
 #endif
       DrawLayer (LAYER_PTR (max_layer + layer), drawn_area);
+
+#if MASK_SUBCOMPOSITE_SILK
+      gui->use_mask (HID_MASK_BEFORE);
+      gui->use_mask (HID_MASK_CLEAR);
+      gui->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
+      gui->use_mask (HID_MASK_BEFORE);
+#endif
+
       /* draw package */
       r_search (PCB->Data->element_tree, drawn_area, NULL, frontE_callback,
 		NULL);
       r_search (PCB->Data->name_tree[NAME_INDEX (PCB)], drawn_area, NULL,
 		frontN_callback, NULL);
+
+#if MASK_SUBCOMPOSITE_SILK
+      gui->use_mask (HID_MASK_AFTER);
+      gui->set_color (Output.fgGC, PCB->ElementColor);
+      gui->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
+      gui->use_mask (HID_MASK_OFF);
+#endif
+
 #if 0
     }
 
@@ -851,6 +868,7 @@ text_callback (const BoxType * b, void *
   return 1;
 }
 
+#define MASK_SUBCOMPOSITE_LAYERS 0
 
 /* ---------------------------------------------------------------------------
  * draws one non-copper layer
@@ -860,6 +878,13 @@ DrawLayer (LayerTypePtr Layer, BoxType *
 {
   struct pin_info info;
 
+#if MASK_SUBCOMPOSITE_LAYERS
+  gui->use_mask (HID_MASK_BEFORE);
+  gui->use_mask (HID_MASK_CLEAR);
+  gui->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
+  gui->use_mask (HID_MASK_BEFORE);
+#endif
+
   /* print the non-clearing polys */
   info.Layer = Layer;
   info.arg = False;
@@ -875,8 +900,17 @@ DrawLayer (LayerTypePtr Layer, BoxType *
   /* draw the layer text on screen */
   r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
   clip_box = NULL;
+
+#if MASK_SUBCOMPOSITE_LAYERS
+  gui->use_mask (HID_MASK_AFTER);
+  gui->set_color (Output.fgGC, Layer->Color);
+  gui->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
+  gui->use_mask (HID_MASK_OFF);
+#endif
 }
 
+#define MASK_SUBCOMPOSITE_LAYER_GROUPS 0
+
 /* ---------------------------------------------------------------------------
  * draws one layer group.  Returns non-zero if pins and pads should be
  * drawn with this group.
@@ -901,6 +935,14 @@ DrawLayerGroup (int group, const BoxType
 	rv = 0;
       if (layernum < max_layer && Layer->On)
 	{
+
+#if MASK_SUBCOMPOSITE_LAYER_GROUPS
+          gui->use_mask (HID_MASK_BEFORE);
+          gui->use_mask (HID_MASK_CLEAR);
+          gui->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
+          gui->use_mask (HID_MASK_BEFORE);
+#endif
+
 	  /* draw all polygons on this layer */
 	  if (Layer->PolygonN)
 	    {
@@ -923,6 +965,12 @@ DrawLayerGroup (int group, const BoxType
 	  /* draw the layer text on screen */
 	  r_search (Layer->text_tree, screen, NULL, text_callback, Layer);
 
+#if MASK_SUBCOMPOSITE_LAYER_GROUPS
+          gui->use_mask (HID_MASK_AFTER);
+          gui->set_color (Output.fgGC, Layer->Color);
+          gui->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
+          gui->use_mask (HID_MASK_OFF);
+#endif
 	}
     }
   if (n_entries > 1)
@@ -2113,8 +2161,16 @@ DrawPlainPolygon (LayerTypePtr Layer, Po
       if (!Gathering)
 	PolygonHoles (clip_box, Layer, Polygon, thin_callback);
     }
-  else if (Polygon->Clipped)
+  else if (Polygon->NoHoles)//(Polygon->Clipped)
     {
+      PolygonType poly;
+      poly.Clipped = Polygon->NoHoles;
+      do {
+        DrawPolygonLowLevel (&poly);
+//        printf ("Drawing no-holes portion of polygon\n");
+        poly.Clipped = poly.Clipped->f;
+      } while (poly.Clipped != Polygon->NoHoles);
+#if 0
       NoHolesPolygonDicer (Polygon, DrawPolygonLowLevel, clip_box);
       /* draw other parts of the polygon if fullpoly flag is set */
       if (TEST_FLAG (FULLPOLYFLAG, Polygon))
@@ -2127,6 +2183,7 @@ DrawPlainPolygon (LayerTypePtr Layer, Po
 	      NoHolesPolygonDicer (&poly, DrawPolygonLowLevel, clip_box);
 	    }
 	}
+#endif
     }
   /* if the gui has the dicer flag set then it won't draw missing poly outlines */
   if (TEST_FLAG (CHECKPLANESFLAG, PCB) && Polygon->Clipped && !Gathering
@@ -2149,10 +2206,7 @@ DrawPlainPolygon (LayerTypePtr Layer, Po
 	    }
 	  gui->set_line_width (Output.fgGC, 1);
 	  for (i = 0; i < n - 1; i++)
-	    {
-	      gui->draw_line (Output.fgGC, x[i], y[i], x[i + 1], y[i + 1]);
-	      /* gui->fill_circle (Output.bgGC, x[i], y[i], 10); */
-	    }
+	    gui->draw_line (Output.fgGC, x[i], y[i], x[i + 1], y[i + 1]);
 	  gui->draw_line (Output.fgGC, x[n - 1], y[n - 1], x[0], y[0]);
 	  free (x);
 	  free (y);
@@ -2160,6 +2214,7 @@ DrawPlainPolygon (LayerTypePtr Layer, Po
     }
 }
 
+
 /* ---------------------------------------------------------------------------
  * draws an element
  */
@@ -2171,6 +2226,8 @@ DrawElement (ElementTypePtr Element, int
   DrawElementPinsAndPads (Element, unused);
 }
 
+#define MASK_SUBCOMPOSITE_ELEMENT_NAMES 0
+
 /* ---------------------------------------------------------------------------
  * draws the name of an element
  */
@@ -2179,6 +2236,16 @@ DrawElementName (ElementTypePtr Element,
 {
   if (TEST_FLAG (HIDENAMEFLAG, Element))
     return;
+
+#if MASK_SUBCOMPOSITE_ELEMENT_NAMES
+  gui->use_mask (HID_MASK_BEFORE);
+  gui->use_mask (HID_MASK_CLEAR);
+  gui->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
+  gui->use_mask (HID_MASK_BEFORE);
+
+  DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
+#endif
+
   if (doing_pinout || doing_assy)
     gui->set_color (Output.fgGC, PCB->ElementColor);
   else if (TEST_FLAG (SELECTEDFLAG, &ELEMENT_TEXT (PCB, Element)))
@@ -2187,15 +2254,33 @@ DrawElementName (ElementTypePtr Element,
     gui->set_color (Output.fgGC, PCB->ElementColor);
   else
     gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
+
+#if MASK_SUBCOMPOSITE_ELEMENT_NAMES
+  gui->use_mask (HID_MASK_AFTER);
+  gui->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
+  gui->use_mask (HID_MASK_OFF);
+#else
   DrawTextLowLevel (&ELEMENT_TEXT (PCB, Element), PCB->minSlk);
+#endif
 }
 
+#define MASK_SUBCOMPOSITE_ELEMENT_PACKAGE 0
+
 /* ---------------------------------------------------------------------------
  * draws the package of an element
  */
 void
 DrawElementPackage (ElementTypePtr Element, int unused)
 {
+#if MASK_SUBCOMPOSITE_ELEMENT_PACKAGE
+  gui->use_mask (HID_MASK_BEFORE);
+  gui->use_mask (HID_MASK_CLEAR);
+  gui->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
+  gui->use_mask (HID_MASK_BEFORE);
+
+  DrawElementPackageLowLevel (Element, unused);
+#endif
+
   /* set color and draw lines, arcs, text and pins */
   if (doing_pinout || doing_assy)
     gui->set_color (Output.fgGC, PCB->ElementColor);
@@ -2205,7 +2290,14 @@ DrawElementPackage (ElementTypePtr Eleme
     gui->set_color (Output.fgGC, PCB->ElementColor);
   else
     gui->set_color (Output.fgGC, PCB->InvisibleObjectsColor);
+
+#if MASK_SUBCOMPOSITE_ELEMENT_PACKAGE
+  gui->use_mask (HID_MASK_AFTER);
+  gui->fill_rect (Output.fgGC, 0, 0, PCB->MaxWidth, PCB->MaxHeight);
+  gui->use_mask (HID_MASK_OFF);
+#else
   DrawElementPackageLowLevel (Element, unused);
+#endif
 }
 
 /* ---------------------------------------------------------------------------
Index: src/global.h
===================================================================
RCS file: /cvsroot/pcb/pcb/src/global.h,v
retrieving revision 1.56
diff -U3 -p -r1.56 global.h
--- src/global.h	6 Aug 2007 04:31:00 -0000	1.56
+++ src/global.h	23 Jun 2008 13:32:20 -0000
@@ -204,6 +204,7 @@ typedef struct			/* holds information ab
   Cardinal PointN,		/* number of points in polygon */
     PointMax;			/* max number from malloc() */
   POLYAREA *Clipped;		/* the clipped region of this polygon */
+  POLYAREA *NoHoles;		/* the polygon broken into hole-less regions */
   PointTypePtr Points;		/* data */
 } PolygonType, *PolygonTypePtr;
 
Index: src/hid.h
===================================================================
RCS file: /cvsroot/pcb/pcb/src/hid.h,v
retrieving revision 1.22
diff -U3 -p -r1.22 hid.h
--- src/hid.h	13 Apr 2008 14:15:37 -0000	1.22
+++ src/hid.h	23 Jun 2008 13:32:20 -0000
@@ -194,6 +194,7 @@ extern "C"
 #define SL_INVISIBLE	0x0060
 #define SL_FAB		0x0070
 #define SL_ASSY		0x0080
+#define SL_RATS		0x0090
 /* Callers should use this.  */
 #define SL(type,side) (~0xfff | SL_##type | SL_##side##_SIDE)
 
Index: src/polygon.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/polygon.c,v
retrieving revision 1.59
diff -U3 -p -r1.59 polygon.c
--- src/polygon.c	2 Dec 2007 09:35:40 -0000	1.59
+++ src/polygon.c	23 Jun 2008 13:32:20 -0000
@@ -109,7 +109,7 @@ biggest (POLYAREA * p)
           big = n->contours->area;
         }
     }
-  while ((n = n->f) != p);
+  while ((n = n->f) != p); /* TODO: Decipher this line ... is it pointless? Is it just "n=p"? */
   assert (top);
   if (top == p)
     return p;
@@ -170,6 +170,54 @@ original_poly (PolygonType * p)
   return biggest (np);
 }
 
+static void
+add_noholes_polyarea (PolygonType *noholes_poly, void *user_data)
+{
+  PolygonType *poly = user_data;
+  PLINE *pline;//, last;
+  POLYAREA *new_area;
+
+  new_area = malloc (sizeof (POLYAREA) * 1);
+
+  /* Allocate a new PLINE, COPY the PLINE from the passed polygon */
+  poly_CopyContour (&pline, noholes_poly->Clipped->contours);
+  new_area->contours = pline;
+
+  /* Link the new POLYAREA into the NoHoles circularaly linked list */
+
+  if (poly->NoHoles)
+    {
+      new_area->f = poly->NoHoles;
+      new_area->b = poly->NoHoles->b;
+      poly->NoHoles->b->f = new_area;
+      poly->NoHoles->b = new_area;
+    }
+  else
+    {
+      new_area->f = new_area;
+      new_area->b = new_area;
+    }
+
+  poly->NoHoles = new_area;
+
+}
+
+static void
+compute_noholes (PolygonType *poly)
+{
+  /* TODO: IS THIS RIGHT? */
+  if (poly->NoHoles)
+    {
+      poly_Free (&poly->NoHoles);
+//      printf ("Just leaked in compute_noholes\n");
+    }
+  poly->NoHoles = NULL;
+  if (poly->Clipped)
+    NoHolesPolygonDicer (poly, add_noholes_polyarea, poly, NULL);
+  else
+    printf ("Compute_noholes caught poly->Clipped = NULL\n");
+}
+
 static int
 ClipOriginal (PolygonType * poly)
 {
@@ -183,10 +231,13 @@ ClipOriginal (PolygonType * poly)
       fprintf (stderr, "Error while clipping PBO_ISECT: %d\n", r);
       poly_Free (&result);
       poly->Clipped = NULL;
+      if (poly->NoHoles) printf ("Just leaked in ClipOriginal\n");
+      poly->NoHoles = NULL;
       return 0;
     }
   poly->Clipped = biggest (result);
   assert (!poly->Clipped || poly_Valid (poly->Clipped));
+//  compute_noholes (poly);
   return 1;
 }
 
@@ -480,10 +531,13 @@ Subtract (POLYAREA * np1, PolygonType * 
       fprintf (stderr, "Error while clipping PBO_SUB: %d\n", x);
       poly_Free (&merged);
       p->Clipped = NULL;
+      if (p->NoHoles) printf ("Just leaked in Subtract\n");
+      p->NoHoles = NULL;
       return -1;
     }
   p->Clipped = biggest (merged);
   assert (!p->Clipped || poly_Valid (p->Clipped));
+//  compute_noholes (p);
   if (!p->Clipped)
     Message ("Polygon cleared out of existence near (%d, %d)\n",
              (p->BoundingBox.X1 + p->BoundingBox.X2) / 2,
@@ -754,6 +808,7 @@ clearPoly (DataTypePtr Data, LayerTypePt
       if (info.solder || group == Group (Data, max_layer + COMPONENT_LAYER))
 	r += r_search (Data->pad_tree, &region, NULL, pad_sub_callback, &info);
     }
+  compute_noholes (polygon);
   return r;
 }
 
@@ -770,10 +825,13 @@ Unsubtract (POLYAREA * np1, PolygonType 
       fprintf (stderr, "Error while clipping PBO_UNITE: %d\n", x);
       poly_Free (&merged);
       p->Clipped = NULL;
+      if (p->NoHoles) printf ("Just leaked in Unsubtract\n");
+      p->NoHoles = NULL;
       return 0;
     }
   p->Clipped = biggest (merged);
   assert (!p->Clipped || poly_Valid (p->Clipped));
+//  compute_noholes (p);
   return ClipOriginal (p);
 }
 
@@ -871,11 +929,19 @@ InitClip (DataTypePtr Data, LayerTypePtr
   if (p->Clipped)
     poly_Free (&p->Clipped);
   p->Clipped = original_poly (p);
+  if (p->NoHoles)
+    {
+      poly_Free (&p->NoHoles);
+//      printf ("Just leaked in InitClip\n");
+    }
+  p->NoHoles = NULL;
   if (!p->Clipped)
     return 0;
   assert (poly_Valid (p->Clipped));
   if (TEST_FLAG (CLEARPOLYFLAG, p))
     clearPoly (Data, layer, p, NULL, 0);
+  else
+    compute_noholes (p);
   return 1;
 }
 
@@ -1129,18 +1195,23 @@ subtract_plow (DataTypePtr Data, LayerTy
     case PIN_TYPE:
     case VIA_TYPE:
       SubtractPin (Data, (PinTypePtr) ptr2, Layer, Polygon);
+      compute_noholes (Polygon);
       return 1;
     case LINE_TYPE:
       SubtractLine ((LineTypePtr) ptr2, Polygon);
+      compute_noholes (Polygon);
       return 1;
     case ARC_TYPE:
       SubtractArc ((ArcTypePtr) ptr2, Polygon);
+      compute_noholes (Polygon);
       return 1;
     case PAD_TYPE:
       SubtractPad ((PadTypePtr) ptr2, Polygon);
+      compute_noholes (Polygon);
       return 1;
     case TEXT_TYPE:
       SubtractText ((TextTypePtr) ptr2, Polygon);
+      compute_noholes (Polygon);
       return 1;
     }
   return 0;
@@ -1337,7 +1408,7 @@ IsRectangleInPolygon (LocationType X1, L
 }
 
 static void
-r_NoHolesPolygonDicer (PLINE * p, void (*emit) (PolygonTypePtr))
+r_NoHolesPolygonDicer (PLINE * p, void (*emit) (PolygonTypePtr, void *), void *user_data)
 {
   POLYAREA *pa;
 
@@ -1345,6 +1416,7 @@ r_NoHolesPolygonDicer (PLINE * p, void (
   pa->b = pa->f = pa;
   pa->contours = p;
   if (!p->next)                 /* no holes */
+//  if (1)
     {
       PolygonType poly;
       PointType pts[4];
@@ -1355,6 +1427,7 @@ r_NoHolesPolygonDicer (PLINE * p, void (
       poly.BoundingBox.Y2 = p->ymax;
       poly.PointN = poly.PointMax = 4;
       poly.Clipped = pa;
+      poly.NoHoles = NULL;
       poly.Points = pts;
       pts[0].X = pts[0].X2 = p->xmin;
       pts[0].Y = pts[0].Y2 = p->ymin;
@@ -1365,7 +1438,7 @@ r_NoHolesPolygonDicer (PLINE * p, void (
       pts[3].X = pts[3].X2 = p->xmin;
       pts[3].Y = pts[3].Y2 = p->ymax;
       poly.Flags = MakeFlags (CLEARPOLYFLAG);
-      emit (&poly);
+      emit (&poly, user_data);
       poly_Free (&pa);
       return;
     }
@@ -1385,7 +1458,7 @@ r_NoHolesPolygonDicer (PLINE * p, void (
           do
             {
               PLINE *pl = x->contours;
-              r_NoHolesPolygonDicer (pl, emit);
+              r_NoHolesPolygonDicer (pl, emit, user_data);
               y = x->f;
               /* the pline was already freed by its use int he recursive dicer */
               free (x);
@@ -1399,7 +1472,7 @@ r_NoHolesPolygonDicer (PLINE * p, void (
           do
             {
               PLINE *pl = x->contours;
-              r_NoHolesPolygonDicer (pl, emit);
+              r_NoHolesPolygonDicer (pl, emit, user_data);
               y = x->f;
               free (x);
             }
@@ -1409,8 +1482,8 @@ r_NoHolesPolygonDicer (PLINE * p, void (
 }
 
 void
-NoHolesPolygonDicer (PolygonTypePtr p, void (*emit) (PolygonTypePtr),
-                     const BoxType * clip)
+NoHolesPolygonDicer (PolygonTypePtr p, void (*emit) (PolygonTypePtr, void *),
+                     void *user_data, const BoxType * clip)
 {
   POLYAREA *save, *ans;
 
@@ -1435,7 +1508,7 @@ NoHolesPolygonDicer (PolygonTypePtr p, v
   do
     {
       POLYAREA *prev;
-      r_NoHolesPolygonDicer (save->contours, emit);
+      r_NoHolesPolygonDicer (save->contours, emit, user_data);
       /* go to next poly (could be one because of clip) */
       prev = save;
       save = prev->f;
@@ -1468,6 +1541,8 @@ MorphPolygon (LayerTypePtr layer, Polygo
    * we do this dirty work.
    */
   poly->Clipped = NULL;
+  if (poly->NoHoles) printf ("Just leaked in MorpyPolygon\n");
+  poly->NoHoles = NULL;
   flags = poly->Flags;
   RemovePolygon (layer, poly);
   inhibit = True;
@@ -1494,6 +1569,7 @@ MorphPolygon (LayerTypePtr layer, Polygo
           new->Clipped = p;
           p = p->f;             /* go to next pline */
           new->Clipped->b = new->Clipped->f = new->Clipped;     /* unlink from others */
+//          compute_noholes (new);
           r_insert_entry (layer->polygon_tree, (BoxType *) new, 0);
           DrawPolygon (layer, new, 0);
         }
Index: src/polygon.h
===================================================================
RCS file: /cvsroot/pcb/pcb/src/polygon.h,v
retrieving revision 1.13
diff -U3 -p -r1.13 polygon.h
--- src/polygon.h	16 Nov 2006 03:01:21 -0000	1.13
+++ src/polygon.h	23 Jun 2008 13:32:20 -0000
@@ -60,5 +60,5 @@ Boolean IsRectangleInPolygon (LocationTy
 			      LocationType, PolygonTypePtr);
 Boolean isects (POLYAREA *, PolygonTypePtr, Boolean);
 Boolean MorphPolygon (LayerTypePtr, PolygonTypePtr);
-void NoHolesPolygonDicer (PolygonTypePtr p, void (*emit) (PolygonTypePtr), const BoxType *clip);
+void NoHolesPolygonDicer (PolygonTypePtr p, void (*emit) (PolygonTypePtr, void *), void *user_data, const BoxType *clip);
 #endif
Index: src/polygon1.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/polygon1.c,v
retrieving revision 1.16
diff -U3 -p -r1.16 polygon1.c
--- src/polygon1.c	11 Jan 2008 20:32:47 -0000	1.16
+++ src/polygon1.c	23 Jun 2008 13:32:20 -0000
@@ -2106,6 +2106,12 @@ poly_CopyContour (PLINE ** dst, PLINE * 
       poly_InclVertex ((*dst)->head.prev, newnode);
     }
   (*dst)->tree = make_edge_tree (*dst);
+
+  {
+    static int count = 0;
+    count ++;
+//    printf ("Counting poly_CopyContour %i\n", count);
+  }
   return TRUE;
 }
 
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	23 Jun 2008 13:32: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	23 Jun 2008 13:32: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	23 Jun 2008 13:32:21 -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	23 Jun 2008 13:32:21 -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	23 Jun 2008 13:32:21 -0000
@@ -32,26 +32,81 @@
 #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 $");
 
 
 extern HID ghid_hid;
 
+#define TRIANGLE_ARRAY_SIZE 5000
+static GLfloat triangle_array [2 * 3 * TRIANGLE_ARRAY_SIZE];
+static unsigned int triangle_count;
+static int coord_comp_count;
+
+void
+ghid_init_triangle_array (void)
+{
+  glEnableClientState (GL_VERTEX_ARRAY);
+  glVertexPointer (2, GL_FLOAT, 0, &triangle_array);
+  triangle_count = 0;
+  coord_comp_count = 0;
+}
+
+void
+ghid_flush_triangles ()
+{
+  if (triangle_count == 0)
+    return;
+
+//  printf ("Flushing %i triangles\n", triangle_count);
+  glDrawArrays (GL_TRIANGLES, 0, triangle_count * 3);
+  triangle_count = 0;
+  coord_comp_count = 0;
+}
+
+static void
+ensure_triangle_space (int count)
+{
+  if (count > TRIANGLE_ARRAY_SIZE)
+    {
+      fprintf (stderr, "Not enough space in vertex buffer\n");
+      fprintf (stderr, "Requested %i triangles, %i available\n", count, TRIANGLE_ARRAY_SIZE);
+      exit (1);
+    }
+  if (count > TRIANGLE_ARRAY_SIZE - triangle_count)
+    ghid_flush_triangles ();
+}
+
+static inline void
+add_triangle (GLfloat x1, GLfloat y1,
+              GLfloat x2, GLfloat y2,
+              GLfloat x3, GLfloat y3)
+{
+  triangle_array [coord_comp_count++] = x1;
+  triangle_array [coord_comp_count++] = y1;
+  triangle_array [coord_comp_count++] = x2;
+  triangle_array [coord_comp_count++] = y2;
+  triangle_array [coord_comp_count++] = x3;
+  triangle_array [coord_comp_count++] = y3;
+  triangle_count++;
+}
 
 static void zoom_to (double factor, int x, int y);
 static void zoom_by (double factor, int x, int y);
 
 /* 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) use_gc (gc)
 
 static int cur_mask = -1;
-static int mask_seq = 0;
 
 int ghid_flip_x = 0, ghid_flip_y = 0;
 
@@ -379,10 +434,10 @@ zoom_by (double factor, int x, int y)
 
 /* ------------------------------------------------------------ */
 
-static void
+/*static*/ void
 draw_grid ()
 {
-  static GdkPoint *points = 0;
+  static GLfloat *points = 0;
   static int npoints = 0;
   int x1, y1, x2, y2, n, i;
   double x, y;
@@ -391,19 +446,23 @@ draw_grid ()
     return;
   if (Vz (PCB->Grid) < MIN_GRID_DISTANCE)
     return;
-  if (!gport->grid_gc)
+
+  if (gdk_color_parse (Settings.GridColor, &gport->grid_color))
     {
-      if (gdk_color_parse (Settings.GridColor, &gport->grid_color))
-	{
-	  gport->grid_color.red ^= gport->bg_color.red;
-	  gport->grid_color.green ^= gport->bg_color.green;
-	  gport->grid_color.blue ^= gport->bg_color.blue;
-	  gdk_color_alloc (gport->colormap, &gport->grid_color);
-	}
-      gport->grid_gc = gdk_gc_new (gport->drawable);
-      gdk_gc_set_function (gport->grid_gc, GDK_XOR);
-      gdk_gc_set_foreground (gport->grid_gc, &gport->grid_color);
+      gport->grid_color.red ^= gport->bg_color.red;
+      gport->grid_color.green ^= gport->bg_color.green;
+      gport->grid_color.blue ^= gport->bg_color.blue;
     }
+
+  ghid_flush_triangles ();
+
+  glEnable (GL_COLOR_LOGIC_OP);
+  glLogicOp (GL_XOR);
+
+  glColor3f (gport->grid_color.red / 65535.,
+             gport->grid_color.green / 65535.,
+             gport->grid_color.blue / 65535.);
+
   x1 = GRIDFIT_X (SIDE_X (gport->view_x0), PCB->Grid);
   y1 = GRIDFIT_Y (SIDE_Y (gport->view_y0), PCB->Grid);
   x2 = GRIDFIT_X (SIDE_X (gport->view_x0 + gport->view_width - 1), PCB->Grid);
@@ -433,21 +492,29 @@ draw_grid ()
     {
       npoints = n + 10;
       points =
-	MyRealloc (points, npoints * sizeof (GdkPoint), "gtk_draw_grid");
+	MyRealloc (points, npoints * 2 * sizeof (GLfloat), "gtk_draw_grid");
     }
+
+  glEnableClientState (GL_VERTEX_ARRAY);
+  glVertexPointer (2, GL_FLOAT, 0, points);
+
   n = 0;
   for (x = x1; x <= x2; x += PCB->Grid)
     {
-      points[n].x = Vx (x);
+      points[2 * n] = Vx (x);
       n++;
     }
   for (y = y1; y <= y2; y += PCB->Grid)
     {
       int vy = Vy (y);
       for (i = 0; i < n; i++)
-	points[i].y = vy;
-      gdk_draw_points (gport->drawable, gport->grid_gc, points, n);
+	points[2 * i + 1] = vy;
+      glDrawArrays (GL_POINTS, 0, n);
     }
+
+  glDisableClientState (GL_VERTEX_ARRAY);
+  glDisable (GL_COLOR_LOGIC_OP);
+  glFlush ();
 }
 
 /* ------------------------------------------------------------ */
@@ -471,108 +538,81 @@ ghid_invalidate_lr (int left, int right,
   ghid_invalidate_all ();
 }
 
+#if 0
 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);
+}
+#endif
 
-  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 +623,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,11 +638,16 @@ ghid_set_layer (const char *name, int gr
 	    return TEST_FLAG (SHOWMASKFLAG, PCB);
 	  return 0;
 	case SL_SILK:
+//          gport->trans_lines = TRUE;
+          gport->trans_lines = FALSE;
 	  if (SL_MYSIDE (idx) /*|| pinout */ )
 	    return PCB->ElementOn;
 	  return 0;
 	case SL_ASSY:
 	  return 0;
+	case SL_RATS:
+	  gport->trans_lines = TRUE;
+	  return 1;
 	case SL_PDRILL:
 	case SL_UDRILL:
 	  return 1;
@@ -609,55 +656,41 @@ 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;
+
+  ghid_flush_triangles ();
+
   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 +707,9 @@ typedef struct
   GdkColor color;
   int xor_set;
   GdkColor xor_color;
+  double red;
+  double green;
+  double blue;
 } ColorCache;
 
 
@@ -688,9 +724,7 @@ set_special_grid_color (void)
   gport->grid_color.red ^= gport->bg_color.red;
   gport->grid_color.green ^= gport->bg_color.green;
   gport->grid_color.blue ^= gport->bg_color.blue;
-  gdk_color_alloc (gport->colormap, &gport->grid_color);
-  if (gport->grid_gc)
-    gdk_gc_set_foreground (gport->grid_gc, &gport->grid_color);
+//  gdk_color_alloc (gport->colormap, &gport->grid_color);
 }
 
 void
@@ -698,99 +732,135 @@ ghid_set_special_colors (HID_Attribute *
 {
   if (!ha->name || !ha->value)
     return;
-  if (!strcmp (ha->name, "background-color") && gport->bg_gc)
+  if (!strcmp (ha->name, "background-color"))
     {
       ghid_map_color_string (*(char **) ha->value, &gport->bg_color);
-      gdk_gc_set_foreground (gport->bg_gc, &gport->bg_color);
       set_special_grid_color ();
     }
-  else if (!strcmp (ha->name, "off-limit-color") && gport->offlimits_gc)
-    {
+  else if (!strcmp (ha->name, "off-limit-color"))
+  {
       ghid_map_color_string (*(char **) ha->value, &gport->offlimits_color);
-      gdk_gc_set_foreground (gport->offlimits_gc, &gport->offlimits_color);
     }
-  else if (!strcmp (ha->name, "grid-color") && gport->grid_gc)
+  else if (!strcmp (ha->name, "grid-color"))
     {
       ghid_map_color_string (*(char **) ha->value, &gport->grid_color);
       set_special_grid_color ();
     }
 }
 
+
 void
 ghid_set_color (hidGC gc, const char *name)
 {
-  static void *cache = 0;
+  static void *cache = NULL;
+  static char *old_name = NULL;
   hidval cval;
+  ColorCache *cc;
+  double alpha_mult = 1.0;
+  double r, g, b, a;
+  a = 1.0;
+
+  if (old_name != NULL)
+    {
+      if (strcmp (name, old_name) == 0)
+        return;
+      free (old_name);
+    }
+
+  old_name = strdup (name);
 
   if (name == NULL)
     {
       fprintf (stderr, "%s():  name = NULL, setting to magenta\n",
-	       __FUNCTION__);
+               __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 (strcmp (name, "erase") == 0)
     {
-      gdk_gc_set_foreground (gc->gc, &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_gc_set_foreground (gc->gc, &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
     {
-      ColorCache *cc;
+      alpha_mult = 0.7;
       if (hid_cache_color (0, name, &cval, &cache))
-	cc = (ColorCache *) cval.ptr;
+        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);
-	}
+        {
+          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->color_set = 1;
-	}
+        {
+          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;
+        }
       if (gc->xor)
-	{
-	  if (!cc->xor_set)
-	    {
-	      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->xor_set = 1;
-	    }
-	  gdk_gc_set_foreground (gc->gc, &cc->xor_color);
-	}
-      else
-	{
-	  gdk_gc_set_foreground (gc->gc, &cc->color);
-	}
+        {
+          if (!cc->xor_set)
+            {
+              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.;
+              cc->xor_set = 1;
+            }
+        }
+      r = cc->red;
+      g = cc->green;
+      b = cc->blue;
 
       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
+  }
+
+  ghid_flush_triangles ();
+  glColor4d (r, g, b, a);
 }
 
 void
 ghid_set_line_cap (hidGC gc, EndCapStyle style)
 {
-
   switch (style)
     {
     case Trace_Cap:
@@ -804,31 +874,22 @@ 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);
+  // printf ("ghid_set_draw_xor (%p, %d) -- not implemented\n", gc, xor);
+  /* NOT IMPLEMENTED */
+
+  /* Only presently called when setting up a crosshair GC.
+   * We manage our own drawing model for that anyway. */
 }
 
 void
@@ -843,56 +904,153 @@ ghid_set_line_cap_angle (hidGC gc, int x
   printf ("ghid_set_line_cap_angle() -- not implemented\n");
 }
 
-static int
+static void
 use_gc (hidGC gc)
 {
-  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;
+  static hidGC current_gc = NULL;
+
+  if (current_gc == gc)
+    return;
+
+  current_gc = gc;
+
+  ghid_set_color (gc, gc->colorname);
 }
 
 void
+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)
 {
+#define TRIANGLES_PER_CAP 15
+#define MIN_TRIANGLES_PER_CAP 3
   double dx1, dy1, dx2, dy2;
+  double width, angle;
+  float deltax, deltay, length;
+  float wdx, wdy;
+  int slices;
+  int circular_caps = 0;
 
-  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,
   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);
+
+  if (length == 0) {
+    angle = 0;
+    wdx = -width / 2.;
+    wdy = 0;
+  } else {
+    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 < MIN_TRIANGLES_PER_CAP)
+    slices = MIN_TRIANGLES_PER_CAP;
+
+//  slices = TRIANGLES_PER_CAP;
+
+  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;
+  }
+
+  ensure_triangle_space (2);
+  add_triangle (dx1 - wdx, dy1 - wdy, dx2 - wdx, dy2 - wdy, dx2 + wdx, dy2 + wdy);
+  add_triangle (dx1 - wdx, dy1 - wdy, dx2 + wdx, dy2 + wdy, dx1 + wdx, dy1 + wdy);
+
+  if (circular_caps) {
+    int i;
+    float last_capx, last_capy;
+
+    ensure_triangle_space (2 * slices);
+
+    last_capx = ((float)width) / 2. * cos (angle * M_PI / 180.) + dx1;
+    last_capy = -((float)width) / 2. * sin (angle * M_PI / 180.) + dy1;
+    for (i = 0; i < slices; i++) {
+      float capx, capy;
+      capx = ((float)width) / 2. * cos (angle * M_PI / 180. + ((float)(i + 1)) * M_PI / (float)slices) + dx1;
+      capy = -((float)width) / 2. * sin (angle * M_PI / 180. + ((float)(i + 1)) * M_PI / (float)slices) + dy1;
+      add_triangle (last_capx, last_capy, capx, capy, dx1, dy1);
+      last_capx = capx;
+      last_capy = capy;
+    }
+    last_capx = -((float)width) / 2. * cos (angle * M_PI / 180.) + dx2;
+    last_capy = ((float)width) / 2. * sin (angle * M_PI / 180.) + dy2;
+    for (i = 0; i < slices; i++) {
+      float capx, capy;
+      capx = -((float)width) / 2. * cos (angle * M_PI / 180. + ((float)(i + 1)) * M_PI / (float)slices) + dx2;
+      capy = ((float)width) / 2. * sin (angle * M_PI / 180. + ((float)(i + 1)) * M_PI / (float)slices) + dy2;
+      add_triangle (last_capx, last_capy, capx, capy, dx2, dy2);
+      last_capx = capx;
+      last_capy = capy;
+    }
+  }
 }
 
 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)
 {
+#define MIN_SLICES_PER_ARC 10
   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 +1059,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 +1074,50 @@ 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 < MIN_SLICES_PER_ARC)
+    slices = MIN_SLICES_PER_ARC;
+
+  /* TODO: CHANGE TO USING THE TRIANGLE LIST */
+  qobj = gluNewQuadric ();
+  gluQuadricCallback (qobj, GLU_ERROR, errorCallback);
+  gluQuadricDrawStyle (qobj, GLU_FILL); /* 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 < MIN_TRIANGLES_PER_CAP)
+    slices = MIN_TRIANGLES_PER_CAP;
+
+  /* TODO: CHANGE TO USING THE TRIANGLE LIST */
+  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 ();
+
+  /* TODO: CHANGE TO USING THE TRIANGLE LIST */
+  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,19 +1144,26 @@ 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);
+  glVertex2f (x1, y1);
+  glVertex2f (x1, y2);
+  glVertex2f (x2, y2);
+  glVertex2f (x2, y1);
+  glEnd ();
 }
 
 
 void
 ghid_fill_circle (hidGC gc, int cx, int cy, int radius)
 {
-  gint w, h, vr;
+#define TRIANGLES_PER_CIRCLE 30
+#define MIN_TRIANGLES_PER_CIRCLE 6
+  gint w, h, vx, vy, vr;
+  float last_x, last_y;
+  int slices;
+  int i;
 
   w = gport->width * gport->zoom;
   h = gport->height * gport->zoom;
@@ -972,38 +1174,187 @@ ghid_fill_circle (hidGC gc, int cx, int 
     return;
 
   USE_GC (gc);
+  vx = Vx (cx);
+  vy = Vy (cy);
   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 * vr / PIXELS_PER_CIRCLINE;
+
+  if (slices < MIN_TRIANGLES_PER_CIRCLE)
+    slices = MIN_TRIANGLES_PER_CIRCLE;
+
+//  slices = TRIANGLES_PER_CIRCLE;
+
+  ensure_triangle_space (slices);
+
+  last_x = vx + vr;
+  last_y = vy;
+
+  for (i = 0; i < slices; i++) {
+    float x, y;
+    x = ((float)vr) * cos (((float)(i + 1)) * 2. * M_PI / (float)slices) + vx;
+    y = ((float)vr) * sin (((float)(i + 1)) * 2. * M_PI / (float)slices) + vy;
+    add_triangle (vx, vy, last_x, last_y, x, y);
+    last_x = x;
+    last_y = y;
+  }
+}
+
+#define MAX_COMBINED_MALLOCS 1500
+static void *combined_to_free [MAX_COMBINED_MALLOCS];
+static int combined_num_to_free = 0;
+
+static GLenum tessVertexType;
+static int stashed_vertices;
+static int triangle_comp_idx;
+
+
+void
+myError (GLenum errno)
+{
+  printf ("gluTess error: %s\n", gluErrorString (errno));
+}
+
+static void
+myFreeCombined ()
+{
+  while (combined_num_to_free)
+    free (combined_to_free [-- combined_num_to_free]);
+}
+
+static void
+myCombine ( GLdouble coords[3], void *vertex_data[4], GLfloat weight[4], void **dataOut )
+{
+#define MAX_COMBINED_VERTICES 1500
+  static GLdouble combined_vertices [3 * MAX_COMBINED_VERTICES];
+  static int num_combined_vertices = 0;
+
+  GLdouble *new_vertex;
+
+  if (num_combined_vertices < MAX_COMBINED_VERTICES)
+    {
+      new_vertex = &combined_vertices [3 * num_combined_vertices];
+      num_combined_vertices ++;
+    }
+  else
+    {
+      new_vertex = malloc (3 * sizeof (GLdouble));
+
+      if (combined_num_to_free < MAX_COMBINED_MALLOCS)
+        combined_to_free [combined_num_to_free ++] = new_vertex;
+      else
+        printf ("myCombine leaking %i bytes of memory\n", 3 * sizeof (GLdouble));
+    }
+
+  new_vertex[0] = coords[0];
+  new_vertex[1] = coords[1];
+  new_vertex[2] = coords[2];
+
+  *dataOut = new_vertex;
+}
+
+static void
+myBegin (GLenum type)
+{
+  tessVertexType = type;
+  stashed_vertices = 0;
+  triangle_comp_idx = 0;
+}
+
+void
+myVertex (GLdouble *vertex_data)
+{
+  static GLfloat triangle_vertices [2 * 3];
+
+  if (tessVertexType == GL_TRIANGLE_STRIP ||
+      tessVertexType == GL_TRIANGLE_FAN)
+    {
+      if (stashed_vertices < 2)
+        {
+          triangle_vertices [triangle_comp_idx ++] = vertex_data [0];
+          triangle_vertices [triangle_comp_idx ++] = vertex_data [1];
+          stashed_vertices ++;
+        }
+      else
+        {
+          ensure_triangle_space (1);
+          add_triangle (triangle_vertices [0], triangle_vertices [1],
+                        triangle_vertices [2], triangle_vertices [3],
+                        vertex_data [0], vertex_data [1]);
+
+          if (tessVertexType == GL_TRIANGLE_STRIP)
+            {
+              /* STRIP saves the last two vertices for re-use in the next triangle */
+              triangle_vertices [0] = triangle_vertices [2];
+              triangle_vertices [1] = triangle_vertices [3];
+            }
+          /* Both FAN and STRIP save the last vertex for re-use in the next triangle */
+          triangle_vertices [2] = vertex_data [0];
+          triangle_vertices [3] = vertex_data [1];
+        }
+    }
+  else if (tessVertexType == GL_TRIANGLES)
+    {
+      triangle_vertices [triangle_comp_idx ++] = vertex_data [0];
+      triangle_vertices [triangle_comp_idx ++] = vertex_data [1];
+      stashed_vertices ++;
+      if (stashed_vertices == 3)
+        {
+          ensure_triangle_space (1);
+          add_triangle (triangle_vertices [0], triangle_vertices [1],
+                        triangle_vertices [2], triangle_vertices [3],
+                        triangle_vertices [4], triangle_vertices [5]);
+          triangle_comp_idx = 0;
+          stashed_vertices = 0;
+        }
+    }
+  else
+    printf ("Vertex recieved with unknown type\n");
 }
 
 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, myBegin);
+  gluTessCallback(tobj, GLU_TESS_VERTEX, myVertex);
+  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 +1374,14 @@ 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);
+  glVertex2f (x1, y1);
+  glVertex2f (x1, y2);
+  glVertex2f (x2, y2);
+  glVertex2f (x2, y1);
+  glEnd ();
 }
 
 void
@@ -1527,7 +1871,7 @@ HID ghid_hid = {
   1,				/* gui */
   0,				/* printer */
   0,				/* exporter */
-  0,				/* poly before */
+  1,				/* poly before */
   1,				/* poly after */
   0,				/* poly dicer */
 
@@ -2160,11 +2504,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	23 Jun 2008 13:32:21 -0000
@@ -297,66 +297,108 @@ ghid_show_crosshair (gboolean show)
 {
   gint x, y;
   static gint x_prev = -1, y_prev = -1;
-  static GdkGC *xor_gc;
+  static int done_once = 0;
   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)
+  if (!done_once)
     {
-      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);
+      done_once = 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);
+
+  ghid_flush_triangles ();
+
+  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
@@ -730,53 +772,217 @@ ghid_port_drawing_area_configure_event_c
   if (!first_time_done)
     {
       gport->colormap = gtk_widget_get_colormap (gport->top_window);
-      gport->bg_gc = gdk_gc_new (gport->drawable);
       if (gdk_color_parse (Settings.BackgroundColor, &gport->bg_color))
 	gdk_color_alloc (gport->colormap, &gport->bg_color);
       else
 	gdk_color_white (gport->colormap, &gport->bg_color);
-      gdk_gc_set_foreground (gport->bg_gc, &gport->bg_color);
 
-      gport->offlimits_gc = gdk_gc_new (gport->drawable);
       if (gdk_color_parse (Settings.OffLimitColor, &gport->offlimits_color))
 	gdk_color_alloc (gport->colormap, &gport->offlimits_color);
       else
 	gdk_color_white (gport->colormap, &gport->offlimits_color);
-      gdk_gc_set_foreground (gport->offlimits_gc, &gport->offlimits_color);
       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
 gboolean
 ghid_port_drawing_area_expose_event_cb (GtkWidget * widget,
 					GdkEventExpose * ev, GHidPort * port)
 {
+  BoxType region;
+  int eleft, eright, etop, ebottom;
+  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 (ev->area.x,
+              widget->allocation.height - ev->area.height - ev->area.y,
+              ev->area.width, ev->area.height);
+
+  glEnable (GL_SCISSOR_TEST);
+  glScissor (ev->area.x,
+             widget->allocation.height - ev->area.height - ev->area.y,
+             ev->area.width, ev->area.height);
+
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+  glOrtho (ev->area.x, ev->area.x + ev->area.width, ev->area.y + ev->area.height, ev->area.y, 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);
+
+  region.X1 = MIN (Px (ev->area.x), Px (ev->area.x + ev->area.width + 1));
+  region.X2 = MAX (Px (ev->area.x), Px (ev->area.x + ev->area.width + 1));
+  region.Y1 = MIN (Py (ev->area.y), Py (ev->area.y + ev->area.height + 1));
+  region.Y2 = MAX (Py (ev->area.y), Py (ev->area.y + ev->area.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;
+    }
+
+  glColor3f (gport->offlimits_color.red / 65535.,
+             gport->offlimits_color.green / 65535.,
+             gport->offlimits_color.blue / 65535.);
+
+  if (eleft > 0)
+    {
+      glBegin (GL_QUADS);
+      glVertex2i (0, 0);
+      glVertex2i (eleft, 0);
+      glVertex2i (eleft, gport->height);
+      glVertex2i (0, gport->height);
+      glEnd ();
+    }
+  else
+    eleft = 0;
+
+  if (eright < gport->width)
+    {
+      glBegin (GL_QUADS);
+      glVertex2i (eright, 0);
+      glVertex2i (gport->width, 0);
+      glVertex2i (gport->width, gport->height);
+      glVertex2i (eright, gport->width);
+      glEnd ();
+    }
+  else
+    eright = gport->width;
+  if (etop > 0)
+    {
+      glBegin (GL_QUADS);
+      glVertex2i (eleft, 0);
+      glVertex2i (eright, 0);
+      glVertex2i (eright, etop);
+      glVertex2i (eleft, etop);
+      glEnd ();
+    }
+  if (ebottom < gport->height)
+    {
+      glBegin (GL_QUADS);
+      glVertex2i (eleft, ebottom);
+      glVertex2i (eright + 1, ebottom);
+      glVertex2i (eright + 1, gport->height);
+      glVertex2i (eleft, gport->height);
+      glEnd ();
+    }
+
+  /* TODO: Background image */
+
+  ghid_init_triangle_array ();
+  hid_expose_callback (&ghid_hid, &region, 0);
+  ghid_flush_triangles ();
+
+  draw_grid ();
+
+  ghid_init_triangle_array ();
+  DrawAttached (TRUE);
   ghid_show_crosshair (TRUE);
+
+  ghid_flush_triangles ();
+
+  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 +995,14 @@ 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)) {
+    printf ("GL THingy returned\n");
+    return FALSE;
+  }
 
   state = (GdkModifierType) (ev->state);
   mk = ghid_modifier_keys_state (&state);
@@ -808,9 +1022,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;
 }
 
@@ -850,7 +1073,7 @@ ghid_port_window_enter_cb (GtkWidget * w
       RestoreCrosshair (TRUE);
       cursor_in_viewport = TRUE;
     }
-	  
+
   return FALSE;
 }
 
@@ -964,18 +1187,18 @@ ghid_port_window_mouse_scroll_cb (GtkWid
 
   state = (GdkModifierType) (ev->state);
   mk = ghid_modifier_keys_state (&state);
+
   if (mk == NONE_PRESSED)
+    dy = ghid_port.height * gport->zoom / 40;
+  else if (mk == SHIFT_PRESSED)
+    dx = ghid_port.width * gport->zoom / 40;
+  else if (mk == CONTROL_PRESSED)
     {
       zoom_factor = (ev->direction == GDK_SCROLL_UP) ? 0.8 : 1.25;
       ghid_port_ranges_zoom (gport->zoom * zoom_factor);
       return TRUE;
     }
 
-  if (mk == SHIFT_PRESSED)
-    dy = ghid_port.height * gport->zoom / 40;
-  else
-    dx = ghid_port.width * gport->zoom / 40;
-
   if (ev->direction == GDK_SCROLL_UP)
     {
       dx = -dx;
Index: src/hid/gtk/gui-pinout-preview.c
===================================================================
RCS file: /cvsroot/pcb/pcb/src/hid/gtk/gui-pinout-preview.c,v
retrieving revision 1.1
diff -U3 -p -r1.1 gui-pinout-preview.c
--- src/hid/gtk/gui-pinout-preview.c	8 Jan 2008 00:50:27 -0000	1.1
+++ src/hid/gtk/gui-pinout-preview.c	23 Jun 2008 13:32:21 -0000
@@ -150,11 +150,14 @@ pinout_set_data (GhidPinoutPreview * pin
 }
 
 
+#define Z_NEAR 3.0
+
 static gboolean
-ghid_pinout_preview_expose (GtkWidget * widget, GdkEventExpose * event)
+ghid_pinout_preview_expose (GtkWidget * widget, GdkEventExpose * ev)
 {
+  GdkGLContext* pGlContext = gtk_widget_get_gl_context (widget);
+  GdkGLDrawable* pGlDrawable = gtk_widget_get_gl_drawable (widget);
   GhidPinoutPreview *pinout = GHID_PINOUT_PREVIEW (widget);
-  GdkDrawable *save_drawable;
   double save_zoom;
   int da_w, da_h;
   int save_left, save_top;
@@ -170,9 +173,7 @@ ghid_pinout_preview_expose (GtkWidget * 
   save_view_width = gport->view_width;
   save_view_height = gport->view_height;
 
-  /* Setup drawable and zoom factor for drawing routines
-   */
-  save_drawable = gport->drawable;
+  /* Setup zoom factor for drawing routines */
 
   gdk_window_get_geometry (widget->window, 0, 0, &da_w, &da_h, 0);
   xz = (double) pinout->x_max / da_w;
@@ -182,7 +183,6 @@ ghid_pinout_preview_expose (GtkWidget * 
   else
     gport->zoom = yz;
 
-  gport->drawable = widget->window;
   gport->width = da_w;
   gport->height = da_h;
   gport->view_width = da_w * gport->zoom;
@@ -190,13 +190,50 @@ ghid_pinout_preview_expose (GtkWidget * 
   gport->view_x0 = (pinout->x_max - gport->view_width) / 2;
   gport->view_y0 = (pinout->y_max - gport->view_height) / 2;
 
-  /* clear background */
-  gdk_draw_rectangle (widget->window, gport->bg_gc, TRUE, 0, 0, da_w, da_h);
+  /* 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 (ev->area.x,
+              widget->allocation.height - ev->area.height - ev->area.y,
+              ev->area.width, ev->area.height);
+
+  glEnable (GL_SCISSOR_TEST);
+  glScissor (ev->area.x,
+             widget->allocation.height - ev->area.height - ev->area.y,
+             ev->area.width, ev->area.height);
+
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+  glOrtho (ev->area.x, ev->area.x + ev->area.width, ev->area.y + ev->area.height, ev->area.y, 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);
 
   /* call the drawing routine */
+  ghid_init_triangle_array ();
   DrawElement (&pinout->element, 0);
+  ghid_flush_triangles ();
+
+  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);
 
-  gport->drawable = save_drawable;
   gport->zoom = save_zoom;
   gport->width = save_width;
   gport->height = save_height;
@@ -218,6 +255,27 @@ enum
 static GObjectClass *ghid_pinout_preview_parent_class = NULL;
 
 
+/*! \brief GObject constructed handler
+ *
+ *  \par Function Description
+ *  Setup any the necessary state for our widget now it is constructed.
+ *
+ *  \param [in] widget  The GObject having just been constructed.
+ */
+static void
+ghid_pinout_preview_constructed (GObject *object)
+{
+  GtkWidget *widget = GTK_WIDGET (object);
+
+  gtk_widget_set_gl_capability (widget,
+                                gport->glconfig,
+                                NULL,
+                                TRUE,
+                                GDK_GL_RGBA_TYPE);
+}
+
+
+
 /*! \brief GObject finalise handler
  *
  *  \par Function Description
@@ -309,6 +367,7 @@ ghid_pinout_preview_class_init (GhidPino
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *gtk_widget_class = GTK_WIDGET_CLASS (klass);
 
+  gobject_class->constructed = ghid_pinout_preview_constructed;
   gobject_class->finalize = ghid_pinout_preview_finalize;
   gobject_class->set_property = ghid_pinout_preview_set_property;
   gobject_class->get_property = ghid_pinout_preview_get_property;
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	23 Jun 2008 13:32:21 -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	23 Jun 2008 13:32:21 -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)
@@ -130,7 +134,7 @@ typedef struct hid_gc_struct
   gint cap, join;
   gchar xor;
   gchar erase;
-  gint mask_seq;
+//  gint mask_seq;
 }
 hid_gc_struct;
 
@@ -197,7 +201,11 @@ typedef struct
   GdkDrawable *drawable;	/* Current drawable for drawing routines */
   gint width, height;
 
-  GdkGC *bg_gc, *offlimits_gc, *mask_gc, *u_gc, *grid_gc;
+  GdkGLConfig *glconfig;
+
+  gint trans_lines;
+
+//  GdkGC *bg_gc, *offlimits_gc, *mask_gc, *u_gc, *grid_gc;
 
   GdkColor bg_color, offlimits_color, grid_color;
 
@@ -510,6 +518,8 @@ void ghid_logv (const char *fmt, va_list
 void ghid_pinout_window_show (GHidPort * out, ElementTypePtr Element);
 
 /* gtkhid-main.c */
+void ghid_init_triangle_array ();
+void ghid_flush_triangles ();
 void ghid_invalidate_all ();
 void ghid_get_coords (const char *msg, int *x, int *y);
 gint PCBChanged (int argc, char **argv, int x, int y);


_______________________________________________
geda-dev mailing list
geda-dev@moria.seul.org
http://www.seul.org/cgi-bin/mailman/listinfo/geda-dev