~centralelyon2010/inkscape/imagelinks2

« back to all changes in this revision

Viewing changes to src/widgets/sp-color-wheel.cpp

  • Committer: JazzyNico
  • Date: 2011-08-29 20:25:30 UTC
  • Revision ID: nicoduf@yahoo.fr-20110829202530-6deuoz11q90usldv
Code refactoring and merging with trunk (revision 10599).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#define __SP_COLOR_WHEEL_C__
2
 
 
3
 
/*
4
 
 * A wheel color widget
5
 
 *
6
 
 * Authors:
7
 
 *   Lauris Kaplinski <lauris@kaplinski.com>
8
 
 *   Jon A. Cruz <jon@joncruz.org>
9
 
 *   John Bintz <jcoswell@coswellproductions.org>
10
 
 *
11
 
 * Copyright (C) 2001-2002 Lauris Kaplinski
12
 
 * Copyright (C) 2003-2004 Authors
13
 
 *
14
 
 * This code is in public domain
15
 
 */
16
 
 
17
 
#include <cstring>
18
 
#include <string>
19
 
 
20
 
#include <gtk/gtksignal.h>
21
 
#include "sp-color-wheel.h"
22
 
 
23
 
#include "libnr/nr-rotate-ops.h"
24
 
#include <2geom/transforms.h>
25
 
 
26
 
#define WHEEL_SIZE 96
27
 
 
28
 
enum {
29
 
    CHANGED,
30
 
    LAST_SIGNAL
31
 
};
32
 
 
33
 
#define noDUMP_CHANGE_INFO
34
 
#define FOO_NAME(x) g_type_name( G_TYPE_FROM_INSTANCE(x) )
35
 
 
36
 
static void sp_color_wheel_class_init (SPColorWheelClass *klass);
37
 
static void sp_color_wheel_init (SPColorWheel *wheel);
38
 
static void sp_color_wheel_destroy (GtkObject *object);
39
 
 
40
 
static void sp_color_wheel_realize (GtkWidget *widget);
41
 
static void sp_color_wheel_size_request (GtkWidget *widget, GtkRequisition *requisition);
42
 
static void sp_color_wheel_size_allocate (GtkWidget *widget, GtkAllocation *allocation);
43
 
 
44
 
static gint sp_color_wheel_expose (GtkWidget *widget, GdkEventExpose *event);
45
 
static gint sp_color_wheel_button_press (GtkWidget *widget, GdkEventButton *event);
46
 
static gint sp_color_wheel_button_release (GtkWidget *widget, GdkEventButton *event);
47
 
static gint sp_color_wheel_motion_notify (GtkWidget *widget, GdkEventMotion *event);
48
 
 
49
 
static void sp_color_wheel_set_hue(SPColorWheel *wheel, gdouble hue);
50
 
static void sp_color_wheel_set_sv( SPColorWheel *wheel, gdouble sat, gdouble value );
51
 
static void sp_color_wheel_recalc_triangle(SPColorWheel *wheel);
52
 
 
53
 
static void sp_color_wheel_paint (SPColorWheel *wheel, GdkRectangle *area);
54
 
static void sp_color_wheel_render_hue_wheel (SPColorWheel *wheel);
55
 
static void sp_color_wheel_render_triangle (SPColorWheel *wheel);
56
 
 
57
 
 
58
 
static gboolean sp_color_wheel_focus(GtkWidget        *widget,
59
 
                                     GtkDirectionType  direction);
60
 
 
61
 
static void sp_color_wheel_process_in_triangle( SPColorWheel *wheel, gdouble x, gdouble y );
62
 
 
63
 
static GtkWidgetClass *parent_class;
64
 
static guint wheel_signals[LAST_SIGNAL] = {0};
65
 
 
66
 
/*
67
 
static double
68
 
get_time (void)
69
 
{
70
 
    GTimeVal tv;
71
 
    g_get_current_time (&tv);
72
 
    return tv.tv_sec + 1e-6 * tv.tv_usec;
73
 
}
74
 
*/
75
 
 
76
 
GType sp_color_wheel_get_type(void)
77
 
{
78
 
    static GType type = 0;
79
 
    if (!type) {
80
 
        GTypeInfo info = {
81
 
            sizeof(SPColorWheelClass),
82
 
            0, // base_init
83
 
            0, // base_finalize
84
 
            (GClassInitFunc)sp_color_wheel_class_init,
85
 
            0, // class_finalize
86
 
            0, // class_data
87
 
            sizeof(SPColorWheel),
88
 
            0, // n_preallocs
89
 
            (GInstanceInitFunc)sp_color_wheel_init,
90
 
            0 // value_table
91
 
        };
92
 
        type = g_type_register_static(GTK_TYPE_WIDGET, "SPColorWheel", &info, static_cast<GTypeFlags>(0));
93
 
    }
94
 
    return type;
95
 
}
96
 
 
97
 
static void
98
 
sp_color_wheel_class_init (SPColorWheelClass *klass)
99
 
{
100
 
    GtkObjectClass *object_class;
101
 
    GtkWidgetClass *widget_class;
102
 
 
103
 
    object_class = (GtkObjectClass *) klass;
104
 
    widget_class = (GtkWidgetClass *) klass;
105
 
 
106
 
    parent_class = (GtkWidgetClass*)gtk_type_class (GTK_TYPE_WIDGET);
107
 
 
108
 
    wheel_signals[CHANGED] = gtk_signal_new ("changed",
109
 
                          (GtkSignalRunType)(GTK_RUN_FIRST | GTK_RUN_NO_RECURSE),
110
 
                          GTK_CLASS_TYPE(object_class),
111
 
                          GTK_SIGNAL_OFFSET (SPColorWheelClass, changed),
112
 
                          gtk_marshal_NONE__NONE,
113
 
                          GTK_TYPE_NONE, 0);
114
 
 
115
 
    object_class->destroy = sp_color_wheel_destroy;
116
 
 
117
 
    widget_class->realize = sp_color_wheel_realize;
118
 
    widget_class->size_request = sp_color_wheel_size_request;
119
 
    widget_class->size_allocate = sp_color_wheel_size_allocate;
120
 
 
121
 
    widget_class->focus = sp_color_wheel_focus;
122
 
 
123
 
    widget_class->expose_event = sp_color_wheel_expose;
124
 
    widget_class->button_press_event = sp_color_wheel_button_press;
125
 
    widget_class->button_release_event = sp_color_wheel_button_release;
126
 
    widget_class->motion_notify_event = sp_color_wheel_motion_notify;
127
 
}
128
 
 
129
 
static void
130
 
sp_color_wheel_init (SPColorWheel *wheel)
131
 
