[gimp] app: clean up and simplify code and math in GimpDial



commit 04c36b80c1ce15ccf859081bea2893d8e83cf64e
Author: Michael Natterer <mitch gimp org>
Date:   Sun May 25 17:05:59 2014 +0200

    app: clean up and simplify code and math in GimpDial

 app/widgets/gimpdial.c |  108 ++++++++++++++++++++++++++++--------------------
 1 files changed, 63 insertions(+), 45 deletions(-)
---
diff --git a/app/widgets/gimpdial.c b/app/widgets/gimpdial.c
index e71d55c..487de59 100644
--- a/app/widgets/gimpdial.c
+++ b/app/widgets/gimpdial.c
@@ -34,10 +34,7 @@
 #include "gimpdial.h"
 
 
-#define REL  0.8
-#define DEL  0.1
-#define TICK 10
-#define EACH_OR_BOTH  0.3
+#define SEGMENT_FRACTION 0.3
 
 typedef void (* GimpDialBGFunc) (gdouble  angle,
                                  gdouble  distance,
@@ -59,6 +56,7 @@ typedef enum
   DIAL_TARGET_BOTH
 } DialTarget;
 
+
 struct _GimpDialPrivate
 {
   gdouble           alpha;
@@ -410,15 +408,6 @@ angle_mod_2PI (gdouble angle)
 }
 
 static gdouble
-arctg (gdouble y,
-       gdouble x)
-{
-  gdouble temp = atan2 (y, x);
-
-  return (temp < 0) ? (temp + 2 * G_PI) : temp;
-}
-
-static gdouble
 min_prox (gdouble alpha,
          gdouble beta,
          gdouble angle)
@@ -448,6 +437,27 @@ closest (gdouble alpha,
     return DIAL_TARGET_BETA;
 }
 
+static gdouble
+get_angle_and_distance (gdouble  center_x,
+                        gdouble  center_y,
+                        gdouble  radius,
+                        gdouble  x,
+                        gdouble  y,
+                        gdouble *distance)
+{
+  gdouble angle = atan2 (center_y - y,
+                         x - center_x);
+
+  if (angle < 0)
+    angle += 2 * G_PI;
+
+  if (distance)
+    *distance = sqrt ((SQR (x - center_x) +
+                       SQR (y - center_y)) / SQR (radius));
+
+  return angle;
+}
+
 static gboolean
 gimp_dial_button_press_event (GtkWidget      *widget,
                               GdkEventButton *bevent)
