~ubuntu-branches/ubuntu/utopic/ardour3/utopic

« back to all changes in this revision

Viewing changes to libs/clearlooks-newer/cairo-support.c

  • Committer: Package Import Robot
  • Author(s): Felipe Sateler
  • Date: 2013-09-21 19:05:02 UTC
  • Revision ID: package-import@ubuntu.com-20130921190502-8gsftrku6jnzhd7v
Tags: upstream-3.4~dfsg
ImportĀ upstreamĀ versionĀ 3.4~dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <math.h>
 
2
#include "general-support.h"
 
3
#include "cairo-support.h"
 
4
 
 
5
/***********************************************
 
6
 * ge_hsb_from_color -
 
7
 *  
 
8
 *   Get HSB values from RGB values.
 
9
 *
 
10
 *   Modified from Smooth but originated in GTK+
 
11
 ***********************************************/
 
12
void
 
13
ge_hsb_from_color (const CairoColor *color, 
 
14
                        gdouble *hue, 
 
15
                        gdouble *saturation,
 
16
                        gdouble *brightness) 
 
17
{
 
18
        gdouble min, max, delta;
 
19
        gdouble red, green, blue;
 
20
 
 
21
        red = color->r;
 
22
        green = color->g;
 
23
        blue = color->b;
 
24
  
 
25
        if (red > green)
 
26
        {
 
27
                max = MAX(red, blue);
 
28
                min = MIN(green, blue);
 
29
        }
 
30
        else
 
31
        {
 
32
                max = MAX(green, blue);
 
33
                min = MIN(red, blue);
 
34
        }
 
35
  
 
36
        *brightness = (max + min) / 2;
 
37
        
 
38
        if (fabs(max - min) < 0.0001)
 
39
        {
 
40
                *hue = 0;
 
41
                *saturation = 0;
 
42
        }       
 
43
        else
 
44
        {
 
45
                if (*brightness <= 0.5)
 
46
                        *saturation = (max - min) / (max + min);
 
47
                else
 
48
                        *saturation = (max - min) / (2 - max - min);
 
49
       
 
50
                delta = max -min;
 
51
 
 
52
                if (red == max)
 
53
                        *hue = (green - blue) / delta;
 
54
                else if (green == max)
 
55
                        *hue = 2 + (blue - red) / delta;
 
56
                else if (blue == max)
 
57
                        *hue = 4 + (red - green) / delta;
 
58
 
 
59
                *hue *= 60;
 
60
                if (*hue < 0.0)
 
61
                        *hue += 360;
 
62
        }
 
63
}
 
64
 
 
65
/***********************************************
 
66
 * ge_color_from_hsb -
 
67
 *  
 
68
 *   Get RGB values from HSB values.
 
69
 *
 
70
 *   Modified from Smooth but originated in GTK+
 
71
 ***********************************************/
 
72
#define MODULA(number, divisor) (((gint)number % divisor) + (number - (gint)number))
 
73
void
 
74
ge_color_from_hsb (gdouble hue, 
 
75
                        gdouble saturation,
 
76
                        gdouble brightness, 
 
77
                        CairoColor *color)
 
78
{
 
79
        gint i;
 
80
        gdouble hue_shift[3], color_shift[3];
 
81
        gdouble m1, m2, m3;
 
82
 
 
83
        if (!color) return;
 
84
          
 
85
        if (brightness <= 0.5)
 
86
                m2 = brightness * (1 + saturation);
 
87
        else
 
88
                m2 = brightness + saturation - brightness * saturation;
 
89
 
 
90
        m1 = 2 * brightness - m2;
 
91
 
 
92
        hue_shift[0] = hue + 120;
 
93
        hue_shift[1] = hue;
 
94
        hue_shift[2] = hue - 120;
 
95
 
 
96
        color_shift[0] = color_shift[1] = color_shift[2] = brightness;  
 
97
 
 
98
        i = (saturation == 0)?3:0;
 
99
 
 
100
        for (; i < 3; i++)
 
101
        {
 
102
                m3 = hue_shift[i];
 
103
 
 
104
                if (m3 > 360)
 
105
                        m3 = MODULA(m3, 360);
 
106
                else if (m3 < 0)
 
107
                        m3 = 360 - MODULA(ABS(m3), 360);
 
108
 
 
109
                if (m3 < 60)
 
110
                        color_shift[i] = m1 + (m2 - m1) * m3 / 60;
 
111
                else if (m3 < 180)
 
112
                        color_shift[i] = m2;
 
113
                else if (m3 < 240)
 
114
                        color_shift[i] = m1 + (m2 - m1) * (240 - m3) / 60;
 
115
                else
 
116
                        color_shift[i] = m1;
 
117
        }       
 
118
 
 
119
        color->r = color_shift[0];
 
120
        color->g = color_shift[1];
 
121
        color->b = color_shift[2];      
 
122
        color->a = 1.0; 
 
123
}
 