{
132
 
    /* We are widget with window */
133
 
    GTK_WIDGET_UNSET_FLAGS (wheel, GTK_NO_WINDOW);
134
 
    GTK_WIDGET_SET_FLAGS (wheel, GTK_CAN_FOCUS );
135
 
 
136
 
    wheel->dragging = FALSE;
137
 
 
138
 
    wheel->_inTriangle = FALSE;
139
 
    wheel->_triDirty = TRUE;
140
 
    wheel->_triangle = NULL;
141
 
    for ( guint i = 0; i < G_N_ELEMENTS(wheel->_triPoints); i++ )
142
 
    {
143
 
        wheel->_triPoints[i].x = 0;
144
 
        wheel->_triPoints[i].y = 0;
145
 
    }
146
 
    wheel->_triImage = NULL;
147
 
    wheel->_triBs = 0;
148
 
 
149
 
    wheel->_image = NULL;
150
 
    wheel->_bs = 0;
151
 
    wheel->_hue = 0.0;
152
 
    wheel->_sat = 0.9;
153
 
    wheel->_value = 0.25;
154
 
    wheel->_inner = 0;
155
 
    wheel->_center = 0;
156
 
    wheel->_spotValue = 1.0;
157
 
}
158
 
 
159
 
static void
160
 
sp_color_wheel_destroy (GtkObject *object)
161
 
{
162
 
    SPColorWheel *wheel;
163
 
 
164
 
    wheel = SP_COLOR_WHEEL (object);
165
 
 
166
 
    if ( wheel->_image )
167
 
    {
168
 
        g_free( wheel->_image );
169
 
        wheel->_image = NULL;
170
 
        wheel->_bs = 0;
171
 
    }
172
 
 
173
 
    if ( wheel->_triImage )
174
 
    {
175
 
        g_free( wheel->_triImage );
176
 
        wheel->_triImage = NULL;
177
 
        wheel->_triBs = 0;
178
 
    }
179
 
 
180
 
    if (((GtkObjectClass *) (parent_class))->destroy)
181
 
        (* ((GtkObjectClass *) (parent_class))->destroy) (object);
182
 
}
183
 
 
184
 
 
185
 
void sp_color_wheel_get_color( SPColorWheel *wheel, SPColor* color )
186
 
{
187
 
    float rgb[3];
188
 
    gint i;
189
 
    g_return_if_fail (SP_IS_COLOR_WHEEL (wheel));
190
 
    g_return_if_fail (wheel != NULL);
191
 
    g_return_if_fail (color != NULL);
192
 
 
193
 
    sp_color_hsv_to_rgb_floatv (rgb, wheel->_hue, 1.0, 1.0);
194
 
    for ( i = 0; i < 3; i++ )
195
 
    {
196
 
        rgb[i] = (rgb[i] * wheel->_sat) + (wheel->_value * (1.0 - wheel->_sat));
197
 
    }
198
 
 
199
 
    color->set( rgb[0], rgb[1], rgb[2] );
200
 
}
201
 
 
202
 
void sp_color_wheel_set_color( SPColorWheel *wheel, const SPColor* color )
203
 
{
204
 
#ifdef DUMP_CHANGE_INFO
205
 
    g_message("sp_color_wheel_set_color( wheel=%p, %f, %f, %f)", wheel, color->v.c[0], color->v.c[1], color->v.c[2] );
206
 
#endif
207
 
    g_return_if_fail (SP_IS_COLOR_WHEEL (wheel));
208
 
    g_return_if_fail (wheel != NULL);
209
 
    g_return_if_fail (color != NULL);
210
 
 
211
 
    float hue;
212
 
    float scratch[3];
213
 
    float rgb[3];
214
 
 
215
 
    sp_color_get_rgb_floatv (color, rgb);
216
 
    sp_color_rgb_to_hsv_floatv (scratch, rgb[0], rgb[1], rgb[2]);
217
 
    hue = scratch[0];
218
 
 
219
 
    sp_color_hsv_to_rgb_floatv (scratch, hue, 1.0, 1.0);
220
 
 
221
 
    gint lowInd = 0;
222
 
    gint hiInd = 0;
223
 
    for ( int i = 1; i < 3; i++ )
224
 
    {
225
 
        if ( scratch[i] < scratch[lowInd] )
226
 
        {
227
 
            lowInd = i;
228
 
        }
229
 
        if ( scratch[i] > scratch[hiInd] )
230
 
        {
231
 
            hiInd = i;
232
 
        }
233
 
    }
234
 
    // scratch[lowInd] should always be 0
235
 
    gdouble sat = (rgb[hiInd] - rgb[lowInd])/(scratch[hiInd]-scratch[lowInd]);
236
 
    gdouble val = sat < 1.0 ? (rgb[hiInd] - sat * scratch[hiInd])/(1.0-sat) : 0.0;
237
 
 
238
 
 
239
 
    sp_color_wheel_set_hue(wheel, hue);
240
 
    sp_color_wheel_set_sv(wheel, sat, val);
241
 
}
242
 
 
243
 
gboolean sp_color_wheel_is_adjusting( SPColorWheel *wheel )
244
 
{
245
 
    g_return_val_if_fail( SP_IS_COLOR_WHEEL(wheel), FALSE );
246
 
    return wheel->dragging;
247
 
}
248
 
 
249
 
static void
250
 
sp_color_wheel_realize (GtkWidget *widget)
251
 
{
252
 
    SPColorWheel *wheel;
253
 
    GdkWindowAttr attributes;
254
 
    gint attributes_mask;
255
 
 
256
 
    wheel = SP_COLOR_WHEEL (widget);
257
 
 
258
 
    GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
259
 
 
260
 
    attributes.window_type = GDK_WINDOW_CHILD;
261
 
    attributes.x = widget->allocation.x;
262
 
    attributes.y = widget->allocation.y;
263
 
    attributes.width = widget->allocation.width;
264
 
    attributes.height = widget->allocation.height;
265
 
    attributes.wclass = GDK_INPUT_OUTPUT;
266
 
    attributes.visual = gdk_rgb_get_visual ();
267
 
    attributes.colormap = gdk_rgb_get_cmap ();
268
 
    attributes.event_mask = gtk_widget_get_events (widget);
269
 
    attributes.event_mask |= (GDK_EXPOSURE_MASK |
270
 
                  GDK_BUTTON_PRESS_MASK |
271
 
                  GDK_BUTTON_RELEASE_MASK |
272
 
                  GDK_POINTER_MOTION_MASK |
273
 
                  GDK_ENTER_NOTIFY_MASK |
274
 
                  GDK_LEAVE_NOTIFY_MASK |
275
 
                  GDK_FOCUS_CHANGE_MASK );
276
 
    attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
277
 
 
278
 
    widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
279
 
    gdk_window_set_user_data (widget->window, widget);
280
 
 
281
 
    widget->style = gtk_style_attach (widget->style, widget->window);
282
 
}
283
 
 
284
 