@@ -468,7 +478,8 @@ gimp_dial_button_press_event (GtkWidget      *widget,
           gint          size;
           gdouble       center_x;
           gdouble       center_y;
-          gdouble       press_angle;
+          gdouble       angle;
+          gdouble       distance;
 
           gtk_widget_get_allocation (widget, &allocation);
 
@@ -482,22 +493,21 @@ gimp_dial_button_press_event (GtkWidget      *widget,
           dial->priv->has_grab    = TRUE;
           dial->priv->press_state = bevent->state;
 
-          press_angle = angle_mod_2PI (arctg (center_y - bevent->y,
-                                              bevent->x - center_x));
-          dial->priv->press_angle = press_angle;
+          angle = get_angle_and_distance (center_x, center_y, size / 2.0,
+                                          bevent->x, bevent->y,
+                                          &distance);
+          dial->priv->press_angle = angle;
 
-          if ((sqrt (SQR (bevent->y - center_y) +
-                     SQR (bevent->x - center_x)) > size / 2.0 * EACH_OR_BOTH) &&
-              (min_prox (dial->priv->alpha, dial->priv->beta,
-                         press_angle) < G_PI / 12))
+          if (distance > SEGMENT_FRACTION &&
+              min_prox (dial->priv->alpha, dial->priv->beta, angle) < G_PI / 12)
             {
               dial->priv->target = closest (dial->priv->alpha, dial->priv->beta,
-                                            press_angle);
+                                            angle);
 
               if (dial->priv->target == DIAL_TARGET_ALPHA)
-                g_object_set (dial, "alpha", press_angle, NULL);
+                g_object_set (dial, "alpha", angle, NULL);
               else
-                g_object_set (dial, "beta", press_angle, NULL);
+                g_object_set (dial, "beta", angle, NULL);
             }
           else
             {
@@ -532,28 +542,29 @@ gimp_dial_motion_notify_event (GtkWidget      *widget,
   GtkAllocation  allocation;
   gdouble        center_x;
   gdouble        center_y;
-  gfloat         motion_angle, delta;
+  gfloat         angle, delta;
 
   gtk_widget_get_allocation (widget, &allocation);
 
   center_x = allocation.width  / 2.0;
   center_y = allocation.height / 2.0;
 
-  motion_angle = angle_mod_2PI (arctg (center_y - mevent->y,
-                                       mevent->x - center_x));
+  angle = get_angle_and_distance (center_x, center_y, 1.0,
+                                  mevent->x, mevent->y,
+                                  NULL);
 
-  delta = motion_angle - dial->priv->press_angle;
-  dial->priv->press_angle = motion_angle;
+  delta = angle - dial->priv->press_angle;
+  dial->priv->press_angle = angle;
 
   if (delta)
     {
       if (dial->priv->target == DIAL_TARGET_ALPHA)
         {
-          g_object_set (dial, "alpha", motion_angle, NULL);
+          g_object_set (dial, "alpha", angle, NULL);
         }
       else if (dial->priv->target == DIAL_TARGET_BETA)
         {
-          g_object_set (dial, "beta", motion_angle, NULL);
+          g_object_set (dial, "beta", angle, NULL);
         }
       else
         {
@@ -584,9 +595,9 @@ gimp_dial_background_func_hsv (gdouble  angle,
                                gdouble  distance,
                                guchar  *rgb)
 {
-  gdouble v = 1 - sqrt (distance) / 4;
+  gdouble v = 1 - sqrt (distance) / 4; /* it just looks nicer this way */
 
-  gimp_hsv_to_rgb4 (rgb, angle, distance, v);
+  gimp_hsv_to_rgb4 (rgb, angle / (2.0 * G_PI), distance, v);
 }
 
 static void
@@ -597,29 +608,28 @@ gimp_dial_draw_background (cairo_t        *cr,
   cairo_surface_t *surface;
   guchar          *data;
   gint             stride;
-  gint             i, j;
+  gint             x, y;
 
   surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, size, size);
 
   data   = cairo_image_surface_get_data (surface);
   stride = cairo_image_surface_get_stride (surface);
 
-  for (j = 0; j < size; j++)
+  for (y = 0; y < size; y++)
     {
-      for (i = 0; i < size; i++)
+      for (x = 0; x < size; x++)
         {
           gdouble angle;
           gdouble distance;
           guchar  rgb[3];
 
-          distance = sqrt ((SQR (i - size  / 2.0) +
-                            SQR (j - size / 2.0)) / (gdouble) SQR (size / 2.0));
-
-          angle = arctg (size / 2.0 - j, i - size / 2.0) / (2 * G_PI);
+          angle = get_angle_and_distance (size / 2.0, size / 2.0, size / 2.0,
+                                          x, y,
+                                          &distance);
 
           bg_func (angle, MIN (1.0, distance), rgb);
 
-          GIMP_CAIRO_ARGB32_SET_PIXEL (data + j * stride + i * 4,
+          GIMP_CAIRO_ARGB32_SET_PIXEL (data + y * stride + x * 4,
                                        rgb[0], rgb[1], rgb[2], 255);
         }
     }
@@ -647,9 +657,15 @@ gimp_dial_draw_arrows (cairo_t  *cr,
                        gdouble   beta,
                        gboolean  clockwise)
 {
-  gint     radius = size / 2.0;
-  gint     dist;
-  gint     direction = clockwise ? -1 : 1;
+  gint radius = size / 2.0;
+  gint dist;
+  gint direction = clockwise ? -1 : 1;
+
+#define REL  0.8
+#define DEL  0.1
+#define TICK 10
+
+  cairo_save (cr);
 
   cairo_move_to (cr, radius, radius);
   cairo_line_to (cr,
@@ -691,7 +707,7 @@ gimp_dial_draw_arrows (cairo_t  *cr,
                  ROUND (radius + radius * REL * cos (beta + DEL)),
                  ROUND (radius - radius * REL * sin (beta + DEL)));
 
-  dist = radius * EACH_OR_BOTH;
+  dist = radius * SEGMENT_FRACTION;
 
   cairo_move_to (cr,
                  radius + dist * cos (beta),
@@ -730,4 +746,6 @@ gimp_dial_draw_arrows (cairo_t  *cr,
   cairo_set_line_width (cr, 1.0);
   cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.8);
   cairo_stroke (cr);
+
+  cairo_restore (cr);
 }


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