124
 
 
125
void
 
126
ge_gdk_color_to_cairo (const GdkColor *c, CairoColor *cc)
 
127
{
 
128
        gdouble r, g, b;
 
129
 
 
130
        g_return_if_fail (c && cc);
 
131
 
 
132
        r = c->red / 65535.0;
 
133
        g = c->green / 65535.0;
 
134
        b = c->blue / 65535.0;
 
135
 
 
136
        cc->r = r;
 
137
        cc->g = g;
 
138
        cc->b = b;
 
139
        cc->a = 1.0;
 
140
}
 
141
 
 
142
void
 
143
ge_cairo_color_to_gtk (const CairoColor *cc, GdkColor *c)
 
144
{
 
145
        gdouble r, g, b;
 
146
 
 
147
        g_return_if_fail (c && cc);
 
148
 
 
149
        r = cc->r * 65535.0;
 
150
        g = cc->g * 65535.0;
 
151
        b = cc->b * 65535.0;
 
152
 
 
153
        c->red = r;
 
154
        c->green = g;
 
155
        c->blue = b;
 
156
}
 
157
 
 
158
void 
 
159
ge_gtk_style_to_cairo_color_cube (GtkStyle * style, CairoColorCube *cube)
 
160
{
 
161
        int i;
 
162
 
 
163
        g_return_if_fail (style && cube);
 
164
 
 
165
        for (i = 0; i < 5; i++)
 
166
        { 
 
167
                ge_gdk_color_to_cairo (&style->bg[i], &cube->bg[i]);
 
168
                ge_gdk_color_to_cairo (&style->fg[i], &cube->fg[i]);
 
169
 
 
170
                ge_gdk_color_to_cairo (&style->dark[i], &cube->dark[i]);
 
171
                ge_gdk_color_to_cairo (&style->light[i], &cube->light[i]);
 
172
                ge_gdk_color_to_cairo (&style->mid[i], &cube->mid[i]);
 
173
 
 
174
                ge_gdk_color_to_cairo (&style->base[i], &cube->base[i]);
 
175
                ge_gdk_color_to_cairo (&style->text[i], &cube->text[i]);
 
176
                ge_gdk_color_to_cairo (&style->text_aa[i], &cube->text_aa[i]);
 
177
        }
 
178
 
 
179
        cube->black.r = cube->black.g = cube->black.b = 0;
 
180
        cube->black.a = 1;
 
181
 
 
182
        cube->white.r = cube->white.g = cube->white.b = 1;
 
183
        cube->white.a = 1;
 
184
}
 
185
 
 
186
void
 
187
ge_shade_color(const CairoColor *base, gdouble shade_ratio, CairoColor *composite)
 
188
{
 
189
        gdouble hue = 0;
 
190
        gdouble saturation = 0;
 
191
        gdouble brightness = 0;
 
192
 
 
193
        g_return_if_fail (base && composite);
 
194
 
 
195
        ge_hsb_from_color (base, &hue, &saturation, &brightness);
 
196
 
 
197
        brightness = MIN(brightness*shade_ratio, 1.0);
 
198
        brightness = MAX(brightness, 0.0);
 
199
  
 
200
        saturation = MIN(saturation*shade_ratio, 1.0);
 
201
        saturation = MAX(saturation, 0.0);
 
202
  
 
203
        ge_color_from_hsb (hue, saturation, brightness, composite);
 
204
        composite->a = base->a; 
 
205
}
 
206
 
 
207
void
 
208
ge_saturate_color (const CairoColor *base, gdouble saturate_level, CairoColor *composite)
 