static void
285
 
sp_color_wheel_size_request (GtkWidget *widget, GtkRequisition *requisition)
286
 
{
287
 
    SPColorWheel *wheel;
288
 
 
289
 
    wheel = SP_COLOR_WHEEL (widget);
290
 
 
291
 
    requisition->width = WHEEL_SIZE + widget->style->xthickness * 2;
292
 
    requisition->height = WHEEL_SIZE + widget->style->ythickness * 2;
293
 
}
294
 
 
295
 
static void
296
 
sp_color_wheel_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
297
 
{
298
 
    SPColorWheel *wheel;
299
 
 
300
 
    wheel = SP_COLOR_WHEEL (widget);
301
 
 
302
 
    widget->allocation = *allocation;
303
 
 
304
 
    wheel->_center = MIN(allocation->width, allocation->height)/2;
305
 
    wheel->_inner = (3 * wheel->_center)/4;
306
 
    if ( wheel->_image )
307
 
    {
308
 
        g_free( wheel->_image );
309
 
        wheel->_image = NULL;
310
 
        wheel->_bs = 0;
311
 
    }
312
 
 
313
 
    // Need to render the gradient before we do the triangle over
314
 
    sp_color_wheel_render_hue_wheel(wheel);
315
 
    sp_color_wheel_recalc_triangle(wheel);
316
 
    sp_color_wheel_render_triangle(wheel);
317
 
 
318
 
    if (GTK_WIDGET_REALIZED (widget)) {
319
 
        /* Resize GdkWindow */
320
 
        gdk_window_move_resize (widget->window, allocation->x, allocation->y, allocation->width, allocation->height);
321
 
    }
322
 
}
323
 
 
324
 
static gint
325
 
sp_color_wheel_expose (GtkWidget *widget, GdkEventExpose *event)
326
 
{
327
 
    SPColorWheel *wheel;
328
 
 
329
 
    wheel = SP_COLOR_WHEEL (widget);
330
 
 
331
 
    if (GTK_WIDGET_DRAWABLE (widget)) {
332
 
        gint width, height;
333
 
        width = widget->allocation.width;
334
 
        height = widget->allocation.height;
335
 
        sp_color_wheel_paint (wheel, &event->area);
336
 
    }
337
 
 
338
 
    return TRUE;
339
 
}
340
 
 
341
 
static gint
342
 
sp_color_wheel_button_press (GtkWidget *widget, GdkEventButton *event)
343
 
{
344
 
    SPColorWheel *wheel;
345
 
 
346
 
    wheel = SP_COLOR_WHEEL (widget);
347
 
 
348
 
    if (event->button == 1) {
349
 
        gint cx, cw;
350
 
        cx = widget->style->xthickness;
351
 
        cw = widget->allocation.width - 2 * cx;
352
 
        gboolean grabbed = FALSE;
353
 
 
354
 
        {
355
 
            double dx = event->x - wheel->_center;
356
 
            double dy = event->y - wheel->_center;
357
 
            gint hyp = static_cast<gint>(ABS(dx*dx) + ABS(dy*dy));
358
 
            if ( hyp <= (wheel->_center*wheel->_center) )
359
 
            {
360
 
                if ( hyp >= (wheel->_inner*wheel->_inner) )
361
 
                {
362
 
                    gdouble rot = atan2( dy, -dx );
363
 
                    sp_color_wheel_set_hue (wheel, (rot + M_PI) / (2.0 * M_PI));
364
 
 
365
 
                    wheel->_inTriangle = FALSE;
366
 
                    grabbed = TRUE;
367
 
                }
368
 
                else if ( wheel->_triangle && gdk_region_point_in( wheel->_triangle, (gint)event->x, (gint)event->y ) )
369
 
                {
370
 
                    wheel->_inTriangle = TRUE;
371
 
                    sp_color_wheel_process_in_triangle( wheel, event->x, event->y );
372
 
                    grabbed = TRUE;
373
 
                }
374
 
            }
375
 
        }
376
 
 
377
 
        if ( grabbed )
378
 
        {
379
 
            gtk_widget_queue_draw( widget );
380
 
            gtk_widget_grab_focus( widget );
381
 
 
382
 
            wheel->dragging = TRUE;
383
 
#ifdef DUMP_CHANGE_INFO
384
 
            {
385
 
                SPColor color;
386
 
                sp_color_wheel_get_color( wheel, &color );
387
 
                g_message( "%s:%d: About to signal %s to color %08x in %s", __FILE__, __LINE__,
388
 
                           "CHANGED",
389
 
                           color.toRGBA32( 0 ), FOO_NAME(wheel));
390
 
            }
391
 
#endif
392
 
            gtk_signal_emit (GTK_OBJECT (wheel), wheel_signals[CHANGED]);
393
 
            gdk_pointer_grab (widget->window, FALSE,
394
 
                              (GdkEventMask)(GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK),
395
 
                              NULL, NULL, event->time);
396
 
        }
397
 
    }
398
 
 
399
 
    return TRUE;
400
 
}
401
 
 
402
 
static gint
403
 
sp_color_wheel_button_release (GtkWidget *widget, GdkEventButton *event)
404
 
{
405
 
    SPColorWheel *wheel;
406
 
 
407
 
    wheel = SP_COLOR_WHEEL (widget);
408
 
 
409
 
    if (event->button == 1) {
410
 
        gdk_pointer_ungrab (event->time);
411
 
        wheel->dragging = FALSE;
412
 
 
413
 
#ifdef DUMP_CHANGE_INFO
414
 
        {
415
 
            SPColor color;
416
 
            sp_color_wheel_get_color( wheel, &color );
417
 
            g_message( "%s:%d: About to signal %s to color %08x in %s", __FILE__, __LINE__,
418
 
                       "CHANGED",
419
 
                       color.toRGBA32( 0 ), FOO_NAME(wheel));
420
 
        }
421
 
#endif
422
 
        gtk_signal_emit (GTK_OBJECT (wheel), wheel_signals[CHANGED]);
423
 
    }
424
 
 
425
 
    return TRUE;
426
 
}
427
 
 
428
 
static gint
429
 
sp_color_wheel_motion_notify (GtkWidget *widget, GdkEventMotion *event)
430
 
