changeset 1261:61d0c5f84644

Initial attempt at adding dw_draw_arc() support on all platforms. This code doesn't yet work... will probably require a bunch of fixes... but I wanted to get the code committed while doing research on it.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Tue, 25 Oct 2011 10:51:59 +0000
parents 3cbd8de0b50b
children 4b0aa8429592
files dw.def dw.h dwtest.c dww.def gtk/dw.c gtk3/dw.c mac/dw.m os2/dw.c template/dw.c win/dw.c
diffstat 10 files changed, 307 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/dw.def	Tue Oct 25 06:21:59 2011 +0000
+++ b/dw.def	Tue Oct 25 10:51:59 2011 +0000
@@ -204,6 +204,7 @@
   dw_draw_rect                           @333
   dw_draw_text                           @334
   dw_draw_polygon                        @335
+  dw_draw_arc                            @336
 
   dw_pixmap_bitblt                       @340
   dw_pixmap_new                          @341
--- a/dw.h	Tue Oct 25 06:21:59 2011 +0000
+++ b/dw.h	Tue Oct 25 10:51:59 2011 +0000
@@ -1650,6 +1650,7 @@
 void API dw_draw_line(HWND handle, HPIXMAP pixmap, int x1, int y1, int x2, int y2);
 void API dw_draw_rect(HWND handle, HPIXMAP pixmap, int fill, int x, int y, int width, int height);
 void API dw_draw_polygon(HWND handle, HPIXMAP pixmap, int fill, int npoints, int *x, int *y);
+void API dw_draw_arc(HWND handle, HPIXMAP pixmap, int flags, int xorigin, int yorigin, int x1, int y1, int x2, int y2);
 void API dw_draw_text(HWND handle, HPIXMAP pixmap, int x, int y, char *text);
 void API dw_font_text_extents_get(HWND handle, HPIXMAP pixmap, char *text, int *width, int *height);
 void API dw_font_set_default(char *fontname);
--- a/dwtest.c	Tue Oct 25 06:21:59 2011 +0000
+++ b/dwtest.c	Tue Oct 25 10:51:59 2011 +0000
@@ -368,6 +368,8 @@
     dw_draw_text(window, pixmap, 10, 10, "This should be aligned with the edges.");
     dw_color_foreground_set(DW_CLR_BLUE);
     dw_draw_polygon(window, pixmap, TRUE, 7, x, y);
+    dw_color_foreground_set(DW_CLR_CYAN);
+    dw_draw_arc(window, pixmap, 0, width - 40, height - 40, width - 40, height - 20, width - 20, height - 40);
     if(image)
     {
         if(image_stretch)
--- a/dww.def	Tue Oct 25 06:21:59 2011 +0000
+++ b/dww.def	Tue Oct 25 10:51:59 2011 +0000
@@ -201,6 +201,7 @@
   dw_draw_rect                           @333
   dw_draw_text                           @334
   dw_draw_polygon                        @335
+  dw_draw_arc                            @336
 
   dw_pixmap_bitblt                       @340
   dw_pixmap_new                          @341
--- a/gtk/dw.c	Tue Oct 25 06:21:59 2011 +0000
+++ b/gtk/dw.c	Tue Oct 25 10:51:59 2011 +0000
@@ -28,6 +28,7 @@
 #include <signal.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <math.h>
 #include <gdk/gdkkeysyms.h>
 #ifdef USE_IMLIB
 #include <gdk_imlib.h>
@@ -8052,6 +8053,76 @@
    DW_MUTEX_UNLOCK;
 }
 