209
{
 
210
        gdouble hue = 0;
 
211
        gdouble saturation = 0;
 
212
        gdouble brightness = 0;
 
213
 
 
214
        g_return_if_fail (base && composite);
 
215
 
 
216
        ge_hsb_from_color (base, &hue, &saturation, &brightness);
 
217
 
 
218
        saturation = MIN(saturation*saturate_level, 1.0);
 
219
        saturation = MAX(saturation, 0.0);
 
220
 
 
221
        ge_color_from_hsb (hue, saturation, brightness, composite);
 
222
        composite->a = base->a; 
 
223
}
 
224
 
 
225
void
 
226
ge_mix_color (const CairoColor *color1, const CairoColor *color2, 
 
227
              gdouble mix_factor, CairoColor *composite)
 
228
{
 
229
        g_return_if_fail (color1 && color2 && composite);
 
230
 
 
231
        composite->r = color1->r * (1-mix_factor) + color2->r * mix_factor;
 
232
        composite->g = color1->g * (1-mix_factor) + color2->g * mix_factor;
 
233
        composite->b = color1->b * (1-mix_factor) + color2->b * mix_factor;
 
234
        composite->a = 1.0;
 
235
}
 
236
 
 
237
cairo_t * 
 
238
ge_gdk_drawable_to_cairo (GdkDrawable  *window, GdkRectangle *area)
 
239
{
 
240
        cairo_t *cr;
 
241
 
 
242
        g_return_val_if_fail (window != NULL, NULL);
 
243
 
 
244
        cr = (cairo_t*) gdk_cairo_create (window);
 
245
        cairo_set_line_width (cr, 1.0);
 
246
        cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
 
247
        cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
 
248
 
 
249
        if (area) 
 
250
        {
 
251
                cairo_rectangle (cr, area->x, area->y, area->width, area->height);
 
252
                cairo_clip_preserve (cr);
 
253
                cairo_new_path (cr);
 
254
        }
 
255
 
 
256
        return cr;
 
257
}
 
258
 
 
259
void 
 
260
ge_cairo_set_color (cairo_t *cr, const CairoColor *color)
 
261
{
 
262
        g_return_if_fail (cr && color);
 
263
 
 
264
        cairo_set_source_rgba (cr, color->r, color->g, color->b, color->a);     
 
265
}
 
266
 
 
267
void
 
268
ge_cairo_set_gdk_color_with_alpha (cairo_t *cr, const GdkColor *color, gdouble alpha)
 
269
{
 
270
        g_return_if_fail (cr && color);
 
271
 
 
272
        cairo_set_source_rgba (cr, color->red / 65535.0,
 
273
                                   color->green / 65535.0,
 
274
                                   color->blue / 65535.0,
 
275
                                   alpha);
 
276
}
 
277
 
 
278
void 
 
279
ge_cairo_pattern_add_color_stop_color (cairo_pattern_t *pattern, 
 
280
                                                gfloat offset, 
 
281
                                                const CairoColor *color)
 
282
{
 
283
        g_return_if_fail (pattern && color);
 
284
 
 
285
        cairo_pattern_add_color_stop_rgba (pattern, offset, color->r, color->g, color->b, color->a);    
 
286
}
 
287
 
 
288
void
 
289
ge_cairo_pattern_add_color_stop_shade(cairo_pattern_t *pattern, 
 
290
                                                gdouble offset, 
 
291
                                                const CairoColor *color, 
 
292
                                                gdouble shade)
 
293
{
 
294
        CairoColor shaded;
 
295
 
 
296
        g_return_if_fail (pattern && color && (shade >= 0) && (shade <= 3));
 
297
 
 
298
        shaded = *color;
 
299
 
 
300
        if (shade != 1)
 
301
        {
 
302
                ge_shade_color(color, shade, &shaded);
 
303
        }
 
304
 
 
305
        ge_cairo_pattern_add_color_stop_color(pattern, offset, &shaded);        
 
306
}
 
307
 
 
308
/* This function will draw a rounded corner at position x,y. If the radius
 
309
 * is very small (or negative) it will instead just do a line_to.
 
310
 * ge_cairo_rounded_corner assumes clockwise drawing. */
 