{
431
 
    SPColorWheel *wheel;
432
 
 
433
 
    wheel = SP_COLOR_WHEEL (widget);
434
 
 
435
 
    if (wheel->dragging) {
436
 
        double dx = event->x - wheel->_center;
437
 
        double dy = event->y - wheel->_center;
438
 
        if ( !wheel->_inTriangle )
439
 
        {
440
 
            gdouble rot = atan2( dy, -dx );
441
 
            sp_color_wheel_set_hue (wheel, (rot + M_PI) / (2.0 * M_PI));
442
 
        }
443
 
        else
444
 
        {
445
 
            sp_color_wheel_process_in_triangle( wheel, event->x, event->y );
446
 
        }
447
 
 
448
 
#ifdef DUMP_CHANGE_INFO
449
 
        {
450
 
            SPColor color;
451
 
            sp_color_wheel_get_color( wheel, &color );
452
 
            g_message( "%s:%d: About to signal %s to color %08x in %s", __FILE__, __LINE__,
453
 
                       "CHANGED",
454
 
                       color.toRGBA32( 0 ), FOO_NAME(wheel));
455
 
        }
456
 
#endif
457
 
        gtk_signal_emit (GTK_OBJECT (wheel), wheel_signals[CHANGED]);
458
 
    }
459
 
 
460
 
    return TRUE;
461
 
}
462
 
 
463
 
GtkWidget *
464
 
sp_color_wheel_new ()
465
 
{
466
 
    SPColorWheel *wheel;
467
 
 
468
 
    wheel = (SPColorWheel*)gtk_type_new (SP_TYPE_COLOR_WHEEL);
469
 
 
470
 
    return GTK_WIDGET (wheel);
471
 
}
472
 
 
473
 
static void sp_color_wheel_set_hue(SPColorWheel *wheel, gdouble hue)
474
 
{
475
 
    g_return_if_fail (SP_IS_COLOR_WHEEL (wheel));
476
 
 
477
 
    if ( wheel->_hue != hue )
478
 
    {
479
 
        wheel->_hue = hue;
480
 
 
481
 
        sp_color_wheel_recalc_triangle(wheel);
482
 
 
483
 
        SPColor color;
484
 
        gfloat rgb[3];
485
 
        sp_color_wheel_get_color( wheel, &color );
486
 
        sp_color_get_rgb_floatv (&color, rgb);
487
 
 
488
 
        wheel->_spotValue = ( (0.299 * rgb[0]) + (0.587 * rgb[1]) + (0.114 * rgb[2]) );
489
 
 
490
 
        gtk_widget_queue_draw (GTK_WIDGET (wheel));
491
 
    }
492
 
}
493
 
 
494
 
 
495
 
static void sp_color_wheel_set_sv( SPColorWheel *wheel, gdouble sat, gdouble value )
496
 
{
497
 
    static gdouble epsilon = 1e-6;
498
 
    gboolean changed = FALSE;
499
 
 
500
 
    if ( ABS( wheel->_sat - sat ) > epsilon )
501
 
    {
502
 
        wheel->_sat = sat;
503
 
        changed = TRUE;
504
 
    }
505
 
    if ( ABS( wheel->_value - value ) > epsilon )
506
 
    {
507
 
        wheel->_value = value;
508
 
        changed = TRUE;
509
 
    }
510
 
 
511
 
    if ( changed )
512
 
    {
513
 
        SPColor color;
514
 
        gfloat rgb[3];
515
 
        sp_color_wheel_get_color( wheel, &color );
516
 
        sp_color_get_rgb_floatv (&color, rgb);
517
 
 
518
 
        wheel->_spotValue = ( (0.299 * rgb[0]) + (0.587 * rgb[1]) + (0.114 * rgb[2]) );
519
 
 
520
 
#ifdef DUMP_CHANGE_INFO
521
 
        {
522
 
            SPColor color;
523
 
            sp_color_wheel_get_color( wheel, &color );
524
 
            g_message( "%s:%d: About to signal %s to color %08x in %s", __FILE__, __LINE__,
525
 
                       "CHANGED",
526
 
                       color.toRGBA32( 0 ), FOO_NAME(wheel));
527
 
        }
528
 
#endif
529
 
        gtk_signal_emit (GTK_OBJECT (wheel), wheel_signals[CHANGED]);
530
 
    }
531
 
    gtk_widget_queue_draw (GTK_WIDGET (wheel));
532
 
}
533
 
 
534
 
static void sp_color_wheel_recalc_triangle(SPColorWheel *wheel)
535
 
{
536
 
    if ( wheel->_triangle )
537
 
    {
538
 
        gdk_region_destroy( wheel->_triangle );
539
 
        wheel->_triangle = NULL;
540
 
    }
541
 
    wheel->_triDirty = TRUE;
542
 
 
543
 
    if ( wheel->_center > 0 && wheel->_inner > 0 )
544
 
    {
545
 
        gdouble dx = cos( M_PI * 2 * wheel->_hue );
546
 
        gdouble dy = -sin( M_PI * 2 * wheel->_hue );
547
 
 
548
 
        wheel->_triPoints[0].x = wheel->_center + static_cast<gint>(dx * wheel->_inner);
549
 
        wheel->_triPoints[0].y = wheel->_center + static_cast<gint>(dy * wheel->_inner);
550
 
 
551
 
        dx = cos( M_PI * 2 * wheel->_hue + ((M_PI * 2)/ 3) );
552
 
        dy = -sin( M_PI * 2 * wheel->_hue + ((M_PI * 2) / 3) );
553
 
        wheel->_triPoints[1].x = wheel->_center + static_cast<gint>(dx * wheel->_inner);
554
 
        wheel->_triPoints[1].y = wheel->_center + static_cast<gint>(dy * wheel->_inner);
555
 
 
556
 
        dx = cos( M_PI * 2 * wheel->_hue - ((M_PI*2) / 3) );
557
 
        dy = -sin( M_PI * 2 * wheel->_hue - ((M_PI*2) / 3) );
558
 
        wheel->_triPoints[2].x = wheel->_center + static_cast<gint>(dx * wheel->_inner);
559
 
        wheel->_triPoints[2].y = wheel->_center + static_cast<gint>(dy * wheel->_inner);
560
 
 
561
 
 
562
 
        wheel->_triangle = gdk_region_polygon( wheel->_triPoints,
563
 
                                               3,
564
 
                                               GDK_EVEN_ODD_RULE );
565
 
    }
566
 
}
567
 
 
568
 
#define VERT_SWAP( X, Y ) { \
569
 
    gfloat tmpF; \
570
 
 \
571
 
    tmpF = point##X.x; \
572
 
    point##X.x = point##Y.x; \
573
 
    point##Y.x = tmpF; \
574
 
 \
575
 
    tmpF = point##X.y; \
576
 
    point##X.y = point##Y.y; \
577
 
    point##Y.y = tmpF; \
578
 
 \
579
 
    tmpF = rgb##X[0]; \