+/* Draw an arc on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       flags: For future use.
+ *       xorigin: X coordinate of center of arc.
+ *       yorigin: Y coordinate of center of arc.
+ *       x1: X coordinate of first segment of arc.
+ *       y1: Y coordinate of first segment of arc.
+ *       x2: X coordinate of second segment of arc.
+ *       y2: Y coordinate of second segment of arc.
+ */
+void API dw_draw_arc(HWND handle, HPIXMAP pixmap, int flags, int xorigin, int yorigin, int x1, int y1, int x2, int y2)
+{
+   int _locked_by_me = FALSE;
+   GdkGC *gc = NULL;
+#if GTK_CHECK_VERSION(2,10,0)
+   cairo_t *cr = NULL;
+#endif
+   double dx = xorigin - x1;
+   double dy = yorigin - y1;
+   double r = sqrt(dx*dx + dy*dy);
+
+   DW_MUTEX_LOCK;
+   if(handle)
+      gc = _set_colors(handle->window);
+   else if(pixmap && pixmap->pixmap)
+      gc = _set_colors(pixmap->pixmap);
+#if GTK_CHECK_VERSION(2,10,0)
+   else if(pixmap && pixmap->image)
+      cr = cairo_create(pixmap->image);
+   if(cr)
+   {
+      GdkColor *foreground = pthread_getspecific(_dw_fg_color_key);
+      double a1 = 180/M_PI * arctan((y1-yorigin)/(x1-xorigin));
+      double a2 = 180/M_PI * arctan((y2-yorigin)/(x2-xorigin));
+      
+      gdk_cairo_set_source_color (cr, foreground);
+      cairo_set_line_width(cr, 1);
+      cairo_arc(cr, xorigin, yorigin, r, a1, a2);
+      cairo_stroke(cr);
+      cairo_destroy(cr);
+   }
+#endif   
+   if(gc)
+   {
+      double radius1 = 0, radius2 = 0;
+      int alpha1, alpha2;
+
+      if(x1 == x2 && y1 == y2)
+      {
+         radius1 = 0.0;
+         radius2 = 360.0;
+      }
+      else
+      {
+         radius1 = (x1 - xorigin == 0) ? (y1 - yc < 0) ? 90.0 : -90.0 : -atan2((double)y1-yc, (double)x1-xc) * RAD2DEG;
+         radius2 = (x2 - xorigin == 0) ? (y2 - yc < 0) ? 90.0 : -90.0 : -atan2((double)y2-yc, (double)x2-xc) * RAD2DEG;
+      }
+      alpha1 = (int)(radius1 * 64.0);
+      alpha2 = (int)((radius2 - radius1) * 64.0);
+      while (alpha2 <= 0) alpha2 += 360*64;
+      while (alpha1 > 360*64) alpha1 -= 360*64;
+     
+      gdk_draw_arc(handle ? handle->window : pixmap->pixmap, gc, TRUE, xorigin-r, yorigin-r, 2*r,2*r, alpha1, alpha2);
+      gdk_gc_unref(gc);
+   }
+   DW_MUTEX_UNLOCK;
+}
+
 /* Draw text on a window (preferably a render window).
  * Parameters:
  *       handle: Handle to the window.
--- a/gtk3/dw.c	Tue Oct 25 06:21:59 2011 +0000
+++ b/gtk3/dw.c	Tue Oct 25 10:51:59 2011 +0000
@@ -28,6 +28,7 @@
 #include <signal.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <math.h>
 #include <gdk/gdkkeysyms.h>
 
 #ifdef USE_GTKMOZEMBED
@@ -6922,6 +6923,55 @@
    DW_MUTEX_UNLOCK;
 }
 
+/* Draw an arc on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       flags: For future use.
+ *       xorigin: X coordinate of center of arc.
+ *       yorigin: Y coordinate of center of arc.
+ *       x1: X coordinate of first segment of arc.
+ *       y1: Y coordinate of first segment of arc.
+ *       x2: X coordinate of second segment of arc.
+ *       y2: Y coordinate of second segment of arc.
+ */
+void API dw_draw_arc(HWND handle, HPIXMAP pixmap, int flags, int xorigin, int yorigin, int x1, int y1, int x2, int y2)
+{
+   int _locked_by_me = FALSE;
+   cairo_t *cr = NULL;
+
+   DW_MUTEX_LOCK;
+   if(handle)
+   {
+      GdkWindow *window = gtk_widget_get_window(handle);
+      /* Safety check for non-existant windows */
+      if(!window || !GDK_IS_WINDOW(window))
+      {
+         DW_MUTEX_UNLOCK;
+         return;
+      }
+      cr = gdk_cairo_create(window);
+   }
+   else if(pixmap)
+      cr = cairo_create(pixmap->image);
+   if(cr)
+   {
+      GdkColor *foreground = pthread_getspecific(_dw_fg_color_key);
+      double dx = xorigin - x1;
+      double dy = yorigin - y1;
+      double r = sqrt(dx*dx + dy*dy);
+      double a1 = 180/M_PI * arctan((y1-yorigin)/(x1-xorigin));
+      double a2 = 180/M_PI * arctan((y2-yorigin)/(x2-xorigin));
+
+      gdk_cairo_set_source_color (cr, foreground);
+      cairo_set_line_width(cr, 1);
+      cairo_arc(cr, xorigin, yorigin, r, a1, a2);
+      cairo_stroke(cr);
+      cairo_destroy(cr);
+   }
+   DW_MUTEX_UNLOCK;
+}
+
 /* Draw text on a window (preferably a render window).
  * Parameters:
  *       handle: Handle to the window.
--- a/mac/dw.m	Tue Oct 25 06:21:59 2011 +0000
+++ b/mac/dw.m	Tue Oct 25 10:51:59 2011 +0000
@@ -17,6 +17,7 @@
 #include <sys/mman.h>
 #include <sys/time.h>
 #include <sys/stat.h>
+#include <math.h>
 
 /* Create a define to let us know to include Snow Leopard specific features */
 #if defined(MAC_OS_X_VERSION_10_6) && ((defined(MAC_OS_X_VERSION_MIN_REQUIRED) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) || !defined(MAC_OS_X_VERSION_MIN_REQUIRED))