311
void
 
312
ge_cairo_rounded_corner (cairo_t      *cr,
 
313
                         double        x,
 
314
                         double        y,
 
315
                         double        radius,
 
316
                         CairoCorners  corner)
 
317
{
 
318
        if (radius < 0.0001)
 
319
        {
 
320
                cairo_line_to (cr, x, y);
 
321
        }
 
322
        else
 
323
        {
 
324
                switch (corner) {
 
325
                case CR_CORNER_NONE:
 
326
                        cairo_line_to (cr, x, y);
 
327
                        break;
 
328
                case CR_CORNER_TOPLEFT:
 
329
                        cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI * 3/2);
 
330
                        break;
 
331
                case CR_CORNER_TOPRIGHT:
 
332
                        cairo_arc (cr, x - radius, y + radius, radius, G_PI * 3/2, G_PI * 2);
 
333
                        break;
 
334
                case CR_CORNER_BOTTOMRIGHT:
 
335
                        cairo_arc (cr, x - radius, y - radius, radius, 0, G_PI * 1/2);
 
336
                        break;
 
337
                case CR_CORNER_BOTTOMLEFT:
 
338
                        cairo_arc (cr, x + radius, y - radius, radius, G_PI * 1/2, G_PI);
 
339
                        break;
 
340
 
 
341
                default:
 
342
                        /* A bitfield and not a sane value ... */
 
343
                        g_assert_not_reached ();
 
344
                        cairo_line_to (cr, x, y);
 
345
                        return;
 
346
                }
 
347
        }
 
348
}
 
349
 
 
350
void
 
351
ge_cairo_rounded_rectangle (cairo_t *cr,
 
352
                                 double x, double y, double w, double h,
 
353
                                 double radius, CairoCorners corners)
 
354
{
 
355
        g_return_if_fail (cr != NULL);
 
356
 
 
357
        if (radius < 0.0001 || corners == CR_CORNER_NONE)
 
358
        {
 
359
                cairo_rectangle (cr, x, y, w, h);
 
360
                return;
 
361
        }
 
362
#ifdef DEVELOPMENT
 
363
        if ((corners == CR_CORNER_ALL) && (radius > w / 2.0 || radius > h / 2.0))
 
364
                g_warning ("Radius is too large for width/height in ge_rounded_rectangle.\n");
 
365
        else if (radius > w || radius > h) /* This isn't perfect. Assumes that only one corner is set. */
 
366
                g_warning ("Radius is too large for width/height in ge_rounded_rectangle.\n");
 
367
#endif
 
368
 
 
369
        if (corners & CR_CORNER_TOPLEFT)
 
370
                cairo_move_to (cr, x+radius, y);
 
371
        else
 
372
                cairo_move_to (cr, x, y);
 
373
        
 
374
        if (corners & CR_CORNER_TOPRIGHT)
 
375
                cairo_arc (cr, x+w-radius, y+radius, radius, G_PI * 1.5, G_PI * 2);
 
376
        else
 
377
                cairo_line_to (cr, x+w, y);
 
378
        
 
379
        if (corners & CR_CORNER_BOTTOMRIGHT)
 
380
                cairo_arc (cr, x+w-radius, y+h-radius, radius, 0, G_PI * 0.5);
 
381
        else
 
382
                cairo_line_to (cr, x+w, y+h);
 
383
        
 
384
        if (corners & CR_CORNER_BOTTOMLEFT)
 
385
                cairo_arc (cr, x+radius,   y+h-radius, radius, G_PI * 0.5, G_PI);
 
386
        else
 
387
                cairo_line_to (cr, x, y+h);
 
388
        
 
389
        if (corners & CR_CORNER_TOPLEFT)
 
390
                cairo_arc (cr, x+radius,   y+radius,   radius, G_PI, G_PI * 1.5);
 
391
        else
 
392
                cairo_line_to (cr, x, y);
 
393
}
 
394
 
 
395
 
 
396
/* ge_cairo_stroke_rectangle.
 
397
 *
 
398
 *  A simple function to stroke the rectangle { x, y, w, h}.
 
399
 *  (This function only exists because of a cairo performance bug that
 
400
 *    has been fixed and it may be a good idea to get rid of it again.)
 
401
 */
 