580
 
    rgb##X[0] = rgb##Y[0]; \
581
 
    rgb##Y[0] = tmpF; \
582
 
 \
583
 
    tmpF = rgb##X[1]; \
584
 
    rgb##X[1] = rgb##Y[1]; \
585
 
    rgb##Y[1] = tmpF; \
586
 
 \
587
 
    tmpF = rgb##X[2]; \
588
 
    rgb##X[2] = rgb##Y[2]; \
589
 
    rgb##Y[2] = tmpF; \
590
 
}
591
 
 
592
 
#define VERT_COPY( dst, src ) { \
593
 
    point##dst.x = point##src.x; \
594
 
 \
595
 
    point##dst.y = point##src.y; \
596
 
 \
597
 
    rgb##dst[0] = rgb##src[0]; \
598
 
    rgb##dst[1] = rgb##src[1]; \
599
 
    rgb##dst[2] = rgb##src[2]; \
600
 
}
601
 
 
602
 
typedef struct {
603
 
    gfloat x;
604
 
    gfloat y;
605
 
} PointF;
606
 
 
607
 
/**
608
 
 * Render the provided color wheel information as a triangle.
609
 
 */
610
 
static void sp_color_wheel_render_triangle (SPColorWheel *wheel)
611
 
{
612
 
    if ( wheel->_image )
613
 
    {
614
 
        if ( wheel->_triBs < wheel->_bs )
615
 
        {
616
 
            g_free( wheel->_triImage );
617
 
            wheel->_triImage = NULL;
618
 
        }
619
 
 
620
 
        if (wheel->_triDirty || !wheel->_triImage)
621
 
        {
622
 
            if ( !wheel->_triImage )
623
 
            {
624
 
                wheel->_triBs = wheel->_bs;
625
 
                wheel->_triImage = g_new (guchar, wheel->_triBs * 3);
626
 
                //g_message( "just allocated %fKB for tri", ((wheel->_triBs * 3.0)/1024.0) );
627
 
            }
628
 
 
629
 
            memcpy( wheel->_triImage, wheel->_image, wheel->_bs * 3 );
630
 
 
631
 
            PointF pointA, pointB, pointC;
632
 
            pointA.x = wheel->_triPoints[0].x;
633
 
            pointA.y = wheel->_triPoints[0].y;
634
 
            pointB.x = wheel->_triPoints[1].x;
635
 
            pointB.y = wheel->_triPoints[1].y;
636
 
            pointC.x = wheel->_triPoints[2].x;
637
 
            pointC.y = wheel->_triPoints[2].y;
638
 
 
639
 
            gfloat rgbA[3];
640
 
            gfloat rgbB[3] = {0.0, 0.0, 0.0};
641
 
            gfloat rgbC[3] = {1.0, 1.0, 1.0};
642
 
 
643
 
            sp_color_hsv_to_rgb_floatv (rgbA, wheel->_hue, 1.0, 1.0);
644
 
 
645
 
// Start of Gouraud fill ============================================================
646
 
            gint rowStride = wheel->_center * 2 * 3;
647
 
            guchar* dst = wheel->_triImage;
648
 
 
649
 
            if ( pointC.y < pointB.y )
650
 
                VERT_SWAP( C, B );
651
 
 
652
 
            if ( pointC.y < pointA.y )
653
 
                VERT_SWAP( C, A );
654
 
 
655
 
            if ( pointB.y < pointA.y )
656
 
                VERT_SWAP( B, A );
657
 
 
658
 
            if ( pointA.y == pointB.y && pointB.x < pointA.x )
659
 
                VERT_SWAP( A, B );
660
 
 
661
 
            gfloat dr, dg, db;
662
 
 
663
 
            gfloat dx1,dx2,dx3;
664
 
            gfloat dr1,dr2,dr3;
665
 
            gfloat dg1,dg2,dg3;
666
 
            gfloat db1,db2,db3;
667
 
 
668
 
 
669
 
            PointF pointS;
670
 
            PointF pointE;
671
 
            PointF pointP;
672
 
            gfloat rgbS[3];
673
 
            gfloat rgbE[3];
674
 
            gfloat rgbP[3];
675
 
 
676
 
 
677
 
            if (pointB.y-pointA.y > 0)
678
 
            {
679
 
                dx1=(pointB.x-pointA.x)/(pointB.y-pointA.y);
680
 
                dr1=(rgbB[0]-rgbA[0])/(pointB.y-pointA.y);
681
 
                dg1=(rgbB[1]-rgbA[1])/(pointB.y-pointA.y);
682
 
                db1=(rgbB[2]-rgbA[2])/(pointB.y-pointA.y);
683
 
            }
684
 
            else
685
 
            {
686
 
                dx1=dr1=dg1=db1=0;
687
 
            }
688
 
 
689
 
            if (pointC.y-pointA.y > 0)
690
 
            {
691
 
                dx2=(pointC.x-pointA.x)/(pointC.y-pointA.y);
692
 
                dr2=(rgbC[0]-rgbA[0])/(pointC.y-pointA.y);
693
 
                dg2=(rgbC[1]-rgbA[1])/(pointC.y-pointA.y);
694
 
                db2=(rgbC[2]-rgbA[2])/(pointC.y-pointA.y);
695
 
            }
696
 
            else
697
 
            {
698
 
                dx2=dr2=dg2=db2=0;
699
 
            }
700
 
 
701
 
            if (pointC.y-pointB.y > 0)
702
 
            {
703
 
                dx3=(pointC.x-pointB.x)/(pointC.y-pointB.y);
704
 
                dr3=(rgbC[0]-rgbB[0])/(pointC.y-pointB.y);
705
 
                dg3=(rgbC[1]-rgbB[1])/(pointC.y-pointB.y);
706
 
                db3=(rgbC[2]-rgbB[2])/(pointC.y-pointB.y);
707
 
            }
708
 
            else
709
 
            {
710
 
                dx3=dr3=dg3=db3=0;
711
 
            }
712
 
 
713
 
            VERT_COPY(S, A);
714
 
            VERT_COPY(E, A);
715
 
 
716
 
            int runs = 1; int fill_mode = 0;
717
 
 
718
 
            if ( dx1 == 0 )
719
 
            {
720
 
                fill_mode = 0;
721
 
            }
722
 
            else if ( dx1 > dx2 )
723
 
            {
724
 
                fill_mode = 1; runs = 2;
725
 
            }
726
 
            else if ( dx1 )
727
 
            {
728
 
                fill_mode = 2; runs = 2;
729
 
            }
730
 
 
731
 
            gfloat targetY = 0;
732
 
            int fill_direction_mode = 0;
733
 
 
734
 
            for (int current_run = 0; current_run < runs; current_run++)
735
 
            {
736
 
                targetY = pointC.y;
737
 
                switch (fill_mode)
738
 
                {
739
 
                    case 0:
740
 
                        VERT_COPY(E,B);
741
 
                        fill_direction_mode = 0;
742
 
                        break;
743
 
                    case 1:
744
 
                        if (current_run == 0) {
745
 
                            targetY = pointB.y;
746
 
                            fill_direction_mode = 1;
747
 
                        } else {
748
 
                            VERT_COPY(E,B);
749
 
                            fill_direction_mode = 0;
750
 
                        }
751
 
                        break;
752
 
                    case 2:
753
 
                        if (current_run == 0) {
754
 
                            targetY = pointB.y;
755
 
                            fill_direction_mode = 2;
756
 
                        } else {
757
 
                            VERT_COPY(S,B);
758
 
                            fill_direction_mode = 3;
759
 
                        }
760
 
                        break;
761
 
                }
762
 
 
763
 
                for(;pointS.y <= targetY; pointS.y++,pointE.y++)
764
 
                {
765
 
                    if (pointE.x-pointS.x > 0)
766
 
                    {
767
 
                        dr=(rgbE[0]-rgbS[0])/(pointE.x-pointS.x);
768
 
                        dg=(rgbE[1]-rgbS[1])/(pointE.x-pointS.x);
769
 
                        db=(rgbE[2]-rgbS[2])/(pointE.x-pointS.x);
770
 
                    }
771
 
                    else
772
 
                    {
773
 
                        dr=dg=db=0;
774
 
                    }
775
 
                    VERT_COPY(P,S);
776
 
                    dst = wheel->_triImage + (static_cast<gint>(pointP.y) * rowStride);
777
 
                    dst += static_cast<gint>(pointP.x) * 3;
778
 
                    for(;pointP.x < pointE.x;pointP.x++)
779
 
                    {
780
 
                        //putpixel(P);
781
 
                        dst[0] = SP_COLOR_F_TO_U(rgbP[0]);
782
 
                        dst[1] = SP_COLOR_F_TO_U(rgbP[1]);
783
 
                        dst[2] = SP_COLOR_F_TO_U(rgbP[2]);
784
 
                        dst += 3;
785
 
                        rgbP[0]+=dr; rgbP[1]+=dg; rgbP[2]+=db;
786
 
                    }
787
 
 
788
 
                    switch (fill_direction_mode) {
789
 
                        case 0:
790
 
                            pointS.x+=dx2; rgbS[0]+=dr2; rgbS[1]+=dg2; rgbS[2]+=db2;
791
 
                            pointE.x+=dx3; rgbE[0]+=dr3; rgbE[1]+=dg3; rgbE[2]+=db3;
792
 
                            break;
793
 
                        case 1:
794
 
                            pointS.x+=dx2; rgbS[0]+=dr2; rgbS[1]+=dg2; rgbS[2]+=db2;
795
 
                            pointE.x+=dx1; rgbE[0]+=dr1; rgbE[1]+=dg1; rgbE[2]+=db1;
796
 
                            break;
797
 
                        case 2:
798
 
                            pointS.x+=dx1; rgbS[0]+=dr1; rgbS[1]+=dg1; rgbS[2]+=db1;
799
 
                            pointE.x+=dx2; rgbE[0]+=dr2; rgbE[1]+=dg2; rgbE[2]+=db2;
800
 
                            break;
801
 
                        case 3:
802
 
                            pointS.x+=dx3; rgbS[0]+=dr3; rgbS[1]+=dg3; rgbS[2]+=db3;
803
 
                            pointE.x+=dx2; rgbE[0]+=dr2; rgbE[1]+=dg2; rgbE[2]+=db2;
804
 
                            break;
805
 
                    }
806
 
                }
807
 
            }
808
 
 
809
 
 
810
 
// End of Gouraud fill  ============================================================
811
 
 
812
 
            wheel->_triDirty = FALSE;
813
 
            //g_message( "Just updated triangle" );
814
 
        }
815
 
    }
816
 
}
817
 
 
818
 