@@ -5226,6 +5227,71 @@
     DW_MUTEX_UNLOCK;
 }
 
+/* Draw an arc on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       flags: For future use.
+ *       xorigin: X coordinate of center of arc.
+ *       yorigin: Y coordinate of center of arc.
+ *       x1: X coordinate of first segment of arc.
+ *       y1: Y coordinate of first segment of arc.
+ *       x2: X coordinate of second segment of arc.
+ *       y2: Y coordinate of second segment of arc.
+ */
+void API dw_draw_arc(HWND handle, HPIXMAP pixmap, int flags, int xorigin, int yorigin, int x1, int y1, int x2, int y2)
+{
+    int _locked_by_me = FALSE;
+    DW_MUTEX_LOCK;
+    id image = handle;
+    double r, a1, a2, a;
+    int x3, y3;
+    
+    if(pixmap)
+    {
+        image = (id)pixmap->image;
+        [NSGraphicsContext saveGraphicsState];
+        [NSGraphicsContext setCurrentContext:[NSGraphicsContext
+                                              graphicsContextWithGraphicsPort:[[NSGraphicsContext graphicsContextWithBitmapImageRep:image] graphicsPort] flipped:YES]];
+    }
+    else
+    {
+        if([image lockFocusIfCanDraw] == NO)
+        {
+            DW_MUTEX_UNLOCK;
+            return;
+        }
+        _DWLastDrawable = handle;
+    }
+    NSBezierPath* aPath = [NSBezierPath bezierPath];
+    [aPath setLineWidth: 0.5];
+    NSColor *color = pthread_getspecific(_dw_fg_color_key);
+    [color set];
+
+    [aPath moveToPoint:NSMakePoint(x1, y1)];
+    /* Calculate the midpoint */
+    r = 0.5 * (hypot((double)(y1 - yorigin), (double)(x1 - xorigin)) +
+               hypot((double)(y2 - yorigin), (double)(x2 - xorigin)));
+    a1 = atan2((double)(y1 - yorigin), (double)(x1 - xorigin));
+    a2 = atan2((double)(y2 - yorigin), (double)(x2 - xorigin));
+    if(a2 < a1)
+        a2 += M_PI * 2;
+    a = (a1 + a2) / 2.;
+    /* Prepare to draw */
+    [aPath appendBezierPathWithArcFromPoint:NSMakePoint((xorigin + r * cos(a)), (yorigin + r * sin(a)))
+           toPoint:NSMakePoint(x2, y2) radius:r];
+    [aPath stroke];
+    if(pixmap)
+    {
+        [NSGraphicsContext restoreGraphicsState];
+    }
+    else
+    {
+        [image unlockFocus];
+    }
+    DW_MUTEX_UNLOCK;
+}
+
 /*
  * Create a tree object to be packed.
  * Parameters:
--- a/os2/dw.c	Tue Oct 25 06:21:59 2011 +0000
+++ b/os2/dw.c	Tue Oct 25 10:51:59 2011 +0000
@@ -28,6 +28,7 @@
 #include <process.h>
 #include <time.h>
 #include <io.h>
+#include <math.h>
 #ifndef __EMX__
 #include <direct.h>
 #endif
@@ -8659,6 +8660,66 @@
       WinReleasePS(hps);
 }
 
+/* Draw an arc on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       flags: For future use.
+ *       xorigin: X coordinate of center of arc.
+ *       yorigin: Y coordinate of center of arc.
+ *       x1: X coordinate of first segment of arc.
+ *       y1: Y coordinate of first segment of arc.
+ *       x2: X coordinate of second segment of arc.
+ *       y2: Y coordinate of second segment of arc.
+ */
+void API dw_draw_arc(HWND handle, HPIXMAP pixmap, int flags, int xorigin, int yorigin, int x1, int y1, int x2, int y2)
+{
+   HPS hps;
+   int thisheight;
+   ARCPARAMS ap = { 1, 1, 0, 0 };
+   POINTL pts[2];
+   double r, a1, a2, a;
+   int x3, y3;
+   
+   if(handle)
+   {
+      hps = _set_colors(handle);
+      thisheight = _get_height(handle);
+   }
+   else if(pixmap)
+   {
+      hps = _set_hps(pixmap->hps);
+      thisheight = pixmap->height;
+   }
+   else
+      return;
+   
+   /* Setup the arc info on the presentation space */
+   GpiSetArcParams(hps, &ap);
+   pts[0].x = x1;
+   pts[0].y = thisheight - y1 - 1;
+   /* Move to the initial position */
+   GpiMove(hps, pts);
+   /* Calculate the midpoint */
+   r = 0.5 * (hypot((double)(y1 - yorigin), (double)(x1 - xorigin)) +
+              hypot((double)(y2 - yorigin), (double)(x2 - xorigin)));
+   a1 = atan2((double)(y1 - yorigin), (double)(x1 - xorigin));
+   a2 = atan2((double)(y2 - yorigin), (double)(x2 - xorigin));
+   if(a2 < a1)
+      a2 += M_PI * 2;
+   a = (a1 + a2) / 2.;
+   /* Prepare to draw */
+   pts[0].x = (int)(xorigin + r * cos(a));
+   pts[0].y = thisheight - (int)(yorigin + r * sin(a)) - 1;
+   pts[1].x = x2;
+   pts[1].y = thisheight - y2 - 1;
+   /* Actually draw the arc */
+   GpiPointArc(hps, pts);
+
+   if(!pixmap)
+      WinReleasePS(hps);
+}
+
 /* Call this after drawing to the screen to make sure
  * anything you have drawn is visible.
  */