402
void
 
403
ge_cairo_stroke_rectangle (cairo_t *cr, double x, double y, double w, double h)
 
404
{
 
405
        cairo_rectangle (cr, x, y, w, h);
 
406
        cairo_stroke (cr);
 
407
}
 
408
 
 
409
/***********************************************
 
410
 * ge_cairo_simple_border -
 
411
 *  
 
412
 *   A simple routine to draw thin squared
 
413
 *   borders with a topleft and bottomright color.
 
414
 *    
 
415
 *   It originated in Smooth-Engine.
 
416
 ***********************************************/
 
417
void
 
418
ge_cairo_simple_border (cairo_t *cr,
 
419
                                const CairoColor * tl, const CairoColor * br,
 
420
                                gint x, gint y, gint width, gint height, 
 
421
                                gboolean topleft_overlap)
 
422
{
 
423
        gboolean solid_color;
 
424
 
 
425
        g_return_if_fail (cr != NULL);
 
426
        g_return_if_fail (tl != NULL);
 
427
        g_return_if_fail (br != NULL);
 
428
        
 
429
 
 
430
        solid_color = (tl == br) || ((tl->r == br->r) && (tl->g == br->g) && (tl->b == br->b) && (tl->a == br->a));
 
431
 
 
432
        topleft_overlap &= !solid_color;
 
433
 
 
434
        cairo_save(cr);
 
435
 
 
436
        cairo_set_line_width (cr, 1);
 
437
 
 
438
        if (topleft_overlap)
 
439
        {
 
440
                ge_cairo_set_color(cr, br);     
 
441
 
 
442
                cairo_move_to(cr, x + 0.5, y + height - 0.5);
 
443
                cairo_line_to(cr, x + width - 0.5, y + height - 0.5);
 
444
                cairo_line_to(cr, x + width - 0.5, y + 0.5);
 
445
                
 
446
                cairo_stroke (cr);
 
447
        }
 
448
 
 
449
        ge_cairo_set_color(cr, tl);     
 
450
 
 
451
        cairo_move_to(cr, x + 0.5, y + height - 0.5);
 
452
        cairo_line_to(cr, x + 0.5, y + 0.5);
 
453
        cairo_line_to(cr, x + width - 0.5, y + 0.5);
 
454
 
 
455
        if (!topleft_overlap)
 
456
        {
 
457
                if (!solid_color)
 
458
                {
 
459
                        cairo_stroke(cr);
 
460
                        ge_cairo_set_color(cr, br);     
 
461
                }
 
462
 
 
463
                cairo_move_to(cr, x + 0.5, y + height - 0.5);
 
464
                cairo_line_to(cr, x + width - 0.5, y + height - 0.5);
 
465
                cairo_line_to(cr, x + width - 0.5, y + 0.5);
 
466
        }
 
467
 
 
468
        cairo_stroke(cr);
 
469
 
 
470
        cairo_restore(cr);
 
471
}
 
472
 
 
473
void ge_cairo_polygon (cairo_t *cr,
 
474
                                const CairoColor *color,
 
475
                                GdkPoint *points,
 
476
                                gint npoints)
 
477
{
 
478
        int i = 0;
 
479
 
 
480
        cairo_save(cr);
 
481
 
 
482
        ge_cairo_set_color(cr, color);  
 
483
        cairo_move_to(cr, points[0].x, points[0].y);
 
484
 
 
485
        for (i = 1; i < npoints; i++)
 
486
        {
 
487
                if (!((points[i].x == points[i + 1].x) &&
 
488
                    (points[i].y == points[i + 1].y))) 
 
489
                {
 
490
                        cairo_line_to(cr, points[i].x, points[i].y);
 
491
                }
 
492
        }
 
493
        
 
494
        if ((points[npoints-1].x != points[0].x) ||
 
495
                (points[npoints-1].y != points[0].y))
 
496
        {
 
497
                cairo_line_to(cr, points[0].x, points[0].y);
 
498
        }
 
499
 
 
500
        cairo_fill(cr);
 
501
 
 
502
        cairo_restore(cr);
 
503
}
 
504
 
 
505
void ge_cairo_line (cairo_t *cr,
 
506
                        const CairoColor *color,
 
507
                        gint x1,
 
508
                        gint y1,
 
509
                        gint x2,
 
510
                        gint y2)
 
