On Sat, 2008-06-14 at 23:33 -0400, Joshua Boyd wrote:
> On Jun 14, 2008, at 9:06 PM, Peter Clifton wrote:
> 
> > This is generally a bit crufty, but for your amusement, see the  
> > attached
> > patch. It breaks drawing the mask layer, cursor and rubber-band lines,
> > but is a stab at making PCB render (translucent drawing) with GL.
> >
> > Its frame-rate on my complex power controller board at minimum zoom is
> > about 2.4 frames per second. This basically matches the frame-rate  
> > of my
> > similarly crufty test implementation with cairo.
> 
> I do not at all have the time to try to put together a build  
> environment for this (I've been using the Motif version on Solaris).  
> If someone had notes on what all I'd have to install to be able to  
> build it, I might get around to trying it.

Thanks for looking,  I'm not sure exactly what is required. It will
basically be the libraries needed for the GTK version (GTK, GLib etc..),
plus GtkGlExt, libGL, libGLU.

> However, reviewing the patch (applying the patch and reviewing that  
> would probably be better still), I have a few suggestions that may  
> help speed.  Some of these suggestions may only help specific chips,  
> and they may all be outdated for the latest and greatest hardware.

Hmm... it appears I have been an idiot, and sent the wrong patch. Sorry
for the wasted review effort. (Although various of the comments still
apply). Try this attached one..

> First, in ghid_draw_line, you are setting the shademodel and the  
> material attributes and setting up  light and doing some enables.   
> These only need to be done if you have turned them off elsewhere.  I  
> don't see anyplace that you disable GL_LIGHTING, GL_LIGHT0, or  
> GL_DEPTH_TEST, so you don't need to do the enable every single line.   
> Likewise with the shade model, material attributes, and light.  Your  
> OpenGL may be smart enough to not make unneeded state changes, but  
> doing the check will still waste some performance.  Also, I could be  
> wrong, but I don't think you need to reinit gobj every time.

I've still got that, I'm not sure how much overhead is associated with
gluNewQuadric(), my profiling showed hotspots in actually flushing
commands in the GPU ring-buffer.

> Second, don't use glVertex3f when you can use glVertext2f.  This will  
> at least help the C performance even if it doesn't make a difference  
> to your graphics card.  That said, I suspect that while an Nvidia  
> card always does a 3D transform, the OpenGL library for Intel  
> graphics may be smart enough to only do 2D transforms sometimes.

I'm not sure, but what does it take the Z-coordinate to be if we don't
specify it? (Does it stay at the last Z vertex value, 0)?

> Third, if you want a spinning 3D view, make that a special mode.   
> Otherwise, turn off lighting and depth testing. That will especially  
> help performance on platforms with a CPU transform system.

Done, and I've tidied up the patch I should have sent in the first
place.

> After those things, if you really want to make it fast, you need to  
> drastically change the line drawing methods. To my understanding, a  
> lot of what is contained in this:
> http://developer.apple.com/graphicsimaging/opengl/optimizingdata.html
> will apply to most platforms.

I'll have a read, thanks! Its the line caps and vias etc.. which seem to
harm the performance so far. gluDisk etc.. I clawed some of that back by
using less slices.

> They mention vertex buffer objects,  
> that I think that may not be the most backwards compatible, but I  
> don't know how far back you want to support.  Personally, I like to  
> keep 1.2 supported as much as I can.  I'd hold out for 1.0, but  
> working with textures in 1.0 is too painful.

Is that the same as vertex lists? That might help if we can stamp out
the same triangles again and again for doing vias and pads etc., but
we'll have to add some some caching mechanism.

-- 
Peter Clifton

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

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

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

Reply via email to