static void
819
 
sp_color_wheel_paint (SPColorWheel *wheel, GdkRectangle *area)
820
 
{
821
 
    GtkWidget *widget;
822
 
    GdkRectangle warea, carea;
823
 
    GdkRectangle wpaint, cpaint;
824
 
 
825
 
    widget = GTK_WIDGET (wheel);
826
 
 
827
 
    /* Widget area */
828
 
    warea.x = 0;
829
 
    warea.y = 0;
830
 
    warea.width = widget->allocation.width;
831
 
    warea.height = widget->allocation.height;
832
 
 
833
 
    /* Color gradient area */
834
 
    carea.x = widget->style->xthickness;
835
 
    carea.y = widget->style->ythickness;
836
 
    carea.width = widget->allocation.width - 2 * carea.x;
837
 
    carea.height = widget->allocation.height - 2 * carea.y;
838
 
 
839
 
    /* Actual paintable area */
840
 
    if (!gdk_rectangle_intersect (area, &warea, &wpaint)) return;
841
 
 
842
 
    //g_message( "Painted as state %d", widget->state );
843
 
 
844
 
    /* Paintable part of color gradient area */
845
 
    if (gdk_rectangle_intersect (area, &carea, &cpaint)) {
846
 
        sp_color_wheel_render_hue_wheel (wheel);
847
 
        sp_color_wheel_render_triangle (wheel);
848
 
    }
849
 
 
850
 
/*
851
 
    gtk_draw_box (widget->style,
852
 
                  widget->window,
853
 
                  (GtkStateType)widget->state,
854
 
                  GTK_SHADOW_NONE,
855
 
                  warea.x,
856
 
                  warea.y,
857
 
                  warea.width,
858
 
                  warea.height);
859
 
*/
860
 
 
861
 
    gtk_style_apply_default_background( widget->style,
862
 
                                        widget->window,
863
 
                                        TRUE,
864
 
                                        (GtkStateType)widget->state,
865
 
                                        NULL,
866
 
                                        0,
867
 
                                        0,
868
 
                                        warea.width,
869
 
                                        warea.height);
870
 
 
871
 
 
872
 
    /* Draw shadow */
873
 
/*
874
 
    gtk_paint_shadow (widget->style, widget->window,
875
 
              (GtkStateType)widget->state, GTK_SHADOW_IN,
876
 
              NULL, widget, "colorwheel",
877
 
              0, 0,
878
 
              warea.width, warea.height);
879
 
*/
880
 
 
881
 
 
882
 
    /* Draw pixelstore */
883
 
    if (wheel->_triImage != NULL) {
884
 
        //gdouble start, end;
885
 
        //start = get_time();
886
 
        gdk_draw_rgb_image (widget->window, widget->style->black_gc,
887
 
                            0, 0,//cpaint.x, cpaint.y,
888
 
                            //cpaint.width, cpaint.height,
889
 
                            wheel->_center * 2, wheel->_center * 2,
890
 
                            GDK_RGB_DITHER_MAX,
891
 
                            wheel->_triImage, wheel->_center * 6);
892
 
 
893
 
        //end = get_time();
894
 
        //g_message( "blits took %f", (end-start) );
895
 
    }
896
 
 
897
 
    {
898
 
        gdouble dx = cos( M_PI * 2 * wheel->_hue );
899
 
        gdouble dy = -sin( M_PI * 2 * wheel->_hue );
900
 
 
901
 
        gfloat rgb[3];
902
 
        sp_color_hsv_to_rgb_floatv (rgb, wheel->_hue, 1.0, 1.0);
903
 
 
904
 
        GdkGC *line_gc = (( (0.299 * rgb[0]) + (0.587 * rgb[1]) + (0.114 * rgb[2]) ) < 0.5) ? widget->style->white_gc : widget->style->black_gc;
905
 
 
906
 
        gint inx = wheel->_center + static_cast<gint>(dx * wheel->_inner);
907
 
        gint iny = wheel->_center + static_cast<gint>(dy * wheel->_inner);
908
 
 
909
 
 
910
 
        gdk_draw_line (widget->window, line_gc,
911
 
                       inx, iny,
912
 
                       wheel->_center + static_cast<gint>(dx * wheel->_center), wheel->_center + static_cast<gint>(dy * wheel->_center) );
913
 
 
914
 
 
915
 
        GdkGCValues values;
916
 
 
917
 
        if ( GTK_WIDGET_HAS_FOCUS(wheel) )
918
 
        {
919
 
            line_gc = widget->style->black_gc;
920
 
 
921
 
            gdk_gc_get_values ( line_gc, &values );
922
 
 
923
 
            gdk_gc_set_line_attributes ( line_gc,
924
 
                                         3, // Line width
925
 
                                         values.line_style, //GDK_LINE_SOLID,
926
 
                                         values.cap_style, //GDK_CAP_BUTT,
927
 
                                         values.join_style ); //GDK_JOIN_MITER );
928
 
 
929
 
            if ( wheel->_inTriangle )
930
 
            {
931
 
                gdk_draw_line (widget->window, line_gc,
932
 
                               wheel->_triPoints[0].x, wheel->_triPoints[0].y,
933
 
                               wheel->_triPoints[1].x, wheel->_triPoints[1].y );
934
 
 
935
 
                gdk_draw_line (widget->window, line_gc,
936
 
                               wheel->_triPoints[1].x, wheel->_triPoints[1].y,
937
 
                               wheel->_triPoints[2].x, wheel->_triPoints[2].y );
938
 
 
939
 
                gdk_draw_line (widget->window, line_gc,
940
 
                               wheel->_triPoints[2].x, wheel->_triPoints[2].y,
941
 
                               wheel->_triPoints[0].x, wheel->_triPoints[0].y );
942
 
            }
943
 
            else
944
 
            {
945
 
                gdk_draw_arc (widget->window, line_gc,
946
 
                              FALSE, // filled
947
 
                              0, 0,
948
 
                              wheel->_center * 2, wheel->_center * 2,
949
 
                              0, 64 * 360 );
950
 
 
951
 
                gint diff = wheel->_center - wheel->_inner;
952
 
 
953
 
                gdk_draw_arc (widget->window, line_gc,
954
 
                              FALSE, // filled
955
 
                              diff, diff,
956
 
                              wheel->_inner * 2, wheel->_inner * 2,
957
 
                              0, 64 * 360 );
958
 
 
959
 
            }
960
 
            gdk_gc_set_line_attributes ( line_gc,
961
 
                                         values.line_width, // Line width
962
 
                                         values.line_style, //GDK_LINE_SOLID,
963
 
                                         values.cap_style, //GDK_CAP_BUTT,
964
 
                                         values.join_style ); //GDK_JOIN_MITER );
965
 
        }
966
 
// ==========
967
 
 
968
 
//        line_gc = (p[3] < 0x80) ? widget->style->white_gc : widget->style->black_gc;
969
 
        line_gc = (wheel->_spotValue < 0.5) ? widget->style->white_gc : widget->style->black_gc;
970
 
 
971
 
        gdk_gc_get_values ( line_gc, &values );
972
 
 
973
 
        gdk_gc_set_line_attributes ( line_gc,
974
 
                                     2, // Line width
975
 
                                     values.line_style, //GDK_LINE_SOLID,
976
 
                                     values.cap_style, //GDK_CAP_BUTT,
977
 
                                     values.join_style ); //GDK_JOIN_MITER );
978
 
 
979
 
        gint pointX = (gint)( (1.0 - wheel->_sat) * ((1.0-wheel->_value)*(gdouble)wheel->_triPoints[1].x + wheel->_value*(gdouble)wheel->_triPoints[2].x)
980
 
            + (wheel->_sat * wheel->_triPoints[0].x) );
981
 
 
982
 
        gint pointY = (gint)( (1.0 - wheel->_sat) * ((1.0-wheel->_value)*(gdouble)wheel->_triPoints[1].y + wheel->_value*(gdouble)wheel->_triPoints[2].y)
983
 
            + (wheel->_sat * wheel->_triPoints[0].y) );
984
 
 
985
 
 
986
 
        gdk_gc_set_line_attributes ( line_gc,
987
 
                                     values.line_width, // Line width
988
 
                                     values.line_style, //GDK_LINE_SOLID,
989
 
                                     values.cap_style, //GDK_CAP_BUTT,
990
 
                                     values.join_style ); //GDK_JOIN_MITER );
991
 
 
992
 
        gdk_draw_arc (widget->window, line_gc,
993
 
                      FALSE, // filled
994
 
                      pointX - 4, pointY - 4,
995
 
                      8, 8,
996
 
                      0, 64 * 360 );
997
 
 
998
 
        gdk_draw_arc (widget->window, line_gc,
999
 
                      FALSE, // filled
1000
 
                      pointX - 3, pointY - 3,
1001
 
                      6, 6,
1002
 
                      0, 64 * 360 );
1003
 
 
1004
 
 
1005
 
 
1006
 
    }
1007
 
}
1008
 
 
1009
 