511
 
512
        cairo_save(cr);
 
513
 
 
514
        ge_cairo_set_color(cr, color);  
 
515
        cairo_set_line_width (cr, 1);
 
516
 
 
517
        cairo_move_to(cr, x1 + 0.5, y1 + 0.5);
 
518
        cairo_line_to(cr, x2 + 0.5, y2 + 0.5);
 
519
 
 
520
        cairo_stroke(cr);
 
521
 
 
522
        cairo_restore(cr);
 
523
}
 
524
 
 
525
void
 
526
ge_cairo_mirror (cairo_t     *cr,
 
527
                 CairoMirror  mirror,
 
528
                 gint        *x,
 
529
                 gint        *y,
 
530
                 gint        *width,
 
531
                 gint        *height)
 
532
{
 
533
        cairo_matrix_t matrix;
 
534
        
 
535
        cairo_matrix_init_identity (&matrix);
 
536
        
 
537
        cairo_translate (cr, *x, *y);
 
538
        *x = 0;
 
539
        *y = 0;
 
540
        
 
541
        if (mirror & CR_MIRROR_HORIZONTAL)
 
542
        {
 
543
                cairo_matrix_scale (&matrix, -1, 1);
 
544
                *x = -*width;
 
545
        }
 
546
        if (mirror & CR_MIRROR_VERTICAL)
 
547
        {
 
548
                cairo_matrix_scale (&matrix, 1, -1);
 
549
                *y = -*height;
 
550
        }
 
551
 
 
552
        cairo_transform (cr, &matrix);
 
553
}
 
554
 
 
555
void
 
556
ge_cairo_exchange_axis (cairo_t  *cr,
 
557
                        gint     *x,
 
558
                        gint     *y,
 
559
                        gint     *width,
 
560
                        gint     *height)
 
561
{
 
562
        gint tmp;
 
563
        cairo_matrix_t matrix;
 
564
 
 
565
        cairo_translate (cr, *x, *y);
 
566
        cairo_matrix_init (&matrix, 0, 1, 1, 0, 0, 0);
 
567
 
 
568
        cairo_transform (cr, &matrix);
 
569
        
 
570
        /* swap width/height */
 
571
        tmp = *width;
 
572
        *x = 0;
 
573
        *y = 0;
 
574
        *width = *height;
 
575
        *height = tmp;
 
576
}
 
577
 
 
578
 
 
579
/***********************************************
 
580
 * ge_cairo_pattern_fill -
 
581
 *  
 
582
 *   Fill an area with some pattern
 
583
 *   Scaling or tiling if needed
 
584
 ***********************************************/
 
585
void 
 
586
ge_cairo_pattern_fill(cairo_t *canvas,
 
587
                        CairoPattern *pattern,
 
588
                        gint x,
 
589
                        gint y,
 
590
                        gint width,
 
591
                        gint height)
 