--- a/template/dw.c	Tue Oct 25 06:21:59 2011 +0000
+++ b/template/dw.c	Tue Oct 25 10:51:59 2011 +0000
@@ -1529,6 +1529,22 @@
 {
 }
 
+/* Draw an arc on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       flags: For future use.
+ *       xorigin: X coordinate of center of arc.
+ *       yorigin: Y coordinate of center of arc.
+ *       x1: X coordinate of first segment of arc.
+ *       y1: Y coordinate of first segment of arc.
+ *       x2: X coordinate of second segment of arc.
+ *       y2: Y coordinate of second segment of arc.
+ */
+void API dw_draw_arc(HWND handle, HPIXMAP pixmap, int flags, int xorigin, int yorigin, int x1, int y1, int x2, int y2)
+{
+}
+
 /*
  * Create a tree object to be packed.
  * Parameters:
--- a/win/dw.c	Tue Oct 25 06:21:59 2011 +0000
+++ b/win/dw.c	Tue Oct 25 10:51:59 2011 +0000
@@ -8815,6 +8815,44 @@
       ReleaseDC(handle, hdcPaint);
 }
 
+/* Draw an arc on a window (preferably a render window).
+ * Parameters:
+ *       handle: Handle to the window.
+ *       pixmap: Handle to the pixmap. (choose only one of these)
+ *       flags: For future use.
+ *       xorigin: X coordinate of center of arc.
+ *       yorigin: Y coordinate of center of arc.
+ *       x1: X coordinate of first segment of arc.
+ *       y1: Y coordinate of first segment of arc.
+ *       x2: X coordinate of second segment of arc.
+ *       y2: Y coordinate of second segment of arc.
+ */
+void API dw_draw_arc(HWND handle, HPIXMAP pixmap, int flags, int xorigin, int yorigin, int x1, int y1, int x2, int y2)
+{
+   HDC hdcPaint;
+   HBRUSH oldBrush;
+   HPEN oldPen;
+   double dx = xorigin - x1;
+   double dy = yorigin - y1;
+   double r = sqrt(dx*dx + dy*dy);
+
+   if(handle)
+      hdcPaint = GetDC(handle);
+   else if(pixmap)
+      hdcPaint = pixmap->hdc;
+   else
+      return;
+      
+   oldBrush = SelectObject( hdcPaint, TlsGetValue(_hBrush) );
+   oldPen = SelectObject( hdcPaint, TlsGetValue(_hPen) );
+   Arc(hdcPaint, xorigin-r, yorigin-r, xorigin+r, yorigin+r, x1, y1, x2, y2);
+   SelectObject( hdcPaint, oldBrush );
+   SelectObject( hdcPaint, oldPen );
+
+   if(!pixmap)
+      ReleaseDC(handle, hdcPaint);
+}
+
 /* Draw text on a window (preferably a render window).
  * Parameters:
  *       handle: Handle to the window.