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> 2004-08-18 Sven Neumann <sven@gimp.org>
* app/widgets/gimphelp-ids.h: define GIMP_HELP_DOCK_SEPARATOR. * app/widgets/gimphelp-ids.h: define GIMP_HELP_DOCK_SEPARATOR.

View File

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