~ubuntu-branches/ubuntu/vivid/gnome-paint/vivid

« back to all changes in this revision

Viewing changes to src/selection.c

  • Committer: Bazaar Package Importer
  • Author(s): Aron Xu
  • Date: 2010-12-13 17:38:49 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20101213173849-kslwesen77to3gfd
Tags: 0.4.0-1
* New upstream release.
  - Draw GtkMenu when clicking items in GtkMenuBar (Closes: #607137)
* debian/control: 
  - Update homepage link.
  - Bump std-ver to 3.9.1.
  + Add DM-Upload-Allowed: yes.
* debian/rules:
  +  LDFLAGS += -Wl,--as-needed
* Update translations:
  + pt by Américo Monteiro <a_monteiro@netcabo.pt> (Closes: #607131)
  + da by Joe Dalton <joedalton2@yahoo.dk> (Closes: #607140)
  + vi by Duy Hùng Trần <nguyentieuhau@gmail.com> (Closes: #607342)
  + cs by Michal Simunek <michal.simunek@gmail.com> (Closes: #607468)
  + de by Chris Leick <c.leick@vollbio.de> (Closes: #607769)
  + fr by Jean-Pierre <ceinestpasuncomptepoubelle@gmail.com> (Closes: #607845)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *            selection.c
 
3
 *
 
4
 *  Sat Jun 19 16:12:19 2010
 
5
 *  Copyright  2010  rogerio
 
6
 *  <rogerioferro@gmail.com>
 
7
 ****************************************************************************/
 
8
 
 
9
/*
 
10
 * This program is free software; you can redistribute it and/or modify
 
11
 * it under the terms of the GNU General Public License as published by
 
12
 * the Free Software Foundation; either version 2 of the License, or
 
13
 * (at your option) any later version.
 
14
 * 
 
15
 * This program is distributed in the hope that it will be useful,
 
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
 * GNU Library General Public License for more details.
 
19
 * 
 
20
 * You should have received a copy of the GNU General Public License
 
21
 * along with this program; if not, write to the Free Software
 
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
 
23
 */
 
24
 
 
25
#include "selection.h"
 
26
#include "cv_drawing.h"
 
27
#include "gp-image.h"
 
28
#include "undo.h"
 
29
 
 
30
typedef enum {
 
31
    SEL_TOP_LEFT,
 
32
    SEL_TOP_MID,
 
33
    SEL_TOP_RIGHT,
 
34
    SEL_MID_RIGHT,
 
35
    SEL_BOTTOM_RIGHT,
 
36
    SEL_BOTTOM_MID,
 
37
    SEL_BOTTOM_LEFT,
 
38
    SEL_MID_LEFT,
 
39
    SEL_CLIPBOX,
 
40
    SEL_NONE
 
41
} GpSelBoxEnum;
 
42
 
 
43
typedef struct {
 
44
    GdkPoint p0;
 
45
    GdkPoint p1;
 
46
} GpSelBox;
 
47
 
 
48
typedef struct {
 
49
    GpSelBoxEnum    action;
 
50
    GdkPoint        p_drag;
 
51
    GdkPoint        sp; /*Start Point*/
 
52
    GdkPoint        ep; /*End Poind*/   
 
53
    GpSelBox        boxes[SEL_NONE];
 
54
    GpImage         *image;
 
55
    gint            active : 1;
 
56
    gint            show_borders : 1;
 
57
    gint            floating : 1;
 
58
    gboolean            transparent;
 
59
    GdkPixbuf           *pb_clipboard;
 
60
} PrivData;
 
61
 
 
62
static gboolean gp_selection_get_bg_color_rgb(guchar *r, guchar *g, guchar *b);
 
63
 
 
64
/* private data */
 
65
static PrivData *m_priv = NULL;
 
66
 
 
67
static void
 
68
create_private_data( void )
 
69
{
 
70
        if (m_priv == NULL)
 
71
        {
 
72
                m_priv = g_slice_new0 (PrivData);
 
73
        m_priv->image = NULL;
 
74
        g_print ("init\n");
 
75
        }
 
76
}
 
77
 
 
78
static void
 
79
destroy_image ( void )
 
80
{
 
81
    if ( m_priv->image != NULL )
 
82
    {
 
83
        g_object_unref ( m_priv->image );
 
84
        m_priv->image = NULL;
 
85
    }
 
86
}
 
87
 
 
88
static void
 
89
destroy_private_data( void )
 
90
{
 
91
    if ( m_priv != NULL )
 
92
    {
 
93
        destroy_image ();
 
94
            g_slice_free (PrivData, m_priv);
 
95
            m_priv = NULL;
 
96
        g_print ("clear\n");
 
97
    }
 
98
}
 
99
 
 
100
static void
 
101
update_clipbox ( void )
 
102
{
 
103
    GdkPoint *sp        = &m_priv->sp;
 
104
    GdkPoint *ep        = &m_priv->ep;
 
105
    GpSelBox *clipbox   = &m_priv->boxes[SEL_CLIPBOX];
 
106
    
 
107
    if ( ep->x > sp->x)
 
108
    {
 
109
        clipbox->p0.x = sp->x;
 
110
        clipbox->p1.x = ep->x;
 
111
    }
 
112
    else
 
113
    {
 
114
        clipbox->p1.x = sp->x;
 
115
        clipbox->p0.x = ep->x;
 
116
    }
 
117
 
 
118
    if ( ep->y > sp->y)
 
119
    {
 
120
        clipbox->p0.y = sp->y;
 
121
        clipbox->p1.y = ep->y;
 
122
    }
 
123
    else
 
124
    {
 
125
        clipbox->p1.y = sp->y;
 
126
        clipbox->p0.y = ep->y;
 
127
    }
 
128
}
 
129
 
 
130
static void 
 
131
set_sel_box ( GpSelBox *box, gint x0, gint y0, gint x1, gint y1 )
 
132
{
 
133
    box->p0.x = x0;
 
134
    box->p0.y = y0;
 
135
    box->p1.x = x1;
 
136
    box->p1.y = y1;
 
137
}
 
138
 
 
139
static void 
 
140
update_borders ( void )
 
141
{
 
142
    
 
143
    if ( m_priv->show_borders )
 
144
    {
 
145
        GdkPoint *sp        = &m_priv->sp;
 
146
        GdkPoint *ep        = &m_priv->ep;
 
147
        GpSelBox *clipbox   = &m_priv->boxes[SEL_CLIPBOX];
 
148
        const gint s = 4;
 
149
        gint xl,yt,xr,yb,xm,ym;
 
150
 
 
151
        sp->x = clipbox->p0.x;
 
152
        sp->y = clipbox->p0.y;
 
153
        ep->x = clipbox->p1.x;
 
154
        ep->y = clipbox->p1.y;
 
155
        update_clipbox ();
 
156
 
 
157
        xl = clipbox->p0.x;
 
158
        yt = clipbox->p0.y;
 
159
        xr = clipbox->p1.x;
 
160
        yb = clipbox->p1.y;
 
161
        xm = (xr + xl)/2;
 
162
        ym = (yb + yt)/2;
 
163
        
 
164
        set_sel_box ( &m_priv->boxes[SEL_TOP_LEFT],
 
165
                       xl,yt,xl+s,yt+s);
 
166
        set_sel_box ( &m_priv->boxes[SEL_TOP_MID],
 
167
                       xm-s/2,yt,xm+s/2,yt+s);
 
168
        set_sel_box ( &m_priv->boxes[SEL_TOP_RIGHT],
 
169
                       xr-s,yt,xr,yt+s);
 
170
        set_sel_box ( &m_priv->boxes[SEL_MID_LEFT],
 
171
                       xl,ym-s/2,xl+s,ym+s/2);
 
172
        set_sel_box ( &m_priv->boxes[SEL_MID_RIGHT],
 
173
                       xr-s,ym-s/2,xr,ym+s/2);
 
174
        set_sel_box ( &m_priv->boxes[SEL_BOTTOM_LEFT],
 
175
                       xl,yb-s,xl+s,yb);
 
176
        set_sel_box ( &m_priv->boxes[SEL_BOTTOM_MID],
 
177
                       xm-s/2,yb-s,xm+s/2,yb);
 
178
        set_sel_box ( &m_priv->boxes[SEL_BOTTOM_RIGHT],
 
179
                       xr-s,yb-s,xr,yb);
 
180
    }
 
181
}
 
182
 
 
183
static gboolean 
 
184
point_in ( GdkPoint *point, GpSelBox *box)
 
185
{
 
186
    if (    point->x >= box->p0.x && 
 
187
            point->x <= box->p1.x && 
 
188
            point->y >= box->p0.y && 
 
189
            point->y <= box->p1.y )
 
190
    {
 
191
        return TRUE;
 
192
    }
 
193
    else
 
194
    {
 
195
        return FALSE;
 
196
    }
 
197
}
 
198
 
 
199
static GpSelBoxEnum
 
200
get_box_in ( GdkPoint *point )
 
201
{
 
202
    GpSelBoxEnum box;
 
203
    for ( box = SEL_TOP_LEFT; box < SEL_NONE; box++ )
 
204
    {
 
205
        if ( point_in ( point, &m_priv->boxes[box] ) )
 
206
            break;
 
207
    }
 
208
    return box;
 
209
}
 
210
 
 
211
 
 
212
void
 
213
gp_selection_init ( void )
 
214
{
 
215
    create_private_data ();
 
216
}
 
217
 
 
218
void
 
219
gp_selection_clear ( void )
 
220
{
 
221
    destroy_private_data ();
 
222
}
 
223
 
 
224
void
 
225
gp_selection_clipbox_set_start_point ( GdkPoint *p )
 
226
{
 
227
    g_return_if_fail ( m_priv != NULL );
 
228
    m_priv->sp.x = p->x;
 
229
    m_priv->sp.y = p->y;
 
230
    update_clipbox ();
 
231
}
 
232
 
 
233
void
 
234
gp_selection_clipbox_set_end_point ( GdkPoint *p )
 
235
{
 
236
    g_return_if_fail ( m_priv != NULL );
 
237
    m_priv->ep.x = p->x;
 
238
    m_priv->ep.y = p->y;
 
239
    update_clipbox ();
 
240
}
 
241
 
 
242
void
 
243
gp_selection_set_active ( gboolean active )
 
244
{
 
245
    g_return_if_fail ( m_priv != NULL );
 
246
    m_priv->active = active;
 
247
}
 
248
 
 
249
void
 
250
gp_selection_set_borders ( gboolean borders )
 
251
{
 
252
    g_return_if_fail ( m_priv != NULL );
 
253
    m_priv->show_borders = borders;
 
254
    update_borders ();
 
255
}
 
256
 
 
257
/* If pixbuf is NULL, a selection is created from the two points
 
258
 * 's' is the top left point of a rectangle and 'e' is the bottom
 
259
 * right. If pixbuf is not NULL a selection is created from the pixbuf
 
260
 * and 's' is the x,y position to place the selection.
 
261
 */
 
262
gboolean gp_selection_create (GdkPoint *s, GdkPoint *e, GdkPixbuf *pixbuf)
 
263
{
 
264
        GdkPoint tmp = {0, 0};
 
265
        gp_canvas *cv;
 
266
        GdkPoint S, E;
 
267
        gint w, h;
 
268
 
 
269
        if((NULL == s) || (NULL == e)){
 
270
                return FALSE;
 
271
        }
 
272
        if(NULL == m_priv){
 
273
                return FALSE;
 
274
        }
 
275
        
 
276
        S = *s ; E = *e ;
 
277
        
 
278
        if(GDK_IS_PIXBUF(pixbuf)){
 
279
                m_priv->pb_clipboard = gdk_pixbuf_copy(pixbuf);
 
280
                w = gdk_pixbuf_get_width(m_priv->pb_clipboard);
 
281
                h = gdk_pixbuf_get_height(m_priv->pb_clipboard);
 
282
                if(ABS(S.x - E.x) != w){
 
283
                        E.x = S.x + w;
 
284
                }
 
285
                if(ABS(S.y - E.y) != h){
 
286
                        E.y = S.y + h;
 
287
                }
 
288
                /* Allow for selection border */
 
289
                E.x-- ; E.y-- ;
 
290
        }
 
291
        
 
292
        gp_selection_set_floating ( TRUE );
 
293
        gp_selection_set_active ( FALSE );
 
294
        gp_selection_clipbox_set_start_point ( &S );
 
295
        gp_selection_clipbox_set_end_point ( &E );
 
296
        gp_selection_set_active ( TRUE );
 
297
 
 
298
        tmp.x = ABS(S.x - E.x);
 
299
        tmp.y = ABS(S.y - E.y);
 
300
 
 
301
        gp_selection_start_action ( &tmp );
 
302
 
 
303
        gp_selection_set_floating ( FALSE );
 
304
 
 
305
        gp_selection_set_borders ( TRUE );
 
306
        cv = cv_get_canvas ();
 
307
    gtk_widget_queue_draw ( cv->widget );
 
308
 
 
309
        return TRUE;
 
310
}
 
311
 
 
312
/* button press ---+----gp_selection_set_active ( FALSE );
 
313
 *                                      `+--gp_selection_set_active ( TRUE );
 
314
 * double click -> gp_selection_set_floating ( FALSE );
 
315
 */
 
316
void
 
317
gp_selection_set_floating ( gboolean floating )
 
318
{
 
319
    g_return_if_fail ( m_priv != NULL );
 
320
    m_priv->floating = floating;
 
321
    if ( m_priv->active )
 
322
    {
 
323
        GpSelBox *clipbox   = &m_priv->boxes[SEL_CLIPBOX];
 
324
        gp_canvas *cv;
 
325
        GdkRectangle rect;
 
326
        cv = cv_get_canvas ();
 
327
        rect.x      = MIN(clipbox->p0.x,clipbox->p1.x);
 
328
        rect.y      = MIN(clipbox->p0.y,clipbox->p1.y);
 
329
        rect.width  = ABS(clipbox->p1.x - clipbox->p0.x)+1;
 
330
        rect.height = ABS(clipbox->p1.y - clipbox->p0.y)+1;
 
331
        if ( m_priv->floating )
 
332
        {
 
333
            printf("gp_selection_set_floating() TRUE\n");
 
334
            if ( m_priv->image != NULL )
 
335
            {
 
336
                gp_image_draw ( m_priv->image,
 
337
                                cv->pixmap,
 
338
                                cv->gc_fg,
 
339
                                rect.x, rect.y,
 
340
                                rect.width, rect.height );            
 
341
                destroy_image ();
 
342
            }
 
343
        }
 
344
        else
 
345
        {
 
346
            printf("gp_selection_set_floating() FALSE\n");
 
347
            destroy_image ();
 
348
            /* Create selection from a pixbuf */
 
349
            if(GDK_IS_PIXBUF(m_priv->pb_clipboard))
 
350
            {
 
351
                GdkPixmap *pm;
 
352
                gint w, h;
 
353
 
 
354
                w = gdk_pixbuf_get_width(m_priv->pb_clipboard);
 
355
                                h = gdk_pixbuf_get_height(m_priv->pb_clipboard);
 
356
                
 
357
                pm = gdk_pixmap_new (cv->widget->window, w, h, -1);
 
358
                gdk_draw_pixbuf (pm, cv->gc_fg, m_priv->pb_clipboard, 0, 0,
 
359
                                                                 0, 0, w, h, GDK_RGB_DITHER_NONE, 0, 0);
 
360
                                
 
361
                                m_priv->image = gp_image_new_from_pixmap ( pm, &rect, TRUE );
 
362
                g_object_unref(pm);
 
363
                g_object_unref(m_priv->pb_clipboard);
 
364
                m_priv->pb_clipboard = NULL;
 
365
            }
 
366
            /* Create selection */
 
367
            else
 
368
            {
 
369
                GdkRectangle undo_area = {0, 0, 0, 0};
 
370
 
 
371
                /* Save all pixmap so redraw where selection was copied from
 
372
                 * and where sel will be pasted - which we don't know where
 
373
                 * that will be. */
 
374
                gdk_drawable_get_size (cv->pixmap, &undo_area.width, &undo_area.height);
 
375
                undo_add ( &undo_area, NULL, NULL, TOOL_RECT_SELECT);
 
376
 
 
377
                m_priv->image = gp_image_new_from_pixmap ( cv->pixmap, &rect, TRUE );
 
378
                
 
379
                printf("   x: %d, y: %d, w: %d, h: %d\n", rect.x, rect.y,
 
380
                                                                                                  rect.width, rect.height);
 
381
 
 
382
                gdk_draw_rectangle ( cv->pixmap, cv->gc_bg, TRUE, 
 
383
                                     rect.x, rect.y, rect.width, rect.height ); 
 
384
            }       
 
385
                /* Add transparancy if necessary */
 
386
                if(cv->transparent)
 
387
                {
 
388
                guchar r, g, b;
 
389
 
 
390
                m_priv->transparent = cv->transparent;
 
391
                gp_selection_get_bg_color_rgb(&r, &g, &b);
 
392
                gp_image_make_color_transparent( m_priv->image, r, g, b, 0);
 
393
                
 
394
            }
 
395
        }
 
396
    }
 
397
}
 
398
 
 
399
GdkCursorType
 
400
gp_selection_get_cursor ( GdkPoint *p )
 
401
{
 
402
    g_return_val_if_fail ( m_priv != NULL, GDK_BLANK_CURSOR);
 
403
    switch ( get_box_in ( p ) )
 
404
    {
 
405
        case SEL_TOP_LEFT:
 
406
            return GDK_TOP_LEFT_CORNER;
 
407
        case SEL_TOP_MID:
 
408
            return GDK_TOP_SIDE;
 
409
        case SEL_TOP_RIGHT:
 
410
            return GDK_TOP_RIGHT_CORNER;
 
411
        case SEL_MID_LEFT:
 
412
            return GDK_LEFT_SIDE;
 
413
        case SEL_MID_RIGHT:
 
414
            return GDK_RIGHT_SIDE;
 
415
        case SEL_BOTTOM_LEFT:
 
416
            return GDK_BOTTOM_LEFT_CORNER;
 
417
        case SEL_BOTTOM_MID:
 
418
            return GDK_BOTTOM_SIDE;
 
419
        case SEL_BOTTOM_RIGHT:
 
420
            return GDK_BOTTOM_RIGHT_CORNER;
 
421
        case SEL_CLIPBOX:
 
422
            return GDK_FLEUR;
 
423
        default:
 
424
            return GDK_BLANK_CURSOR;
 
425
    }
 
426
}
 
427
 
 
428
gboolean
 
429
gp_selection_start_action ( GdkPoint *p )
 
430
{
 
431
    g_return_val_if_fail ( m_priv != NULL, FALSE );
 
432
    if ( m_priv->active )
 
433
    {
 
434
        m_priv->action = get_box_in ( p );
 
435
        m_priv->p_drag.x = p->x;
 
436
        m_priv->p_drag.y = p->y;
 
437
 
 
438
        g_print ("action:%i\n", m_priv->action);
 
439
 
 
440
        return (m_priv->action != SEL_NONE);
 
441
    }
 
442
    return FALSE;
 
443
        
 
444
}
 
445
 
 
446
void
 
447
gp_selection_do_action ( GdkPoint *p )
 
448
{
 
449
    g_return_if_fail ( m_priv != NULL );
 
450
 
 
451
    GpSelBox *clipbox   = &m_priv->boxes[SEL_CLIPBOX];
 
452
    gint dx = p->x - m_priv->p_drag.x;
 
453
    gint dy = p->y - m_priv->p_drag.y;
 
454
 
 
455
    switch ( m_priv->action )
 
456
    {
 
457
        case SEL_TOP_LEFT:
 
458
            clipbox->p0.y  += dy;
 
459
        case SEL_MID_LEFT:
 
460
            clipbox->p0.x  += dx;
 
461
            break;            
 
462
        case SEL_TOP_RIGHT:
 
463
            clipbox->p1.x  += dx;
 
464
        case SEL_TOP_MID:
 
465
            clipbox->p0.y  += dy;
 
466
            break;            
 
467
        case SEL_BOTTOM_LEFT:
 
468
            clipbox->p0.x  += dx;
 
469
        case SEL_BOTTOM_MID:
 
470
            clipbox->p1.y  += dy;
 
471
            break;
 
472
        case SEL_CLIPBOX:
 
473
            clipbox->p0.x  += dx;
 
474
            clipbox->p0.y  += dy;
 
475
        case SEL_BOTTOM_RIGHT:
 
476
            clipbox->p1.y  += dy;
 
477
        case SEL_MID_RIGHT:
 
478
            clipbox->p1.x  += dx;
 
479
            break;   
 
480
    }    
 
481
    m_priv->p_drag.x += dx;
 
482
    m_priv->p_drag.y += dy;
 
483
}
 
484
 
 
485
 
 
486
static void 
 
487
draw_sel_box ( GdkDrawable *drawing, GdkGC *gc, GpSelBox *box )
 
488
{
 
489
    gint x,y,w,h;
 
490
    x = box->p0.x;
 
491
    y = box->p0.y;
 
492
    w = (box->p1.x - x + 1);
 
493
    h = (box->p1.y - y + 1);
 
494
    gdk_draw_rectangle ( drawing, gc, TRUE, 
 
495
                         x, y, w, h);
 
496
}
 
497
 
 
498
static void
 
499
draw_top_line ( GdkDrawable *drawing, GdkGC *gc )
 
500
{
 
501
    GpSelBox *tlbox = &m_priv->boxes[SEL_TOP_LEFT];
 
502
    GpSelBox *tmbox = &m_priv->boxes[SEL_TOP_MID];
 
503
    GpSelBox *trbox = &m_priv->boxes[SEL_TOP_RIGHT];
 
504
    gdk_draw_line ( drawing, gc, tlbox->p1.x+1, tlbox->p0.y, 
 
505
                                 tmbox->p0.x-1, tmbox->p0.y );
 
506
    gdk_draw_line ( drawing, gc, tmbox->p1.x+1, tmbox->p0.y,
 
507
                                 trbox->p0.x-1, trbox->p0.y );
 
508
}
 
509
 
 
510
static void
 
511
draw_right_line ( GdkDrawable *drawing, GdkGC *gc )
 
512
{
 
513
    GpSelBox *trbox = &m_priv->boxes[SEL_TOP_RIGHT];
 
514
    GpSelBox *mrbox = &m_priv->boxes[SEL_MID_RIGHT];
 
515
    GpSelBox *brbox = &m_priv->boxes[SEL_BOTTOM_RIGHT];
 
516
    gdk_draw_line ( drawing, gc, trbox->p1.x, trbox->p1.y+1, 
 
517
                                 mrbox->p1.x, mrbox->p0.y-1);
 
518
    gdk_draw_line ( drawing, gc, mrbox->p1.x, mrbox->p1.y+1,
 
519
                                 brbox->p1.x, brbox->p0.y-1 );
 
520
}
 
521
 
 
522
 
 
523
static void
 
524
draw_left_line ( GdkDrawable *drawing, GdkGC *gc )
 
525
{
 
526
    GpSelBox *tlbox = &m_priv->boxes[SEL_TOP_LEFT];
 
527
    GpSelBox *mlbox = &m_priv->boxes[SEL_MID_LEFT];
 
528
    GpSelBox *blbox = &m_priv->boxes[SEL_BOTTOM_LEFT];
 
529
    gdk_draw_line ( drawing, gc, tlbox->p0.x, tlbox->p1.y+1, 
 
530
                                 mlbox->p0.x, mlbox->p0.y-1 );
 
531
    gdk_draw_line ( drawing, gc, mlbox->p0.x, mlbox->p1.y+1,
 
532
                                 blbox->p0.x, blbox->p0.y-1 );
 
533
}
 
534
 
 
535
static void
 
536
draw_bottom_line ( GdkDrawable *drawing, GdkGC *gc )
 
537
{
 
538
    GpSelBox *brbox = &m_priv->boxes[SEL_BOTTOM_RIGHT];
 
539
    GpSelBox *bmbox = &m_priv->boxes[SEL_BOTTOM_MID];
 
540
    GpSelBox *blbox = &m_priv->boxes[SEL_BOTTOM_LEFT];
 
541
    gdk_draw_line ( drawing, gc, brbox->p0.x-1, brbox->p1.y, 
 
542
                                 bmbox->p1.x+1, bmbox->p1.y );
 
543
    gdk_draw_line ( drawing, gc, bmbox->p0.x-1, bmbox->p1.y,
 
544
                                 blbox->p1.x+1, blbox->p1.y );
 
545
}
 
546
 
 
547
static void
 
548
draw_borders ( GdkDrawable *drawing, GdkGC *gc )
 
549
{
 
550
    GpSelBoxEnum box;
 
551
    for ( box = SEL_TOP_LEFT; box < SEL_CLIPBOX; box++ )
 
552
    {
 
553
        draw_sel_box ( drawing, gc, &m_priv->boxes[box] );
 
554
    }
 
555
    draw_top_line       ( drawing, gc );
 
556
    draw_right_line     ( drawing, gc );
 
557
    draw_bottom_line    ( drawing, gc );
 
558
    draw_left_line      ( drawing, gc );
 
559
}
 
560
 
 
561
 
 
562
void
 
563
gp_selection_draw ( GdkDrawable *gdkd )
 
564
{
 
565
    g_return_if_fail ( m_priv != NULL );
 
566
    if ( m_priv->active )
 
567
    {
 
568
        GpSelBox *clipbox   = &m_priv->boxes[SEL_CLIPBOX];
 
569
        gint x,y,w,h;
 
570
        gp_canvas *cv;
 
571
        gint8 dash_list[]       =       { 3, 3 };
 
572
        GdkGC *gc;
 
573
 
 
574
        cv = cv_get_canvas ();
 
575
        gc      =       gdk_gc_new ( cv->widget->window );
 
576
        gdk_gc_set_function ( gc, GDK_INVERT );
 
577
        gdk_gc_set_dashes ( gc, 0, dash_list, 2 );
 
578
        gdk_gc_set_line_attributes ( gc, 1, GDK_LINE_ON_OFF_DASH,
 
579
                                     GDK_CAP_NOT_LAST, GDK_JOIN_ROUND );
 
580
 
 
581
        x = MIN(clipbox->p0.x,clipbox->p1.x);
 
582
        y = MIN(clipbox->p0.y,clipbox->p1.y);
 
583
        w = ABS(clipbox->p1.x - clipbox->p0.x)+1;
 
584
        h = ABS(clipbox->p1.y - clipbox->p0.y)+1;
 
585
 
 
586
 
 
587
        if ( m_priv->floating )
 
588
        {
 
589
            cairo_t     *cr;
 
590
            cr  =   gdk_cairo_create ( cv->drawing );
 
591
            cairo_set_line_width (cr, 1.0);
 
592
            cairo_set_source_rgba (cr, 0.7, 0.9, 1.0, 0.3);
 
593
            cairo_rectangle ( cr, x, y, w, h); 
 
594
            cairo_fill (cr);
 
595
            cairo_destroy (cr);
 
596
        }
 
597
        else
 
598
        {
 
599
            /* Make transparent/opaque */
 
600
            if(cv->transparent != m_priv->transparent)
 
601
            {
 
602
                guchar r, g, b, a = 0xFF;
 
603
 
 
604
                m_priv->transparent = cv->transparent;
 
605
                gp_selection_get_bg_color_rgb ( &r, &g, &b );
 
606
                if(cv->transparent)
 
607
                {
 
608
                        a = 0;
 
609
                }
 
610
                gp_image_make_color_transparent ( m_priv->image, r, g, b, a );
 
611
                
 
612
            }
 
613
            
 
614
            /* Had to add this here because the selection
 
615
             * was being erased when changing tools. Don't
 
616
             * know if this was by design or not, but just
 
617
             * doesn't seem right. This is just temporary
 
618
             * until we find out.
 
619
             */
 
620
            if(GDK_IS_DRAWABLE(gdkd)){
 
621
                gp_image_draw ( m_priv->image,
 
622
                            gdkd,
 
623
                            cv->gc_fg,
 
624
                            x,y,w,h );
 
625
            }
 
626
            else{
 
627
                gp_image_draw ( m_priv->image,
 
628
                            cv->drawing,
 
629
                            cv->gc_fg,
 
630
                            x,y,w,h );
 
631
                }
 
632
        }
 
633
 
 
634
 
 
635
        if ( m_priv->show_borders )
 
636
        {
 
637
            draw_borders ( cv->drawing, gc );
 
638
        }
 
639
        else
 
640
        {
 
641
            gdk_draw_rectangle ( cv->drawing, gc, FALSE, 
 
642
                                 x, y, w-1, h-1 );
 
643
        }
 
644
 
 
645
        
 
646
        g_object_unref ( gc );
 
647
        
 
648
    }    
 
649
}
 
650
 
 
651
/* Get background color's rgb values */
 
652
static gboolean gp_selection_get_bg_color_rgb(guchar *r, guchar *g, guchar *b)
 
653
{
 
654
        gp_canvas *cv;
 
655
        
 
656
        cv = cv_get_canvas ();
 
657
        if((cv) && (r) && (g) && (b))
 
658
        {
 
659
                GdkColor color;
 
660
                GdkGCValues values;
 
661
                GdkColormap* colormap = gdk_colormap_get_system();
 
662
                
 
663
                gdk_gc_get_values (cv->gc_bg, &values);
 
664
                gdk_colormap_query_color(colormap, values.foreground.pixel, &color);
 
665
 
 
666
                *r = color.red >>= 8;
 
667
                *g = color.green >>= 8;
 
668
                *b = color.blue >>= 8;
 
669
                
 
670
                return TRUE;
 
671
        }
 
672
        
 
673
        return FALSE;
 
674
}
 
675
 
 
676
/* See if there is a selection image */
 
677
gboolean gp_selection_query(void)
 
678
{
 
679
        if(m_priv){
 
680
                if(m_priv->image){
 
681
                        return TRUE;
 
682
                }
 
683
        }
 
684
        
 
685
        return FALSE;
 
686
}
 
687
 
 
688
void gp_selection_invert(void)
 
689
{
 
690
        if(m_priv){
 
691
                if(m_priv->image){
 
692
                        gp_image_invert_colors ( m_priv->image);
 
693
                }
 
694
        }
 
695
}
 
696
 
 
697
void gp_selection_flip(gboolean flip)
 
698
{
 
699
        if(m_priv){
 
700
                if(m_priv->image){
 
701
                        gp_image_flip ( m_priv->image, flip );
 
702
                }
 
703
        }
 
704
}
 
705
 
 
706
void gp_selection_rotate(GdkPixbufRotation angle)
 
707
{
 
708
        if(m_priv){
 
709
                if(m_priv->image){
 
710
                        GdkPixbuf *pixbuf;
 
711
                        GdkPoint s, e;
 
712
                        GpSelBox *clipbox;
 
713
                        GpImage *new_image;
 
714
                        gp_canvas *cv = cv_get_canvas ();
 
715
 
 
716
                        gp_image_rotate ( m_priv->image, angle );
 
717
                        pixbuf = gp_image_get_pixbuf(m_priv->image);
 
718
 
 
719
                        clipbox = &m_priv->boxes[SEL_CLIPBOX];
 
720
                        s.x = MIN(clipbox->p0.x,clipbox->p1.x);
 
721
                s.y = MIN(clipbox->p0.y,clipbox->p1.y);
 
722
                e.x = gdk_pixbuf_get_width(pixbuf);
 
723
                e.y = gdk_pixbuf_get_height(pixbuf);
 
724
                
 
725
                clipbox->p0.x = s.x;
 
726
                clipbox->p0.y = s.y;
 
727
                /* -1 to allow for border width */
 
728
                clipbox->p1.x = clipbox->p0.x + e.x - 1;
 
729
                clipbox->p1.y = clipbox->p0.y + e.y - 1;
 
730
 
 
731
                update_borders ( );
 
732
                
 
733
                g_object_unref ( m_priv->image );
 
734
                        m_priv->image = gp_image_new_from_pixbuf ( pixbuf, TRUE );
 
735
 
 
736
                        g_object_unref(pixbuf);
 
737
                }
 
738
        }
 
739
}
 
740
 
 
741
/* Return a copy of selection's image pixbuf */
 
742
GdkPixbuf *gp_selection_get_pixbuf(void)
 
743
{
 
744
        if(m_priv){
 
745
                if(m_priv->image){
 
746
                        return gp_image_get_pixbuf(m_priv->image);
 
747
                }
 
748
        }
 
749
        
 
750
        return NULL;
 
751
}
 
752
 
 
753
/* Clear selection. Does not clear
 
754
 * as in destroying m_priv.
 
755
 * draw == TRUE to draw image
 
756
 */
 
757
void gp_selection_draw_and_clear (gboolean draw)
 
758
{
 
759
        GdkPoint pt = {0, 0};
 
760
        gp_canvas *cv = cv_get_canvas ();
 
761
 
 
762
        g_return_if_fail( gp_selection_query() );
 
763
        
 
764
        pt.x = m_priv->sp.x - 1;
 
765
        pt.y = pt.x;
 
766
        
 
767
        if(!draw){ g_object_unref (m_priv->image) ; m_priv->image = NULL ; }
 
768
 
 
769
        gp_selection_set_floating ( TRUE );
 
770
        gp_selection_set_active ( FALSE );
 
771
        gp_selection_clipbox_set_start_point ( &pt );
 
772
        gp_selection_clipbox_set_end_point ( &pt );
 
773
        gp_selection_set_active ( TRUE );
 
774
 
 
775
        gp_selection_set_borders ( FALSE );
 
776
        gtk_widget_queue_draw ( cv->widget );
 
777
}