592
{
 
593
        cairo_matrix_t original_matrix, current_matrix;
 
594
 
 
595
        if (pattern->operator == CAIRO_OPERATOR_DEST)
 
596
        {
 
597
                return;
 
598
        }
 
599
 
 
600
        cairo_pattern_get_matrix(pattern->handle, &original_matrix);
 
601
        current_matrix = original_matrix;
 
602
 
 
603
        if (pattern->scale != GE_DIRECTION_NONE)
 
604
        {
 
605
                gdouble scale_x = 1.0;
 
606
                gdouble scale_y = 1.0;
 
607
 
 
608
                if ((pattern->scale == GE_DIRECTION_VERTICAL) || (pattern->scale == GE_DIRECTION_BOTH))
 
609
                {
 
610
                        scale_x = 1.0/width;
 
611
                }
 
612
 
 
613
                if ((pattern->scale == GE_DIRECTION_HORIZONTAL) || (pattern->scale == GE_DIRECTION_BOTH))
 
614
                {
 
615
                        scale_y = 1.0/height;
 
616
                }
 
617
 
 
618
                cairo_matrix_scale(&current_matrix, scale_x, scale_y);
 
619
        }
 
620
 
 
621
        if (pattern->translate != GE_DIRECTION_NONE)
 
622
        {
 
623
                gdouble translate_x = 0;
 
624
                gdouble translate_y = 0;
 
625
 
 
626
                if ((pattern->translate == GE_DIRECTION_VERTICAL) || (pattern->translate == GE_DIRECTION_BOTH))
 
627
                {
 
628
                        translate_x = 0.0-x;
 
629
                }
 
630
 
 
631
                if ((pattern->translate == GE_DIRECTION_HORIZONTAL) || (pattern->translate == GE_DIRECTION_BOTH))
 
632
                {
 
633
                        translate_y = 0.0-y;
 
634
                }
 
635
 
 
636
                cairo_matrix_translate(&current_matrix, translate_x, translate_y);
 
637
        }
 
638
 
 
639
        cairo_pattern_set_matrix(pattern->handle, &current_matrix);
 
640
 
 
641
        cairo_save(canvas);
 
642
 
 
643
        cairo_set_source(canvas, pattern->handle);
 
644
        cairo_set_operator(canvas, pattern->operator);
 
645
        cairo_rectangle(canvas, x, y, width, height);
 
646
 
 
647
        cairo_fill (canvas);
 
648
 
 
649
        cairo_restore(canvas);
 
650
 
 
651
        cairo_pattern_set_matrix(pattern->handle, &original_matrix);
 
652
}
 
653
 
 
654
/***********************************************
 
655
 * ge_cairo_color_pattern -
 
656
 *  
 
657
 *   Create A Solid Color Pattern
 
658
 ***********************************************/
 
659
CairoPattern*
 
660
ge_cairo_color_pattern(CairoColor *base)
 
661
{       
 
662
        CairoPattern * result = g_new0(CairoPattern, 1);
 
663
 
 
664
        #if  ((CAIRO_VERSION_MAJOR < 1) || ((CAIRO_VERSION_MAJOR == 1) && (CAIRO_VERSION_MINOR < 2)))
 
665
                result->type = CAIRO_PATTERN_TYPE_SOLID;
 
666
        #endif
 
667
 
 
668
        result->scale = GE_DIRECTION_NONE;
 
669
        result->translate = GE_DIRECTION_NONE;
 
670
 
 
671
        result->handle = cairo_pattern_create_rgba(base->r, 
 
672
                                                        base->g, 
 
673
                                                        base->b, 
 
674
                                                        base->a);
 
675
 
 
676
        result->operator = CAIRO_OPERATOR_SOURCE;
 
677
        
 
678
        return result;
 
679
}
 
680
 
 
681
/***********************************************
 
682
 * ge_cairo_pixbuf_pattern -
 
683
 *  
 
684
 *   Create A Tiled Pixbuf Pattern
 
685
 ***********************************************/
 
686
CairoPattern*
 
687
ge_cairo_pixbuf_pattern(GdkPixbuf *pixbuf)
 
688
{       
 
689
        CairoPattern * result = g_new0(CairoPattern, 1);
 
690
 
 
691
        cairo_t *canvas;
 
692
        cairo_surface_t * surface;
 
693
        gint width, height;
 
694
 
 
695
        #if  ((CAIRO_VERSION_MAJOR < 1) || ((CAIRO_VERSION_MAJOR == 1) && (CAIRO_VERSION_MINOR < 2)))
 
696
                result->type = CAIRO_PATTERN_TYPE_SURFACE;
 
697
        #endif
 
698
 
 
699
        result->scale = GE_DIRECTION_NONE;
 
700
        result->translate = GE_DIRECTION_BOTH;
 
701
 
 
702
        width = gdk_pixbuf_get_width(pixbuf);
 
703
        height = gdk_pixbuf_get_height(pixbuf);
 
704
        
 
705
        surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
 
706
 
 
707
        canvas = cairo_create(surface);
 
708
 
 
709
        gdk_cairo_set_source_pixbuf (canvas, pixbuf, 0, 0);
 
710
        cairo_rectangle (canvas, 0, 0, width, height);
 
711
        cairo_fill (canvas);
 
712
        cairo_destroy(canvas);
 
713
 
 
714
        result->handle = cairo_pattern_create_for_surface (surface);
 
715
        cairo_surface_destroy(surface);
 
716
 
 
717
        cairo_pattern_set_extend (result->handle, CAIRO_EXTEND_REPEAT);
 
718
 
 
719
        result->operator = CAIRO_OPERATOR_SOURCE;
 
720
 
 
721
        return result;
 
722
}
 