/* Colors are << 16 */
1010
 
 
1011
 
static void
1012
 
sp_color_wheel_render_hue_wheel (SPColorWheel *wheel)
1013
 
{
1014
 
    guchar *dp;
1015
 
    gint x, y;
1016
 
    guint r, g, b;
1017
 
    gint size = wheel->_center * 2;
1018
 
    gboolean dirty = FALSE;
1019
 
 
1020
 
    if (wheel->_image && (wheel->_bs < (size * size) )) {
1021
 
        g_free (wheel->_image);
1022
 
        wheel->_image = NULL;
1023
 
        wheel->_bs = 0;
1024
 
 
1025
 
        if ( wheel->_triImage )
1026
 
        {
1027
 
            g_free( wheel->_triImage );
1028
 
            wheel->_triImage = NULL;
1029
 
            wheel->_triBs = 0;
1030
 
            wheel->_triDirty = TRUE;
1031
 
        }
1032
 
    }
1033
 
 
1034
 
    if (!wheel->_image) {
1035
 
        wheel->_image = g_new (guchar, size * size * 3);
1036
 
        wheel->_bs = size * size;
1037
 
        dirty = TRUE;
1038
 
        //g_message( "just allocated %fKB for hue", ((wheel->_bs * 3.0)/1024.0) );
1039
 
    }
1040
 
 
1041
 
    if ( dirty )
1042
 
    {
1043
 
        GtkWidget* widget = GTK_WIDGET (wheel);
1044
 
        dp = wheel->_image;
1045
 
        r = widget->style->bg[widget->state].red >> 8;
1046
 
        g = widget->style->bg[widget->state].green >> 8;
1047
 
        b = widget->style->bg[widget->state].blue >> 8;
1048
 
        //g_message( "Rendered as state %d", widget->state );
1049
 
 
1050
 
        gint offset = wheel->_center;
1051
 
        gint inner = wheel->_inner * wheel->_inner;
1052
 
        gint rad = wheel->_center * wheel->_center;
1053
 
 
1054
 
        for (x = 0; x < size; x++) {
1055
 
            guchar *d = dp;
1056
 
            for (y = 0; y < size; y++) {
1057
 
                gint dx = x - offset;
1058
 
                gint dy = y - offset;
1059
 
                gint hyp = (ABS(dx*dx) + ABS(dy*dy));
1060
 
                if ( hyp >= inner && hyp <= rad)
1061
 
                {
1062
 
                    gdouble rot = atan2( static_cast<gdouble>(dy), static_cast<gdouble>(-dx) );
1063
 
 
1064
 
                    gfloat rgb[3];
1065
 
                    sp_color_hsv_to_rgb_floatv (rgb, (rot + M_PI) / (2.0 * M_PI), 1.0, 1.0);
1066
 
 
1067
 
                    d[0] = SP_COLOR_F_TO_U (rgb[0]);
1068
 
                    d[1] = SP_COLOR_F_TO_U (rgb[1]);
1069
 
                    d[2] = SP_COLOR_F_TO_U (rgb[2]);
1070
 
                }
1071
 
                else
1072
 
                {
1073
 
                    /* Background value */
1074
 
                    d[0] = r;
1075
 
                    d[1] = g;
1076
 
                    d[2] = b;
1077
 
                }
1078
 
 
1079
 
                d += 3 * size;
1080
 
            }
1081
 
            dp += 3;
1082
 
        }
1083
 
    }
1084
 
}
1085
 
 
1086
 
