fixed crashes that occured with small sizes, some code cleanups and a

2004-08-18  Sven Neumann  <sven@gimp.org>

	* modules/colorsel_triangle.c: fixed crashes that occured with
	small sizes, some code cleanups and a simple optimization.
This commit is contained in:
Sven Neumann 2004-08-18 18:09:06 +00:00 committed by Sven Neumann
parent 2d5ee4485d
commit d5cd7ae3f1
2 changed files with 86 additions and 59 deletions

View File

@ -1,3 +1,8 @@
2004-08-18 Sven Neumann <sven@gimp.org>
* modules/colorsel_triangle.c: fixed crashes that occured with
small sizes, some code cleanups and a simple optimization.
2004-08-18 Sven Neumann <sven@gimp.org>
* app/widgets/gimphelp-ids.h: define GIMP_HELP_DOCK_SEPARATOR.

View File

@ -35,10 +35,11 @@
#include "libgimp/libgimp-intl.h"
#define BGCOLOR 180
#define PREVIEW_MASK (GDK_BUTTON_PRESS_MASK | \
GDK_BUTTON_RELEASE_MASK | \
GDK_BUTTON_MOTION_MASK )
#define BGCOLOR 180
#define MINIMUM_SIZE 48
#define PREVIEW_MASK (GDK_BUTTON_PRESS_MASK | \
GDK_BUTTON_RELEASE_MASK | \
GDK_BUTTON_MOTION_MASK )
#define COLORSEL_TYPE_TRIANGLE (colorsel_triangle_type)
@ -90,11 +91,13 @@ static void colorsel_xy_to_triangle_buf (gint x,
static GtkWidget *colorsel_triangle_create_preview (ColorselTriangle *triangle);
static void colorsel_triangle_update_preview (ColorselTriangle *triangle);
static void colorsel_triangle_size_allocate (GtkWidget *widget,
GtkAllocation *allocation,
ColorselTriangle *triangle);
static gboolean colorsel_triangle_event (GtkWidget *widget,
GdkEvent *event,
ColorselTriangle *triangle);
static const GimpModuleInfo colorsel_triangle_info =
{
GIMP_MODULE_ABI_VERSION,
@ -179,10 +182,6 @@ colorsel_triangle_init (ColorselTriangle *triangle)
triangle->oldval = 0;
triangle->mode = 0;
triangle->wheelradius = GIMP_COLOR_SELECTOR_SIZE / 2;
triangle->triangleradius = GIMP_COLOR_SELECTOR_SIZE / 2
- GIMP_COLOR_SELECTOR_BAR_SIZE;
frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
gtk_box_pack_start (GTK_BOX (triangle), frame, TRUE, TRUE, 0);
@ -190,6 +189,7 @@ colorsel_triangle_init (ColorselTriangle *triangle)
triangle->preview = colorsel_triangle_create_preview (triangle);
gtk_container_add (GTK_CONTAINER (frame), triangle->preview);
gtk_widget_set_size_request (triangle->preview, MINIMUM_SIZE, MINIMUM_SIZE);
gtk_widget_show (triangle->preview);
}
@ -208,7 +208,7 @@ colorsel_triangle_create_preview (ColorselTriangle *triangle)
{
GtkWidget *preview = gimp_preview_area_new ();
gtk_widget_add_events (GTK_WIDGET (preview), PREVIEW_MASK);
gtk_widget_add_events (preview, PREVIEW_MASK);
g_signal_connect (preview, "motion_notify_event",
G_CALLBACK (colorsel_triangle_event),
@ -219,9 +219,10 @@ colorsel_triangle_create_preview (ColorselTriangle *triangle)
g_signal_connect (preview, "button_release_event",
G_CALLBACK (colorsel_triangle_event),
triangle);
g_signal_connect_swapped (preview, "size_allocate",
G_CALLBACK (colorsel_triangle_update_preview),
triangle);
g_signal_connect (preview, "size_allocate",
G_CALLBACK (colorsel_triangle_size_allocate),
triangle);
return preview;
}
@ -234,17 +235,20 @@ colorsel_triangle_update_preview (ColorselTriangle *triangle)
gint x, y, k, r2, dx, col;
gint x0, y0;
gdouble hue, sat, val, atn;
gint hx,hy, sx,sy, vx,vy;
gint hx, hy;
gint sx, sy;
gint vx, vy;
gint width, height, size;
gint d;
width = GIMP_PREVIEW_AREA (triangle->preview)->width;
height = GIMP_PREVIEW_AREA (triangle->preview)->height;
/* return gracefully if the widget is not yet configured */
if (width * height == 0)
/* return gracefully if the widget is not yet configured or too small */
if (width < MINIMUM_SIZE || height < MINIMUM_SIZE)
return;
triangle->wheelradius = MIN (width-1, height-1) / 2;
triangle->wheelradius = MIN (width - 1, height - 1) / 2;
triangle->triangleradius = RINT (0.8 * triangle->wheelradius);
size = triangle->wheelradius * 2 + 1;
@ -272,16 +276,15 @@ colorsel_triangle_update_preview (ColorselTriangle *triangle)
for (y = triangle->wheelradius; y >= -triangle->wheelradius; y--)
{
dx = RINT (sqrt (fabs (triangle->wheelradius * triangle->wheelradius -
y * y)));
dx = RINT (sqrt (fabs (SQR (triangle->wheelradius) - SQR (y))));
for (x = -dx, k = 0; x <= dx; x++)
{
buf[k] = buf[k+1] = buf[k+2] = BGCOLOR;
r2 = (x * x) + (y * y);
r2 = SQR (x) + SQR (y);
if (r2 <= triangle->wheelradius * triangle->wheelradius)
if (r2 <= SQR (triangle->wheelradius))
{
if (r2 > triangle->triangleradius * triangle->triangleradius)
if (r2 > SQR (triangle->triangleradius))
{
atn = atan2 (x, y);
if (atn < 0)
@ -298,6 +301,7 @@ colorsel_triangle_update_preview (ColorselTriangle *triangle)
k += 3;
}
memcpy (preview_buf + ((triangle->wheelradius - y) * size +
triangle->wheelradius - dx ) * 3,
buf,
@ -307,10 +311,12 @@ colorsel_triangle_update_preview (ColorselTriangle *triangle)
/* marker in outer ring */
x0 = RINT (sin (hue * G_PI / 180) *
((gdouble) (triangle->wheelradius - triangle->triangleradius + 1) / 2 +
((gdouble) (triangle->wheelradius -
triangle->triangleradius + 1) / 2 +
triangle->triangleradius));
y0 = RINT (cos (hue * G_PI / 180) *
((gdouble) (triangle->wheelradius - triangle->triangleradius + 1) / 2 +
((gdouble) (triangle->wheelradius -
triangle->triangleradius + 1) / 2 +
triangle->triangleradius));
atn = atan2 (x0, y0);
@ -321,13 +327,15 @@ colorsel_triangle_update_preview (ColorselTriangle *triangle)
col = GIMP_RGB_INTENSITY (buf[0], buf[1], buf[2]) > 127 ? 0 : 255;
for (y = y0 - 4 ; y <= y0 + 4 ; y++)
{
for (x = x0 - 4, k=0 ; x <= x0 + 4 ; x++)
{
r2 = (x - x0) * (x - x0) + (y - y0) * (y - y0);
d = CLAMP (triangle->wheelradius / 16, 2, 4);
if (r2 <= 20 && r2 >= 6)
for (y = y0 - d ; y <= y0 + d ; y++)
{
for (x = x0 - d, k = 0; x <= x0 + d ; x++)
{
r2 = SQR (x - x0) + SQR (y - y0);
if ((r2 <= d * 5) && (r2 >= d + 2))
{
buf[k] = buf[k+1] = buf[k+2] = col;
}
@ -336,6 +344,7 @@ colorsel_triangle_update_preview (ColorselTriangle *triangle)
atn = atan2 (x, y);
if (atn < 0)
atn = atn + 2 * G_PI;
gimp_hsv_to_rgb4 (buf + k, atn / (2 * G_PI), 1, 1);
}
@ -343,9 +352,9 @@ colorsel_triangle_update_preview (ColorselTriangle *triangle)
}
memcpy (preview_buf + ((triangle->wheelradius - y) * size +
triangle->wheelradius + x0 - 4) * 3,
triangle->wheelradius + x0 - d) * 3,
buf,
27);
(2 * d + 1) * 3);
}
/* marker in triangle */
@ -363,7 +372,7 @@ colorsel_triangle_update_preview (ColorselTriangle *triangle)
for (x = x0 - 4, k=0 ; x <= x0 + 4 ; x++)
{
buf[k] = buf[k+1] = buf[k+2] = BGCOLOR;
r2 = (x - x0) * (x - x0) + (y - y0) * (y - y0);
r2 = SQR (x - x0) + SQR (y - y0);
if (r2 <= 20 && r2 >= 6)
{
@ -371,16 +380,18 @@ colorsel_triangle_update_preview (ColorselTriangle *triangle)
}
else
{
if (x * x + y * y > triangle->triangleradius * triangle->triangleradius)
if (SQR (x) + SQR (y) > SQR (triangle->triangleradius))
{
atn = atan2 (x, y);
if (atn < 0)
atn = atn + 2 * G_PI;
gimp_hsv_to_rgb4 (buf + k, atn / (2 * G_PI), 1, 1);
}
else
{
colorsel_xy_to_triangle_buf (x, y, hue, buf + k, hx, hy, sx, sy, vx, vy);
colorsel_xy_to_triangle_buf (x, y, hue, buf + k,
hx, hy, sx, sy, vx, vy);
}
}
@ -390,15 +401,11 @@ colorsel_triangle_update_preview (ColorselTriangle *triangle)
memcpy (preview_buf + ((triangle->wheelradius - y) * size +
triangle->wheelradius + x0 - 4) * 3,
buf,
27);
9 * 3);
}
gimp_preview_area_fill (GIMP_PREVIEW_AREA (triangle->preview),
0, 0, width, height,
BGCOLOR, BGCOLOR, BGCOLOR);
gimp_preview_area_draw (GIMP_PREVIEW_AREA (triangle->preview),
(width - size) / 2,
(width - size) / 2,
(height - size) / 2,
size,
size,
@ -449,29 +456,49 @@ colorsel_xy_to_triangle_buf (gint x,
}
}
static void
colorsel_triangle_size_allocate (GtkWidget *widget,
GtkAllocation *allocation,
ColorselTriangle *triangle)
{
gimp_preview_area_fill (GIMP_PREVIEW_AREA (widget),
0, 0, allocation->width, allocation->height,
BGCOLOR, BGCOLOR, BGCOLOR);
colorsel_triangle_update_preview (triangle);
}
static gboolean
colorsel_triangle_event (GtkWidget *widget,
GdkEvent *event,
ColorselTriangle *triangle)
{
GimpColorSelector *selector = GIMP_COLOR_SELECTOR (triangle);
gint x,y, angle, mousex, mousey;
gint x, y, angle;
gdouble r;
gdouble hue, sat, val;
gint hx,hy, sx,sy, vx,vy;
gint hx, hy;
gint sx, sy;
gint vx, vy;
gint width, height;
width = GIMP_PREVIEW_AREA (triangle->preview)->width;
height = GIMP_PREVIEW_AREA (triangle->preview)->height;
/* return gracefully if the widget is not yet configured or too small */
if (width < MINIMUM_SIZE || height < MINIMUM_SIZE)
return FALSE;
switch (event->type)
{
case GDK_BUTTON_PRESS:
gtk_grab_add (widget);
x = event->button.x - (width - 1) / 2 - 1;
y = - event->button.y + (height - 1) / 2 + 1;
r = sqrt ((gdouble) (x * x + y * y));
r = sqrt ((gdouble) (SQR (x) + SQR (y)));
angle = ((gint) RINT (atan2 (x, y) / G_PI * 180) + 360 ) % 360;
if ( /* r <= triangle->wheelradius && */ r > triangle->triangleradius)
triangle->mode = 1; /* Dragging in the Ring */
else
@ -479,9 +506,13 @@ colorsel_triangle_event (GtkWidget *widget,
break;
case GDK_MOTION_NOTIFY:
x = event->motion.x - (width - 1) / 2 - 1;
y = - event->motion.y + (height - 1) / 2 + 1;
r = sqrt ((gdouble) (x * x + y * y));
gtk_widget_get_pointer (widget, &x, &y);
if (x != event->motion.x || y != event->motion.y)
return FALSE;
x = x - (width - 1) / 2 - 1;
y = - y + (height - 1) / 2 + 1;
r = sqrt ((gdouble) (SQR (x) + SQR (y)));
angle = ((gint) RINT (atan2 (x, y) / G_PI * 180) + 360 ) % 360;
break;
@ -493,22 +524,11 @@ colorsel_triangle_event (GtkWidget *widget,
gimp_color_selector_color_changed (GIMP_COLOR_SELECTOR (triangle));
return FALSE;
break;
default:
gtk_widget_get_pointer (widget, &x, &y);
x = x - (width - 1) / 2 - 1;
y = - y + (height - 1) / 2 + 1;
r = sqrt ((gdouble) (x * x + y * y));
angle = ((gint) RINT (atan2 (x, y) / G_PI * 180) + 360 ) % 360;
break;
return FALSE;
}
gtk_widget_get_pointer (widget, &mousex, &mousey);
if ((event->type == GDK_MOTION_NOTIFY &&
(mousex != event->motion.x || mousey != event->motion.y)))
return FALSE;
if (triangle->mode == 1 ||
(r > triangle->wheelradius &&
(abs (angle - selector->hsv.h * 360.0) < 30 ||
@ -521,12 +541,14 @@ colorsel_triangle_event (GtkWidget *widget,
else
{
hue = selector->hsv.h * 2 * G_PI;
hx = sin (hue) * triangle->triangleradius;
hy = cos (hue) * triangle->triangleradius;
sx = sin (hue - 2 * G_PI / 3) * triangle->triangleradius;
sy = cos (hue - 2 * G_PI / 3) * triangle->triangleradius;
vx = sin (hue + 2 * G_PI / 3) * triangle->triangleradius;
vy = cos (hue + 2 * G_PI / 3) * triangle->triangleradius;
hue = selector->hsv.h * 360.0;
if ((x - sx) * vx + (y - sy) * vy < 0)