723
 
 
724
/***********************************************
 
725
 * ge_cairo_pixmap_pattern -
 
726
 *  
 
727
 *   Create A Tiled Pixmap Pattern
 
728
 ***********************************************/
 
729
CairoPattern*
 
730
ge_cairo_pixmap_pattern(GdkPixmap *pixmap)
 
731
{       
 
732
        CairoPattern * result = NULL;
 
733
 
 
734
        GdkPixbuf * pixbuf;
 
735
        gint width, height;
 
736
 
 
737
        gdk_drawable_get_size (GDK_DRAWABLE (pixmap), &width, &height);
 
738
 
 
739
        pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE (pixmap), 
 
740
                                gdk_drawable_get_colormap(GDK_DRAWABLE (pixmap)), 
 
741
                                0, 0, 0, 0, width, height);
 
742
 
 
743
        result = ge_cairo_pixbuf_pattern(pixbuf);
 
744
        
 
745
        g_object_unref (pixbuf);
 
746
 
 
747
        return result;
 
748
}
 
749
 
 
750
/***********************************************
 
751
 * ge_cairo_linear_shade_gradient_pattern - 
 
752
 *  
 
753
 *   Create A Linear Shade Gradient Pattern
 
754
 *   Aka Smooth Shade Gradient, from/to gradient
 
755
 *   With End points defined as shades of the
 
756
 *   base color
 
757
 ***********************************************/
 
758
CairoPattern *
 
759
ge_cairo_linear_shade_gradient_pattern(CairoColor *base, 
 
760
                                                gdouble shade1, 
 
761
                                                gdouble shade2, 
 
762
                                                gboolean vertical)
 
763
{
 
764
        CairoPattern * result = g_new0(CairoPattern, 1);
 
765
        
 
766
        #if  ((CAIRO_VERSION_MAJOR < 1) || ((CAIRO_VERSION_MAJOR == 1) && (CAIRO_VERSION_MINOR < 2)))
 
767
                result->type = CAIRO_PATTERN_TYPE_LINEAR;
 
768
        #endif
 
769
 
 
770
        if (vertical)
 
771
        {
 
772
                result->scale = GE_DIRECTION_VERTICAL;
 
773
 
 
774
                result->handle = cairo_pattern_create_linear(0, 0, 1, 0);
 
775
        }
 
776
        else
 
777
        {
 
778
                result->scale = GE_DIRECTION_HORIZONTAL;
 
779
 
 
780
                result->handle = cairo_pattern_create_linear(0, 0, 0, 1);
 
781
        }
 
782
 
 
783
        result->translate = GE_DIRECTION_BOTH;
 
784
        result->operator = CAIRO_OPERATOR_SOURCE;
 
785
 
 
786
        ge_cairo_pattern_add_color_stop_shade(result->handle, 0, base, shade1);
 
787
        ge_cairo_pattern_add_color_stop_shade(result->handle, 1, base, shade2);
 
788
 
 
789
        return result;
 
790
}
 
791
 
 
792
void
 
793
ge_cairo_pattern_destroy(CairoPattern *pattern)
 
794
{
 
795
        if (pattern)
 
796
        {
 
797
                if (pattern->handle)
 
798
                        cairo_pattern_destroy(pattern->handle);
 
799
                        
 
800
                g_free(pattern);
 
801
        }
 
802
}
 
803
 
 
804
/* The following function will be called by GTK+ when the module
 
805
 * is loaded and checks to see if we are compatible with the
 
806
 * version of GTK+ that loads us.
 
807
 */
 
808
GE_EXPORT const gchar* g_module_check_init (GModule *module);
 
809
const gchar*
 
810
g_module_check_init (GModule *module)
 
811
{
 
812
        (void) module;
 
813
        
 
814
        return gtk_check_version (GTK_MAJOR_VERSION,
 
815
                                  GTK_MINOR_VERSION,
 
816
                                  GTK_MICRO_VERSION - GTK_INTERFACE_AGE);
 
817
}