static gboolean sp_color_wheel_focus(GtkWidget        *widget,
1087
 
                                     GtkDirectionType  direction)
1088
 
{
1089
 
    gboolean focusKept = FALSE;
1090
 
    gboolean wasFocused = GTK_WIDGET_HAS_FOCUS(widget);
1091
 
    SPColorWheel* wheel = SP_COLOR_WHEEL(widget);
1092
 
    gboolean goingUp = FALSE;
1093
 
 
1094
 
    switch ( direction )
1095
 
    {
1096
 
    case GTK_DIR_TAB_FORWARD:
1097
 
    case GTK_DIR_UP:
1098
 
    case GTK_DIR_LEFT:
1099
 
        goingUp = TRUE;
1100
 
        break;
1101
 
 
1102
 
    case GTK_DIR_TAB_BACKWARD:
1103
 
    case GTK_DIR_DOWN:
1104
 
    case GTK_DIR_RIGHT:
1105
 
        goingUp = FALSE;
1106
 
        break;
1107
 
    default:
1108
 
        ;
1109
 
    }
1110
 
 
1111
 
    if ( !wasFocused )
1112
 
    {
1113
 
        wheel->_inTriangle = !goingUp;
1114
 
        gtk_widget_grab_focus (widget);
1115
 
        focusKept = TRUE;
1116
 
    }
1117
 
    else if ( (!wheel->_inTriangle) == (!goingUp) )
1118
 
    {
1119
 
        focusKept = FALSE;
1120
 
    }
1121
 
    else
1122
 
    {
1123
 
        wheel->_inTriangle = !wheel->_inTriangle;
1124
 
        gtk_widget_queue_draw( widget );
1125
 
        focusKept = TRUE;
1126
 
    }
1127
 
 
1128
 
    return focusKept;
1129
 
}
1130
 
 
1131
 
static void sp_color_wheel_process_in_triangle( SPColorWheel *wheel, gdouble x, gdouble y )
1132
 
{
1133
 
// njh: dot(rot90(B-C), x) = saturation
1134
 
// njh: dot(B-C, x) = value
1135
 
    Geom::Point delta( x - (((gdouble)(wheel->_triPoints[1].x + wheel->_triPoints[2].x)) / 2.0),
1136
 
                     y - (((gdouble)(wheel->_triPoints[1].y + wheel->_triPoints[2].y)) / 2.0) );
1137
 
 
1138
 
    gdouble rot = (M_PI * 2 * wheel->_hue );
1139
 
 
1140
 
    Geom::Point result = delta * Geom::Rotate(rot);
1141
 
 
1142
 
    gdouble sat = CLAMP( result[Geom::X] / (wheel->_inner * 1.5), 0.0, 1.0 );
1143
 
 
1144
 
    gdouble halfHeight = (wheel->_inner * sin(M_PI/3.0)) * (1.0 - sat);
1145
 
    gdouble value = CLAMP( ((result[Geom::Y]+ halfHeight) / (2.0*halfHeight)), 0.0, 1.0 );
1146
 
 
1147
 
    wheel->_triDirty = TRUE;
1148
 
 
1149
 
    sp_color_wheel_set_sv( wheel, sat, value );
1150
 
}
1151
 
 
1152
 
 
1153
 
/*
1154
 
  Local Variables:
1155
 
  mode:c++
1156
 
  c-file-style:"stroustrup"
1157
 
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
1158
 
  indent-tabs-mode:nil
1159
 
  fill-column:99
1160
 
  End:
1161
 
*/
1162
 
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :