2 Copyright 2009 by Hans Baier
10 public enum ButtonState
{
15 public enum ButtonType
{
20 public static Gdk
.RGBA
rgba_new (double red
, double green
, double blue
, double alpha
= 1.0) {
21 Gdk
.RGBA color
= RGBA();
29 public static Gdk
.RGBA
rgba_from_string (string s
) {
30 Gdk
.RGBA color
= RGBA();
36 public static Gdk
.RGBA
gdk_color_to_rgba (Gdk
.Color color
) {
37 Gdk
.RGBA rgba
= RGBA();
38 rgba
.red
= (double)color
.red
/ (double)uint16.MAX
;
39 rgba
.green
= (double)color
.green
/ (double)uint16.MAX
;
40 rgba
.blue
= (double)color
.blue
/ (double)uint16.MAX
;
44 public static void add_color_stop_to (Cairo
.Pattern p
, double offset
, Gdk
.RGBA color
) {
45 p
.add_color_stop_rgba (offset
, color
.red
, color
.green
, color
.blue
, color
.alpha
);
48 public static void set_line_width_from_device (Cairo
.Context cr
) {
50 cr
.device_to_user (ref ux
, ref uy
);
54 cr
.set_line_width (ux
);
57 public static void set_source_color (Cairo
.Context cr
, Gdk
.RGBA color
, double alpha
= 1.0) {
58 cr
.set_source_rgba(color
.red
, color
.green
, color
.blue
, alpha
);
61 public static void set_source_color_string (Cairo
.Context cr
, string color
, double alpha
= 1.0) {
62 Gdk
.RGBA c
= rgba_from_string(color
);
64 Gdk
.cairo_set_source_rgba (cr
, c
);
67 public static void add_color_stop (Cairo
.Pattern p
, double offset
, Gdk
.RGBA color
, double alpha
= 1.0) {
68 p
.add_color_stop_rgba (offset
, color
.red
, color
.green
, color
.blue
, alpha
);
71 public static void add_color_stop_str (Cairo
.Pattern p
, double offset
, string color
, double alpha
= 1.0) {
72 add_color_stop (p
, offset
, rgba_from_string (color
), alpha
);
75 public static Cairo
.Pattern
create_gradient (double x1
, double y1
, double x2
, double y2
, Gdk
.RGBA start
, Gdk
.RGBA stop
, double alpha_start
= 1.0, double alpha_stop
= 1.0) {
76 Cairo
.Pattern gradient
= new Cairo
.Pattern
.linear(x1
, y1
, x2
, y2
);
77 add_color_stop(gradient
, 0, start
, alpha_start
);
78 add_color_stop(gradient
, 1, stop
, alpha_stop
);
82 public static Cairo
.Pattern
create_gradient_str (double x1
, double y1
, double x2
, double y2
, string start
, string stop
, double alpha_start
= 1.0, double alpha_stop
= 1.0) {
83 return create_gradient (x1
, y1
, x2
, y2
, rgba_from_string (start
), rgba_from_string (stop
), alpha_start
, alpha_stop
);
86 public static void rounded_rect (Cairo
.Context cr
, double x
, double y
, double w
, double h
, double radius_x
=5, double radius_y
=5) {
87 // from mono moonlight aka mono silverlight
88 // test limits (without using multiplications)
89 // http://graphics.stanford.edu/courses/cs248-98-fall/Final/q1.html
90 double ARC_TO_BEZIER
= 0.55228475;
92 if (radius_x
> w
- radius_x
)
94 if (radius_y
> h
- radius_y
)
97 // approximate (quite close) the arc using a bezier curve
98 var c1
= ARC_TO_BEZIER
* radius_x
;
99 var c2
= ARC_TO_BEZIER
* radius_y
;
102 cr
.move_to ( x
+ radius_x
, y
);
103 cr
.rel_line_to ( w
- 2 * radius_x
, 0.0);
104 cr
.rel_curve_to ( c1
, 0.0, radius_x
, c2
, radius_x
, radius_y
);
105 cr
.rel_line_to ( 0, h
- 2 * radius_y
);
106 cr
.rel_curve_to ( 0.0, c2
, c1
- radius_x
, radius_y
, -radius_x
, radius_y
);
107 cr
.rel_line_to ( -w
+ 2 * radius_x
, 0);
108 cr
.rel_curve_to ( -c1
, 0, -radius_x
, -c2
, -radius_x
, -radius_y
);
109 cr
.rel_line_to (0, -h
+ 2 * radius_y
);
110 cr
.rel_curve_to (0.0, -c2
, radius_x
- c1
, -radius_y
, radius_x
, -radius_y
);
114 public static void background_gradient(Cairo
.Context cr
, double w
, double h
) {
115 // outside background
116 Gdk
.RGBA background_gradient_start
= RGBA();
117 Gdk
.RGBA background_gradient_stop
= RGBA();
118 background_gradient_start
.parse("#bebdc2");
119 background_gradient_stop
.parse("#b1b4b9");
121 cr
.rectangle (0, 0, w
, h
);
122 Cairo
.Pattern background_gradient
= new Cairo
.Pattern
.linear(0, 0, 0, h
);
123 add_color_stop(background_gradient
, 0, background_gradient_start
);
124 add_color_stop(background_gradient
, 1, background_gradient_stop
);
125 cr
.set_source (background_gradient
);
129 public static double modula(double number
, double divisor
) {
130 return (((int)number
% (int)divisor
) + (number
- (int)number
));
134 public double hue
{get; set;}
135 public double saturation
{get; set;}
136 public double lightness
{get; set;}
137 public double alpha
{get; set;}
143 public string to_string() {
144 return "HSL (%f, %f, %f)".printf (hue
, saturation
, lightness
);
147 public Gdk
.RGBA
to_rgba() {
149 var hue_shift
= new
double[3];
150 var color_shift
= new
double[3];
155 if (lightness
<= 0.5)
156 m2
= lightness
* (1 + saturation
);
158 m2
= lightness
+ saturation
- lightness
* saturation
;
160 m1
= 2 * lightness
- m2
;
162 hue_shift
[0] = hue
+ 120;
164 hue_shift
[2] = hue
- 120;
166 color_shift
[0] = color_shift
[1] = color_shift
[2] = lightness
;
168 i
= (saturation
== 0) ?
3 : 0;
175 m3
= modula(m3
, 360);
177 m3
= 360 - modula(Math
.fabs(m3
), 360);
180 color_shift
[i
] = m1
+ (m2
- m1
) * m3
/ 60.0;
184 color_shift
[i
] = m1
+ (m2
- m1
) * (240 - m3
) / 60.0;
189 Gdk
.RGBA color
= { color_shift
[0], color_shift
[1], color_shift
[2], alpha
};
194 public void from_rgba(Gdk
.RGBA color
) {
195 double min
, max
, delta
;
197 double red
= color
.red
;
198 double green
= color
.green
;
199 double blue
= color
.blue
;
200 this
.alpha
= color
.alpha
;
224 lightness
= (max
+ min
) / 2.0;
226 if (Math
.fabs(max
- min
) < 0.0001) {
230 if (lightness
<= 0.5)
231 saturation
= (max
- min
) / (max
+ min
);
233 saturation
= (max
- min
) / (2.0 - max
- min
);
238 hue
= (green
- blue
) / delta
;
239 else if (green
== max
)
240 hue
= 2.0 + (blue
- red
) / delta
;
241 else if (blue
== max
)
242 hue
= 4.0 + (red
- green
) / delta
;
252 public double hue
{get; set;}
253 public double saturation
{get; set;}
254 public double value
{get; set;}
255 public double alpha
{get; set;}
261 public string to_string() {
262 return "HSV (%f, %f, %f)".printf (hue
, saturation
, value
);
265 public HSV
.for_rgba (Gdk
.RGBA color
) {
269 public Gdk
.RGBA
to_rgba() {
270 double r
= 0.0, g
= 0.0, b
= 0.0;
275 hi
= (int) modula(Math
.floor(hue
/ 60.0), 6);
276 f
= hue
/ 60.0 - Math
.floor(hue
/ 60.0);
277 p
= value
* (1.0 - saturation
);
278 q
= value
* (1.0 - f
* saturation
);
279 t
= value
* (1.0 - (1.0 - f
) * saturation
);
282 case 0: r
= value
; g
= t
; b
= p
; break;
283 case 1: r
= q
; g
= value
; b
= p
; break;
284 case 2: r
= p
; g
= value
; b
= t
; break;
285 case 3: r
= p
; g
= q
; b
= value
; break;
286 case 4: r
= t
; g
= p
; b
= value
; break;
287 case 5: r
= value
; g
= p
; b
= q
; break;
291 Gdk
.RGBA color
= {r
, g
, b
, alpha
};
296 public void from_rgba(Gdk
.RGBA color
) {
297 double min
, max
, delta
;
299 double red
= color
.red
;
300 double green
= color
.green
;
301 double blue
= color
.blue
;
302 this
.alpha
= color
.alpha
;
328 if (Math
.fabs(max
- min
) < 0.0001)
338 saturation
= (max
- min
) / max
;
343 hue
= (green
- blue
) / delta
;
344 else if (green
== max
)
345 hue
= 2.0 + (blue
- red
) / delta
;
346 else if (blue
== max
)
347 hue
= 4.0 + (red
- green
) / delta
;
356 public static Gdk
.RGBA
rgba_shade(Gdk
.RGBA orig
, double shade_ratio
) {
357 HSL HSL
= new
HSL ();
358 HSL
.from_rgba (orig
);
360 HSL
.lightness
= Math
.fmin (HSL
.lightness
* shade_ratio
, 1.0);
361 HSL
.lightness
= Math
.fmax (HSL
.lightness
, 0.0);
363 HSL
.saturation
= Math
.fmin (HSL
.saturation
* shade_ratio
, 1.0);
364 HSL
.saturation
= Math
.fmax (HSL
.saturation
, 0.0);
366 Gdk
.RGBA result
= HSL
.to_rgba ();
370 public static Gdk
.Pixbuf
cairo_image_surface_to_pixbuf (Cairo
.ImageSurface surface
) {
371 if (surface
.get_format() != Cairo
.Format
.ARGB32
)
374 weak uchar[] knob_data
= surface
.get_data ();
376 for (int i
= 0; i
< surface
.get_height() * surface
.get_stride(); i
+= 4) {
377 uchar r
= knob_data
[i
+0];
378 uchar g
= knob_data
[i
+1];
379 uchar b
= knob_data
[i
+2];
380 uchar a
= knob_data
[i
+3];
382 //FIXME: Undo premultiplied alpha here
389 return new Gdk
.Pixbuf
.from_data (knob_data
, Gdk
.Colorspace
.RGB
, true, 8, surface
.get_width(), surface
.get_height(), surface
.get_stride() , null);
392 } // namespace Prolooks