1 /* Murrine theme engine
2  * Copyright (C) 2006-2007-2008-2009 Andrea Cimitan
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  */
20 
21 #include <math.h>
22 
23 #include "cairo-support.h"
24 #include "support.h"
25 #include "murrine_types.h"
26 #include "raico-blur.h"
27 
28 G_GNUC_INTERNAL void
murrine_rgb_to_hls(gdouble * r,gdouble * g,gdouble * b)29 murrine_rgb_to_hls (gdouble *r,
30                     gdouble *g,
31                     gdouble *b)
32 {
33 	gdouble min;
34 	gdouble max;
35 	gdouble red;
36 	gdouble green;
37 	gdouble blue;
38 	gdouble h, l, s;
39 	gdouble delta;
40 
41 	red = *r;
42 	green = *g;
43 	blue = *b;
44 
45 	if (red > green)
46 	{
47 		if (red > blue)
48 			max = red;
49 		else
50 			max = blue;
51 
52 		if (green < blue)
53 			min = green;
54 		else
55 			min = blue;
56 	}
57 	else
58 	{
59 		if (green > blue)
60 			max = green;
61 		else
62 			max = blue;
63 
64 		if (red < blue)
65 			min = red;
66 		else
67 			min = blue;
68 	}
69 
70 	l = (max+min)/2;
71 	if (fabs (max-min) < 0.0001)
72 	{
73 		h = 0;
74 		s = 0;
75 	}
76 	else
77 	{
78 		if (l <= 0.5)
79 			s = (max-min)/(max+min);
80 		else
81 			s = (max-min)/(2-max-min);
82 
83 		delta = max -min;
84 		if (red == max)
85 			h = (green-blue)/delta;
86 		else if (green == max)
87 			h = 2+(blue-red)/delta;
88 		else if (blue == max)
89 			h = 4+(red-green)/delta;
90 
91 		h *= 60;
92 		if (h < 0.0)
93 			h += 360;
94 	}
95 
96 	*r = h;
97 	*g = l;
98 	*b = s;
99 }
100 
101 G_GNUC_INTERNAL void
murrine_hls_to_rgb(gdouble * h,gdouble * l,gdouble * s)102 murrine_hls_to_rgb (gdouble *h,
103                     gdouble *l,
104                     gdouble *s)
105 {
106 	gdouble hue;
107 	gdouble lightness;
108 	gdouble saturation;
109 	gdouble m1, m2;
110 	gdouble r, g, b;
111 
112 	lightness = *l;
113 	saturation = *s;
114 
115 	if (lightness <= 0.5)
116 		m2 = lightness*(1+saturation);
117 	else
118 		m2 = lightness+saturation-lightness*saturation;
119 
120 	m1 = 2*lightness-m2;
121 
122 	if (saturation == 0)
123 	{
124 		*h = lightness;
125 		*l = lightness;
126 		*s = lightness;
127 	}
128 	else
129 	{
130 		hue = *h+120;
131 		while (hue > 360)
132 			hue -= 360;
133 		while (hue < 0)
134 			hue += 360;
135 
136 		if (hue < 60)
137 			r = m1+(m2-m1)*hue/60;
138 		else if (hue < 180)
139 			r = m2;
140 		else if (hue < 240)
141 			r = m1+(m2-m1)*(240-hue)/60;
142 		else
143 			r = m1;
144 
145 		hue = *h;
146 		while (hue > 360)
147 			hue -= 360;
148 		while (hue < 0)
149 			hue += 360;
150 
151 		if (hue < 60)
152 			g = m1+(m2-m1)*hue/60;
153 		else if (hue < 180)
154 			g = m2;
155 		else if (hue < 240)
156 			g = m1+(m2-m1)*(240-hue)/60;
157 		else
158 			g = m1;
159 
160 		hue = *h-120;
161 		while (hue > 360)
162 			hue -= 360;
163 		while (hue < 0)
164 			hue += 360;
165 
166 		if (hue < 60)
167 			b = m1+(m2-m1)*hue/60;
168 		else if (hue < 180)
169 			b = m2;
170 		else if (hue < 240)
171 			b = m1+(m2-m1)*(240-hue)/60;
172 		else
173 			b = m1;
174 
175 		*h = r;
176 		*l = g;
177 		*s = b;
178 	}
179 }
180 
181 void
murrine_shade(const MurrineRGB * a,float k,MurrineRGB * b)182 murrine_shade (const MurrineRGB *a, float k, MurrineRGB *b)
183 {
184 	double red;
185 	double green;
186 	double blue;
187 
188 	red   = a->r;
189 	green = a->g;
190 	blue  = a->b;
191 
192 	if (k == 1.0)
193 	{
194 		b->r = red;
195 		b->g = green;
196 		b->b = blue;
197 		return;
198 	}
199 
200 	murrine_rgb_to_hls (&red, &green, &blue);
201 
202 	green *= k;
203 	if (green > 1.0)
204 		green = 1.0;
205 	else if (green < 0.0)
206 		green = 0.0;
207 
208 	blue *= k;
209 	if (blue > 1.0)
210 		blue = 1.0;
211 	else if (blue < 0.0)
212 		blue = 0.0;
213 
214 	murrine_hls_to_rgb (&red, &green, &blue);
215 
216 	b->r = red;
217 	b->g = green;
218 	b->b = blue;
219 }
220 
221 void
murrine_invert_text(const MurrineRGB * a,MurrineRGB * b)222 murrine_invert_text (const MurrineRGB *a, MurrineRGB *b)
223 {
224 	double red;
225 	double green;
226 	double blue;
227 
228 	red   = a->r;
229 	green = a->g;
230 	blue  = a->b;
231 
232 	murrine_rgb_to_hls (&red, &green, &blue);
233 
234 	if (green < 0.8)
235 		green = 1.0;
236 	else
237 		green = 0.0;
238 
239 	murrine_hls_to_rgb (&red, &green, &blue);
240 
241 	b->r = red;
242 	b->g = green;
243 	b->b = blue;
244 }
245 
246 void
murrine_mix_color(const MurrineRGB * color1,const MurrineRGB * color2,gdouble mix_factor,MurrineRGB * composite)247 murrine_mix_color (const MurrineRGB *color1, const MurrineRGB *color2,
248                    gdouble mix_factor, MurrineRGB *composite)
249 {
250 	g_return_if_fail (color1 && color2 && composite);
251 
252 	composite->r = color1->r*(1-mix_factor)+color2->r*mix_factor;
253 	composite->g = color1->g*(1-mix_factor)+color2->g*mix_factor;
254 	composite->b = color1->b*(1-mix_factor)+color2->b*mix_factor;
255 }
256 
257 void
murrine_gdk_color_to_rgb(GdkColor * c,double * r,double * g,double * b)258 murrine_gdk_color_to_rgb (GdkColor *c, double *r, double *g, double *b)
259 {
260 	*r = (double)c->red/(double)65535;
261 	*g = (double)c->green/(double)65535;
262 	*b = (double)c->blue/(double)65535;
263 }
264 
265 void
murrine_get_parent_bg(const GtkWidget * widget,MurrineRGB * color)266 murrine_get_parent_bg (const GtkWidget *widget, MurrineRGB *color)
267 {
268 	GtkStateType state_type;
269 	const GtkWidget *parent;
270 	GdkColor *gcolor;
271 	gboolean stop;
272 
273 	if (widget == NULL)
274 		return;
275 
276 	parent = widget->parent;
277 	stop = FALSE;
278 
279 	while (parent && !stop)
280 	{
281 		stop = FALSE;
282 
283 		stop |= !GTK_WIDGET_NO_WINDOW (parent);
284 		stop |= GTK_IS_NOTEBOOK (parent) &&
285 		        gtk_notebook_get_show_tabs (GTK_NOTEBOOK (parent)) &&
286 		        gtk_notebook_get_show_border (GTK_NOTEBOOK (parent));
287 
288 		if (GTK_IS_TOOLBAR (parent))
289 		{
290 			GtkShadowType shadow = GTK_SHADOW_OUT;
291 			gtk_widget_style_get (GTK_WIDGET (parent), "shadow-type", &shadow, NULL);
292 
293 			stop |= (shadow != GTK_SHADOW_NONE);
294 		}
295 
296 		if (!stop)
297 			parent = parent->parent;
298 	}
299 
300 	if (parent == NULL)
301 		return;
302 
303 	state_type = GTK_WIDGET_STATE (parent);
304 
305 	gcolor = &parent->style->bg[state_type];
306 
307 	murrine_gdk_color_to_rgb (gcolor, &color->r, &color->g, &color->b);
308 }
309 
310 void
murrine_set_color_rgb(cairo_t * cr,const MurrineRGB * color)311 murrine_set_color_rgb (cairo_t *cr, const MurrineRGB *color)
312 {
313 	g_return_if_fail (cr && color);
314 
315 	cairo_set_source_rgb (cr, color->r, color->g, color->b);
316 }
317 
318 void
murrine_set_color_rgba(cairo_t * cr,const MurrineRGB * color,double alpha)319 murrine_set_color_rgba (cairo_t *cr, const MurrineRGB *color, double alpha)
320 {
321 	g_return_if_fail (cr && color);
322 
323 	cairo_set_source_rgba (cr, color->r, color->g, color->b, alpha);
324 }
325 
326 void
murrine_pattern_add_color_stop_rgb(cairo_pattern_t * pat,double pos,const MurrineRGB * color)327 murrine_pattern_add_color_stop_rgb (cairo_pattern_t *pat, double pos,
328                                     const MurrineRGB *color)
329 {
330 	g_return_if_fail (pat && color);
331 
332 	cairo_pattern_add_color_stop_rgb (pat, pos, color->r, color->g, color->b);
333 }
334 
335 void
murrine_pattern_add_color_stop_rgba(cairo_pattern_t * pat,double pos,const MurrineRGB * color,double alpha)336 murrine_pattern_add_color_stop_rgba (cairo_pattern_t *pat, double pos,
337                                      const MurrineRGB *color, double alpha)
338 {
339 	g_return_if_fail (pat && color);
340 
341 	cairo_pattern_add_color_stop_rgba (pat, pos, color->r, color->g, color->b, alpha);
342 }
343 
344 void
murrine_rounded_corner(cairo_t * cr,double x,double y,int radius,uint8 corner)345 murrine_rounded_corner (cairo_t *cr,
346                         double   x,
347                         double   y,
348                         int radius, uint8 corner)
349 {
350 	if (radius < 1)
351 	{
352 		cairo_line_to (cr, x, y);
353 	}
354 	else
355 	{
356 		switch (corner)
357 		{
358 			case MRN_CORNER_NONE:
359 				cairo_line_to (cr, x, y);
360 				break;
361 			case MRN_CORNER_TOPLEFT:
362 				cairo_arc (cr, x+radius, y+radius, radius, G_PI, G_PI*3/2);
363 				break;
364 			case MRN_CORNER_TOPRIGHT:
365 				cairo_arc (cr, x-radius, y+radius, radius, G_PI*3/2, G_PI*2);
366 				break;
367 			case MRN_CORNER_BOTTOMRIGHT:
368 				cairo_arc (cr, x-radius, y-radius, radius, 0, G_PI*1/2);
369 				break;
370 			case MRN_CORNER_BOTTOMLEFT:
371 				cairo_arc (cr, x+radius, y-radius, radius, G_PI*1/2, G_PI);
372 				break;
373 
374 			default:
375 				/* A bitfield and not a sane value ... */
376 				g_assert_not_reached ();
377 				cairo_line_to (cr, x, y);
378 				return;
379 		}
380 	}
381 }
382 
383 void
murrine_rounded_rectangle_fast(cairo_t * cr,double x,double y,double w,double h,uint8 corners)384 murrine_rounded_rectangle_fast (cairo_t *cr,
385                                 double x, double y, double w, double h,
386                                 uint8 corners)
387 {
388 	const float RADIUS_CORNERS = 0.35;
389 
390 	if (corners & MRN_CORNER_TOPLEFT)
391 		cairo_move_to (cr, x+RADIUS_CORNERS, y);
392 	else
393 		cairo_move_to (cr, x, y);
394 
395 	if (corners & MRN_CORNER_TOPRIGHT)
396 	{
397 		cairo_line_to (cr, x+w-RADIUS_CORNERS, y);
398 		cairo_move_to (cr, x+w, y+RADIUS_CORNERS);
399 	}
400 	else
401 		cairo_line_to (cr, x+w, y);
402 
403 	if (corners & MRN_CORNER_BOTTOMRIGHT)
404 	{
405 		cairo_line_to (cr, x+w, y+h-RADIUS_CORNERS);
406 		cairo_move_to (cr, x+w-RADIUS_CORNERS, y+h);
407 	}
408 	else
409 		cairo_line_to (cr, x+w, y+h);
410 
411 	if (corners & MRN_CORNER_BOTTOMLEFT)
412 	{
413 		cairo_line_to (cr, x+RADIUS_CORNERS, y+h);
414 		cairo_move_to (cr, x, y+h-RADIUS_CORNERS);
415 	}
416 	else
417 		cairo_line_to (cr, x, y+h);
418 
419 	if (corners & MRN_CORNER_TOPLEFT)
420 		cairo_line_to (cr, x, y+RADIUS_CORNERS);
421 	else
422 	{
423 		if (corners == MRN_CORNER_NONE)
424 			cairo_close_path (cr);
425 		else
426 			cairo_line_to (cr, x, y);
427 	}
428 }
429 
430 void
clearlooks_rounded_rectangle(cairo_t * cr,double x,double y,double w,double h,int radius,uint8 corners)431 clearlooks_rounded_rectangle (cairo_t *cr,
432                               double x, double y, double w, double h,
433                               int radius, uint8 corners)
434 {
435 	if (radius < 1)
436 	{
437 		cairo_rectangle (cr, x, y, w, h);
438 		return;
439 	}
440 
441 	radius = MIN (radius, MIN (w/2.0, h/2.0));
442 
443 	if (corners & MRN_CORNER_TOPLEFT)
444 		cairo_move_to (cr, x+radius, y);
445 	else
446 		cairo_move_to (cr, x, y);
447 
448 	if (corners & MRN_CORNER_TOPRIGHT)
449 		cairo_arc (cr, x+w-radius, y+radius, radius, M_PI*1.5, M_PI*2);
450 	else
451 		cairo_line_to (cr, x+w, y);
452 
453 	if (corners & MRN_CORNER_BOTTOMRIGHT)
454 		cairo_arc (cr, x+w-radius, y+h-radius, radius, 0, M_PI*0.5);
455 	else
456 		cairo_line_to (cr, x+w, y+h);
457 
458 	if (corners & MRN_CORNER_BOTTOMLEFT)
459 		cairo_arc (cr, x+radius,   y+h-radius, radius, M_PI*0.5, M_PI);
460 	else
461 		cairo_line_to (cr, x, y+h);
462 
463 	if (corners & MRN_CORNER_TOPLEFT)
464 		cairo_arc (cr, x+radius,   y+radius,   radius, M_PI, M_PI*1.5);
465 	else
466 		cairo_line_to (cr, x, y);
467 }
468 
469 void
murrine_rounded_rectangle_inverted(cairo_t * cr,double x,double y,double w,double h,int radius,uint8 corners)470 murrine_rounded_rectangle_inverted (cairo_t *cr,
471                                     double x, double y, double w, double h,
472                                     int radius, uint8 corners)
473 {
474 	radius = MIN (radius, MIN (w/2.0, h/2.0));
475 
476 	cairo_translate(cr, x, y);
477 
478 	if (corners & MRN_CORNER_TOPLEFT)
479 		cairo_move_to(cr, 0, -radius);
480 	else
481 		cairo_move_to(cr, 0, 0);
482 
483 	if (corners & MRN_CORNER_BOTTOMLEFT)
484 		cairo_arc(cr, radius, h + radius, radius, M_PI * 1.0, M_PI * 1.5);
485 	else
486 		cairo_line_to(cr, 0, h);
487 
488 	if (corners & MRN_CORNER_BOTTOMRIGHT)
489 		cairo_arc(cr, w - radius, h + radius, radius, M_PI * 1.5, M_PI * 2.0);
490 	else
491 		cairo_line_to(cr, w, h);
492 
493 	if (corners & MRN_CORNER_TOPRIGHT)
494 		cairo_arc(cr, w - radius, -radius, radius, M_PI * 0.0, M_PI * 0.5);
495 	else
496 		cairo_line_to(cr, w, 0);
497 
498 	if (corners & MRN_CORNER_TOPLEFT)
499 		cairo_arc(cr, radius, -radius, radius, M_PI * 0.5, M_PI * 1.0);
500 	else
501 		cairo_line_to(cr, 0, 0);
502 
503 	cairo_translate(cr, -x, -y);
504 }
505 
506 void
murrine_rounded_rectangle(cairo_t * cr,double x,double y,double w,double h,int radius,uint8 corners)507 murrine_rounded_rectangle (cairo_t *cr,
508                            double x, double y, double w, double h,
509                            int radius, uint8 corners)
510 {
511 	radius < 2 ? radius < 1 ? cairo_rectangle (cr, x, y, w, h) :
512 	                          murrine_rounded_rectangle_fast (cr, x, y, w, h, corners) :
513 	             clearlooks_rounded_rectangle (cr, x, y, w, h, radius, corners);
514 }
515 
516 void
murrine_rounded_rectangle_closed(cairo_t * cr,double x,double y,double w,double h,int radius,uint8 corners)517 murrine_rounded_rectangle_closed (cairo_t *cr,
518                                   double x, double y, double w, double h,
519                                   int radius, uint8 corners)
520 {
521 	radius < 2 ? cairo_rectangle (cr, x, y, w, h) :
522 	             clearlooks_rounded_rectangle (cr, x, y, w, h, radius, corners);
523 }
524 
525 static void
murrine_draw_flat_highlight(cairo_t * cr,int x,int y,int width,int height)526 murrine_draw_flat_highlight (cairo_t *cr,
527                              int x, int y, int width, int height)
528 {
529 	cairo_rectangle (cr, x, y, width, height/2);
530 }
531 
532 static void
murrine_draw_curved_highlight(cairo_t * cr,int x,int y,int width,int height)533 murrine_draw_curved_highlight (cairo_t *cr,
534                                int x, int y, int width, int height)
535 {
536 	int w = width+x*2;
537 	int h = height+y*2;
538 
539 	cairo_move_to (cr, x, h-y);
540 	cairo_curve_to (cr, x, h/2+h/5, h/5, h/2, h/2, h/2);
541 	cairo_line_to (cr, w-h/2, h/2);
542 	cairo_curve_to (cr, w-x-h/5, h/2, w-x-0.5, h/2-h/5, w-x, y);
543 	cairo_line_to (cr, x, y);
544 	cairo_line_to (cr, x, h-y);
545 	cairo_close_path (cr);
546 }
547 
548 static void
murrine_draw_curved_highlight_top(cairo_t * cr,int x,int y,int width,int height)549 murrine_draw_curved_highlight_top (cairo_t *cr,
550                                    int x, int y, int width, int height)
551 {
552 	int w = width+x*2;
553 	int h = height+y*2;
554 
555 	cairo_move_to (cr, x, y);
556 	cairo_curve_to (cr, x, h/2-h/5, h/5, h/2, h/2, h/2);
557 	cairo_line_to (cr, w-h/2, h/2);
558 	cairo_curve_to (cr, w-x-h/5, h/2, w-x-0.5, h/2-h/5, w-x, y);
559 	cairo_close_path (cr);
560 }
561 
562 static void
murrine_draw_curved_highlight_bottom(cairo_t * cr,int x,int y,int width,int height)563 murrine_draw_curved_highlight_bottom (cairo_t *cr,
564                                       int x, int y, int width, int height)
565 {
566 	int w = width+x*2;
567 	int h = height+y*2;
568 
569 	cairo_move_to (cr, x, h-y);
570 	cairo_curve_to (cr, x, h/2+h/5, h/5, h/2, h/2, h/2);
571 	cairo_line_to (cr, w-h/2, h/2);
572 	cairo_curve_to (cr, w-x-h/5, h/2, w-x-0.5, h/2+h/5, w-x, h-y);
573 	cairo_close_path (cr);
574 }
575 
576 /*
577  * Test new glazestyles here :)
578  */
579 static void
murrine_draw_new_glossy_highlight(cairo_t * cr,int x,int y,int width,int height)580 murrine_draw_new_glossy_highlight (cairo_t *cr,
581                                    int x, int y, int width, int height)
582 {
583 	double gloss_height = .5;
584 	int gloss_angle = 3;
585 	int local_gloss_height = (int) (height*gloss_height);
586 
587 	cairo_move_to (cr, x, y);
588 	cairo_line_to (cr, x+width, y);
589 	cairo_line_to (cr, x+width, local_gloss_height);
590 	cairo_curve_to (cr, x+2*width/3, local_gloss_height+gloss_angle, x+width/3,
591 	                    local_gloss_height+gloss_angle, x, local_gloss_height);
592 	cairo_close_path (cr);
593 }
594 
595 static void
murrine_draw_bottom_glow(cairo_t * cr,const MurrineRGB * glow,int x,int y,int width,int height)596 murrine_draw_bottom_glow (cairo_t *cr,
597                           const MurrineRGB *glow,
598                           int x, int y, int width, int height)
599 {
600 	cairo_pattern_t *pat;
601 	double           scaling_factor = (double)1.2*width/height;
602 
603 	cairo_rectangle (cr, x, y, width, height);
604 	cairo_save (cr);
605 	cairo_scale (cr, scaling_factor, 1);
606 	pat = cairo_pattern_create_radial ((x+width/2.0)/scaling_factor, y+height, 0,
607 	                                   (x+width/2.0)/scaling_factor, y+height, height/2);
608 	murrine_pattern_add_color_stop_rgba (pat, 0.0, glow, 0.5);
609 	murrine_pattern_add_color_stop_rgba (pat, 1.0, glow, 0.0);
610 	cairo_set_source (cr, pat);
611 	cairo_pattern_destroy (pat);
612 	cairo_fill (cr);
613 	cairo_restore (cr);
614 }
615 
616 static void
murrine_draw_centered_glow(cairo_t * cr,const MurrineRGB * glow,int x,int y,int width,int height)617 murrine_draw_centered_glow (cairo_t *cr,
618                             const MurrineRGB *glow,
619                             int x, int y, int width, int height)
620 {
621 	cairo_pattern_t *pat;
622 	double           scaling_factor = (double)1.2*width/height;
623 
624 	cairo_rectangle (cr, x, y, width, height);
625 	cairo_save (cr);
626 	cairo_scale (cr, scaling_factor, 1);
627 	pat = cairo_pattern_create_radial ((x+width/2.0)/scaling_factor, y+height/2, 0,
628 	                                   (x+width/2.0)/scaling_factor, y+height/2, height/2);
629 	murrine_pattern_add_color_stop_rgba (pat, 0.0, glow, 0.5);
630 	murrine_pattern_add_color_stop_rgba (pat, 1.0, glow, 0.0);
631 	cairo_set_source (cr, pat);
632 	cairo_pattern_destroy (pat);
633 	cairo_fill (cr);
634 	cairo_restore (cr);
635 }
636 
637 static void
murrine_draw_horizontal_glow(cairo_t * cr,const MurrineRGB * glow,int x,int y,int width,int height)638 murrine_draw_horizontal_glow (cairo_t *cr,
639                               const MurrineRGB *glow,
640                               int x, int y, int width, int height)
641 {
642 	cairo_pattern_t *pat;
643 
644 	cairo_rectangle (cr, x, y, width, height);
645 	pat = cairo_pattern_create_linear (x, y, width, 0);
646 	murrine_pattern_add_color_stop_rgba (pat, 0.0, glow, 0.0);
647 	murrine_pattern_add_color_stop_rgba (pat, 0.5, glow, 0.5);
648 	murrine_pattern_add_color_stop_rgba (pat, 1.0, glow, 0.0);
649 	cairo_set_source (cr, pat);
650 	cairo_pattern_destroy (pat);
651 	cairo_fill (cr);
652 }
653 
654 static void
murrine_draw_top_glow(cairo_t * cr,const MurrineRGB * glow,int x,int y,int width,int height)655 murrine_draw_top_glow (cairo_t *cr,
656                        const MurrineRGB *glow,
657                        int x, int y, int width, int height)
658 {
659 	cairo_pattern_t *pat;
660 	double           scaling_factor = (double)1.2*width/height;
661 
662 	cairo_rectangle (cr, x, y, width, height);
663 	cairo_save (cr);
664 	cairo_scale (cr, scaling_factor, 1);
665 	pat = cairo_pattern_create_radial ((x+width/2.0)/scaling_factor, y, 0,
666 	                                   (x+width/2.0)/scaling_factor, y, height/2);
667 	murrine_pattern_add_color_stop_rgba (pat, 0.0, glow, 0.5);
668 	murrine_pattern_add_color_stop_rgba (pat, 1.0, glow, 0.0);
669 	cairo_set_source (cr, pat);
670 	cairo_pattern_destroy (pat);
671 	cairo_fill (cr);
672 	cairo_restore (cr);
673 }
674 
675 static void
murrine_draw_blur_glow(cairo_t * cr,const MurrineRGB * glow,int x,int y,int width,int height,int roundness,uint8 corners)676 murrine_draw_blur_glow (cairo_t *cr,
677                         const MurrineRGB *glow,
678                         int x, int y, int width, int height,
679                         int roundness, uint8 corners)
680 {
681 	raico_blur_t* blur = NULL;
682 	cairo_t *cr_surface;
683 	cairo_surface_t *surface;
684 	double bradius = 6;
685 
686 	/* draw glow */
687 	surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width+bradius*2, height+bradius*2);
688 	cr_surface = cairo_create (surface);
689 	blur = raico_blur_create (RAICO_BLUR_QUALITY_LOW);
690 	raico_blur_set_radius (blur, bradius);
691 	cairo_set_line_width (cr_surface, 4.0);
692 	murrine_rounded_rectangle_closed (cr_surface, bradius, bradius, width, height, roundness, corners);
693 	murrine_set_color_rgb (cr_surface, glow);
694 	cairo_stroke (cr_surface);
695 	raico_blur_apply (blur, surface);
696 	cairo_set_source_surface (cr, surface, -bradius+2, -bradius+2);
697 	cairo_paint (cr);
698 	cairo_surface_destroy (surface);
699 	cairo_destroy (cr_surface);
700 }
701 
702 static void
murrine_draw_lightborder(cairo_t * cr,const MurrineRGB * fill,MurrineGradients mrn_gradient,double x,double y,int width,int height,boolean gradients,int glazestyle,int lightborderstyle,double lightborder_shade,int radius,uint8 corners)703 murrine_draw_lightborder (cairo_t *cr,
704                           const MurrineRGB *fill,
705                           MurrineGradients mrn_gradient,
706                           double x, double y, int width, int height,
707                           boolean gradients,
708                           int glazestyle, int lightborderstyle,
709                           double lightborder_shade, int radius, uint8 corners)
710 {
711 	cairo_pattern_t *pat;
712 	MurrineRGB shade1, shade2, shade3, shade4;
713 	double alpha_value = mrn_gradient.use_rgba ? mrn_gradient.rgba_opacity : 1.0;
714 	double top_alpha, mid_alpha, bottom_alpha, lower_alpha;
715 	radius = MIN (radius, MIN ((double)width/2.0, (double)height/2.0));
716 
717 	if (mrn_gradient.has_gradient_colors)
718 	{
719 		murrine_shade (&mrn_gradient.gradient_colors[0], lightborder_shade*mrn_gradient.gradient_shades[0], &shade1);
720 		murrine_shade (&mrn_gradient.gradient_colors[1], lightborder_shade*mrn_gradient.gradient_shades[1], &shade2);
721 		murrine_shade (&mrn_gradient.gradient_colors[2], lightborder_shade*mrn_gradient.gradient_shades[2], &shade3);
722 		murrine_shade (&mrn_gradient.gradient_colors[3], lightborder_shade*mrn_gradient.gradient_shades[3], &shade4);
723 	}
724 	else
725 	{
726 		murrine_shade (fill, lightborder_shade*mrn_gradient.gradient_shades[0], &shade1);
727 		murrine_shade (fill, lightborder_shade*mrn_gradient.gradient_shades[1], &shade2);
728 		murrine_shade (fill, lightborder_shade*mrn_gradient.gradient_shades[2], &shade3);
729 		murrine_shade (fill, lightborder_shade*mrn_gradient.gradient_shades[3], &shade4);
730 	}
731 
732 	cairo_save (cr);
733 
734 	double fill_pos = 1.0-1.0/(double)height;
735 	if (corners == MRN_CORNER_ALL && radius > 2)
736 		fill_pos = 1.0-(((double)radius-1.0)/2.0)/(double)height;
737 
738 	radius < 2 ? cairo_rectangle (cr, x, y, width, height) :
739 	             clearlooks_rounded_rectangle (cr, x, y, width, height, radius-1, corners);
740 
741 	pat = cairo_pattern_create_linear (x, y, x, height+y);
742 
743 	switch (lightborderstyle)
744 	{
745 		default:
746 		case 0:
747 			top_alpha = mid_alpha = bottom_alpha = 0.5;
748 			lower_alpha = 0.0;
749 			break;
750 		case 1:
751 			top_alpha = mid_alpha = bottom_alpha = lower_alpha = 0.5;
752 			break;
753 		case 2:
754 			top_alpha = 0.5;
755 			mid_alpha = 0.3;
756 			bottom_alpha = 0.1;
757 			lower_alpha = 0.0;
758 			break;
759 		case 3:
760 			top_alpha = 0.5;
761 			mid_alpha = 0.3;
762 			bottom_alpha = 0.1;
763 			lower_alpha = 0.1;
764 			break;
765 	}
766 
767 	murrine_pattern_add_color_stop_rgba (pat, 0.00,     &shade1, top_alpha*alpha_value);
768 	murrine_pattern_add_color_stop_rgba (pat, 0.49,     &shade2, mid_alpha*alpha_value);
769 	murrine_pattern_add_color_stop_rgba (pat, 0.49,     &shade3, mid_alpha*alpha_value);
770 	murrine_pattern_add_color_stop_rgba (pat, fill_pos, &shade4, bottom_alpha*alpha_value);
771 	murrine_pattern_add_color_stop_rgba (pat, fill_pos, &shade4, lower_alpha*alpha_value);
772 	murrine_pattern_add_color_stop_rgba (pat, 1.00,     &shade4, lower_alpha*alpha_value);
773 	cairo_set_source (cr, pat);
774 	cairo_pattern_destroy (pat);
775 
776 	cairo_stroke (cr);
777 
778 	if (glazestyle == 2)
779 	{
780 		murrine_set_gradient (cr, fill, mrn_gradient, x, y, 0, height, mrn_gradient.gradients, FALSE);
781 		cairo_move_to (cr, width+x, y+0.5);
782 		cairo_line_to (cr, width+x, height+y);
783 		cairo_line_to (cr, x-0.5, height+y);
784 		cairo_stroke (cr);
785 	}
786 
787 	cairo_restore (cr);
788 }
789 
790 void
murrine_draw_glaze(cairo_t * cr,const MurrineRGB * fill,double glow_shade,double highlight_shade,double lightborder_shade,MurrineGradients mrn_gradient,const WidgetParameters * widget,int x,int y,int width,int height,int radius,uint8 corners,boolean horizontal)791 murrine_draw_glaze (cairo_t *cr,
792                     const MurrineRGB *fill,
793                     double glow_shade,
794                     double highlight_shade,
795                     double lightborder_shade,
796                     MurrineGradients mrn_gradient,
797                     const WidgetParameters *widget,
798                     int x, int y, int width, int height,
799                     int radius, uint8 corners, boolean horizontal)
800 {
801 	MurrineRGB highlight;
802 	murrine_shade (fill, highlight_shade, &highlight);
803 
804 	murrine_set_gradient (cr, fill, mrn_gradient, x, y, 0, height, mrn_gradient.gradients, FALSE);
805 	cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
806 	switch (widget->glazestyle)
807 	{
808 		default:
809 		case 0:
810 			cairo_fill (cr);
811 			murrine_draw_flat_highlight (cr, x, y, width, height);
812 			break;
813 		case 1:
814 			cairo_fill (cr);
815 			murrine_draw_curved_highlight (cr, x, y, width, height);
816 			break;
817 		case 2:
818 			cairo_fill_preserve (cr);
819 			murrine_draw_curved_highlight (cr, x, y, width, height);
820 			break;
821 		case 3:
822 		case 4:
823 			cairo_fill (cr);
824 			murrine_draw_curved_highlight_top (cr, x, y, width, height);
825 			break;
826 		case 5:
827 			cairo_fill (cr);
828 			murrine_draw_new_glossy_highlight (cr, x, y, width, height);
829 			break;
830 	}
831 	murrine_set_gradient (cr, &highlight, mrn_gradient, x, y, 0, height, mrn_gradient.gradients, TRUE);
832 	cairo_fill (cr);
833 	if (widget->glazestyle == 4)
834 	{
835 		MurrineRGB shadow;
836 		murrine_shade (fill, 1.0/highlight_shade, &shadow);
837 
838 		murrine_draw_curved_highlight_bottom (cr, x, y, width, height);
839 		murrine_set_gradient (cr, &shadow, mrn_gradient, x, y, 0, height, mrn_gradient.gradients, TRUE);
840 		cairo_fill (cr);
841 	}
842 
843 	if (glow_shade != 1.0)
844 	{
845 		MurrineRGB glow;
846 		murrine_shade (fill, glow_shade, &glow);
847 
848 		if (mrn_gradient.use_rgba)
849 			cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
850 
851 		switch (widget->glowstyle)
852 		{
853 			default:
854 			case 0:
855 				murrine_draw_top_glow (cr, &glow, x, y, width, height);
856 				break;
857 			case 1:
858 				murrine_draw_bottom_glow (cr, &glow, x, y, width, height);
859 				break;
860 			case 2:
861 				murrine_draw_top_glow (cr, &glow, x, y, width, height);
862 				murrine_draw_bottom_glow (cr, &glow, x, y, width, height);
863 				break;
864 			case 3:
865 				murrine_draw_horizontal_glow (cr, &glow, x, y, width, height);
866 				break;
867 			case 4:
868 				murrine_draw_centered_glow (cr, &glow, x, y, width, height);
869 				break;
870 			case 5:
871 				murrine_draw_blur_glow (cr, &glow, x, y, width, height, radius, corners);
872 				break;
873 		}
874 	}
875 
876 	if (widget->glazestyle != 4 && lightborder_shade != 1.0)
877 	{
878 		if (mrn_gradient.use_rgba)
879 			cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
880 
881 		murrine_draw_lightborder (cr, fill, mrn_gradient,
882 		                          x+0.5, y+0.5, width-1, height-1,
883 		                          mrn_gradient.gradients,
884 		                          widget->glazestyle, widget->lightborderstyle,
885 		                          lightborder_shade*highlight_shade, radius, corners);
886 	}
887 }
888 
889 void
murrine_set_gradient(cairo_t * cr,const MurrineRGB * color,MurrineGradients mrn_gradient,int x,int y,int width,int height,boolean gradients,boolean alpha)890 murrine_set_gradient (cairo_t *cr,
891                       const MurrineRGB *color,
892                       MurrineGradients mrn_gradient,
893                       int x, int y, int width, int height,
894                       boolean gradients, boolean alpha)
895 {
896 	double alpha_value = 1.0;
897 	if (mrn_gradient.use_rgba)
898 	{
899 		alpha_value = mrn_gradient.rgba_opacity;
900 	}
901 	else if (alpha)
902 	{
903 		alpha_value *= 0.8;
904 	}
905 
906 	if (mrn_gradient.has_gradient_colors)
907 	{
908 		cairo_pattern_t *pat;
909 		MurrineRGB shade1, shade2, shade3, shade4;
910 
911 		murrine_shade (&mrn_gradient.gradient_colors[0], mrn_gradient.gradient_shades[0], &shade1);
912 		murrine_shade (&mrn_gradient.gradient_colors[1], mrn_gradient.gradient_shades[1], &shade2);
913 		murrine_shade (&mrn_gradient.gradient_colors[2], mrn_gradient.gradient_shades[2], &shade3);
914 		murrine_shade (&mrn_gradient.gradient_colors[3], mrn_gradient.gradient_shades[3], &shade4);
915 
916 		pat = cairo_pattern_create_linear (x, y, width+x, height+y);
917 
918 		murrine_pattern_add_color_stop_rgba (pat, 0.00, &shade1, alpha_value);
919 		murrine_pattern_add_color_stop_rgba (pat, 0.49, &shade2, alpha_value);
920 		murrine_pattern_add_color_stop_rgba (pat, 0.49, &shade3, alpha_value);
921 		murrine_pattern_add_color_stop_rgba (pat, 1.00, &shade4, alpha_value);
922 
923 		cairo_set_source (cr, pat);
924 		cairo_pattern_destroy (pat);
925 	}
926 	else if (gradients)
927 	{
928 		cairo_pattern_t *pat;
929 		MurrineRGB shade1, shade2, shade3, shade4;
930 
931 		murrine_shade (color, mrn_gradient.gradient_shades[0], &shade1);
932 		murrine_shade (color, mrn_gradient.gradient_shades[1], &shade2);
933 		murrine_shade (color, mrn_gradient.gradient_shades[2], &shade3);
934 		murrine_shade (color, mrn_gradient.gradient_shades[3], &shade4);
935 
936 		pat = cairo_pattern_create_linear (x, y, width+x, height+y);
937 
938 		murrine_pattern_add_color_stop_rgba (pat, 0.00, &shade1, alpha_value);
939 		murrine_pattern_add_color_stop_rgba (pat, 0.49, &shade2, alpha_value);
940 		murrine_pattern_add_color_stop_rgba (pat, 0.49, &shade3, alpha_value);
941 		murrine_pattern_add_color_stop_rgba (pat, 1.00, &shade4, alpha_value);
942 
943 		cairo_set_source (cr, pat);
944 		cairo_pattern_destroy (pat);
945 	}
946 	else
947 	{
948 		murrine_set_color_rgba (cr, color, alpha_value);
949 	}
950 }
951 
952 void
murrine_draw_border_from_path(cairo_t * cr,const MurrineRGB * color,double x,double y,double width,double height,MurrineGradients mrn_gradient,double alpha)953 murrine_draw_border_from_path (cairo_t *cr,
954                                const MurrineRGB  *color,
955                                double x, double y, double width, double height,
956                                MurrineGradients mrn_gradient, double alpha)
957 {
958 	if (mrn_gradient.has_border_colors)
959 	{
960 		cairo_pattern_t *pat;
961 		MurrineRGB shade1, shade2;
962 
963 		murrine_shade (&mrn_gradient.border_colors[0], mrn_gradient.border_shades[0], &shade1);
964 		murrine_shade (&mrn_gradient.border_colors[1], mrn_gradient.border_shades[1], &shade2);
965 
966 		pat = cairo_pattern_create_linear (x, y, x, height+y);
967 		murrine_pattern_add_color_stop_rgba (pat, 0.00, &shade1, alpha);
968 		murrine_pattern_add_color_stop_rgba (pat, 1.00, &shade2, alpha);
969 
970 		cairo_set_source (cr, pat);
971 		cairo_pattern_destroy (pat);
972 	}
973 	else if (mrn_gradient.border_shades[0] != 1.0 ||
974 	         mrn_gradient.border_shades[1] != 1.0) // improve
975 	{
976 		cairo_pattern_t *pat;
977 		MurrineRGB shade1, shade2;
978 
979 		murrine_shade (color, mrn_gradient.border_shades[0], &shade1);
980 		murrine_shade (color, mrn_gradient.border_shades[1], &shade2);
981 
982 		pat = cairo_pattern_create_linear (x, y, x, height+y);
983 		murrine_pattern_add_color_stop_rgba (pat, 0.00, &shade1, alpha);
984 		murrine_pattern_add_color_stop_rgba (pat, 1.00, &shade2, alpha);
985 
986 		cairo_set_source (cr, pat);
987 		cairo_pattern_destroy (pat);
988 	}
989 	else
990 		murrine_set_color_rgba (cr, color, alpha);
991 
992 	cairo_stroke (cr);
993 }
994 
995 void
murrine_draw_border(cairo_t * cr,const MurrineRGB * color,double x,double y,double width,double height,int roundness,uint8 corners,MurrineGradients mrn_gradient,double alpha)996 murrine_draw_border (cairo_t *cr,
997                      const MurrineRGB  *color,
998                      double x, double y, double width, double height,
999                      int roundness, uint8 corners,
1000                      MurrineGradients mrn_gradient, double alpha)
1001 {
1002 	murrine_rounded_rectangle (cr, x, y, width, height, roundness, corners);
1003 	murrine_draw_border_from_path (cr, color, x, y, width, height, mrn_gradient, alpha);
1004 }
1005 
1006 void
murrine_draw_shadow_from_path(cairo_t * cr,const MurrineRGB * color,double x,double y,double width,double height,int reliefstyle,MurrineGradients mrn_gradient,double alpha)1007 murrine_draw_shadow_from_path (cairo_t *cr,
1008                                const MurrineRGB  *color,
1009                                double x, double y, double width, double height,
1010                                int reliefstyle,
1011                                MurrineGradients mrn_gradient, double alpha)
1012 {
1013 	if (mrn_gradient.shadow_shades[0] != 1.0 ||
1014 	    mrn_gradient.shadow_shades[1] != 1.0 ||
1015 	    reliefstyle > 2) // improve
1016 	{
1017 		cairo_pattern_t *pat;
1018 		MurrineRGB shade1, shade2;
1019 
1020 		murrine_shade (color, mrn_gradient.shadow_shades[0], &shade1);
1021 		murrine_shade (color, mrn_gradient.shadow_shades[1], &shade2);
1022 
1023 		pat = cairo_pattern_create_linear (x, y, x, height+y);
1024 		murrine_pattern_add_color_stop_rgba (pat, 0.00, &shade1, reliefstyle == 3 ? 0.5*alpha : alpha);
1025 		murrine_pattern_add_color_stop_rgba (pat, 1.00, &shade2, reliefstyle >= 3 && reliefstyle != 5 ? 2.0*alpha : alpha);
1026 
1027 		cairo_set_source (cr, pat);
1028 		cairo_pattern_destroy (pat);
1029 	}
1030 	else
1031 		murrine_set_color_rgba (cr, color, alpha);
1032 
1033 	cairo_stroke (cr);
1034 }
1035 
1036 void
murrine_draw_shadow(cairo_t * cr,const MurrineRGB * color,double x,double y,double width,double height,int roundness,uint8 corners,int reliefstyle,MurrineGradients mrn_gradient,double alpha)1037 murrine_draw_shadow (cairo_t *cr,
1038                      const MurrineRGB  *color,
1039                      double x, double y, double width, double height,
1040                      int roundness, uint8 corners,
1041                      int reliefstyle,
1042                      MurrineGradients mrn_gradient, double alpha)
1043 {
1044 	murrine_rounded_rectangle (cr, x, y, width, height, roundness, corners);
1045 	murrine_draw_shadow_from_path (cr, color, x, y, width, height, reliefstyle, mrn_gradient, alpha);
1046 }
1047 
1048 void
murrine_draw_trough_from_path(cairo_t * cr,const MurrineRGB * color,double x,double y,double width,double height,MurrineGradients mrn_gradient,double alpha,boolean horizontal)1049 murrine_draw_trough_from_path (cairo_t *cr,
1050                                const MurrineRGB  *color,
1051                                double x, double y, double width, double height,
1052                                MurrineGradients mrn_gradient, double alpha,
1053                                boolean horizontal)
1054 {
1055 	if (mrn_gradient.trough_shades[0] != 1.0 ||
1056 	    mrn_gradient.trough_shades[1] != 1.0) // improve
1057 	{
1058 		cairo_pattern_t *pat;
1059 		MurrineRGB shade1, shade2;
1060 
1061 		murrine_shade (color, mrn_gradient.trough_shades[0], &shade1);
1062 		murrine_shade (color, mrn_gradient.trough_shades[1], &shade2);
1063 
1064 		pat = cairo_pattern_create_linear (x, y, horizontal ? x : width+x, horizontal ? height+y : y);
1065 		murrine_pattern_add_color_stop_rgba (pat, 0.00, &shade1, alpha);
1066 		murrine_pattern_add_color_stop_rgba (pat, 1.00, &shade2, alpha);
1067 
1068 		cairo_set_source (cr, pat);
1069 		cairo_pattern_destroy (pat);
1070 	}
1071 	else
1072 		murrine_set_color_rgba (cr, color, alpha);
1073 
1074 	cairo_fill (cr);
1075 }
1076 
1077 void
murrine_draw_trough(cairo_t * cr,const MurrineRGB * color,double x,double y,double width,double height,int roundness,uint8 corners,MurrineGradients mrn_gradient,double alpha,boolean horizontal)1078 murrine_draw_trough (cairo_t *cr,
1079                      const MurrineRGB  *color,
1080                      double x, double y, double width, double height,
1081                      int roundness, uint8 corners,
1082                      MurrineGradients mrn_gradient, double alpha,
1083                      boolean horizontal)
1084 {
1085 	murrine_rounded_rectangle_closed (cr, x, y, width, height, roundness, corners);
1086 	murrine_draw_trough_from_path (cr, color, x, y, width, height, mrn_gradient, alpha, horizontal);
1087 }
1088 
1089 void
murrine_draw_trough_border_from_path(cairo_t * cr,const MurrineRGB * color,double x,double y,double width,double height,MurrineGradients mrn_gradient,double alpha,boolean horizontal)1090 murrine_draw_trough_border_from_path (cairo_t *cr,
1091                                       const MurrineRGB  *color,
1092                                       double x, double y, double width, double height,
1093                                       MurrineGradients mrn_gradient, double alpha,
1094                                       boolean horizontal)
1095 {
1096 	if (mrn_gradient.trough_border_shades[0] != 1.0 ||
1097 	    mrn_gradient.trough_border_shades[1] != 1.0 ||
1098 	    mrn_gradient.trough_shades[0] != 1.0 ||
1099 	    mrn_gradient.trough_shades[1] != 1.0) // improve
1100 	{
1101 		cairo_pattern_t *pat;
1102 		MurrineRGB shade1, shade2;
1103 
1104 		murrine_shade (color, mrn_gradient.trough_shades[0]*mrn_gradient.trough_border_shades[0], &shade1);
1105 		murrine_shade (color, mrn_gradient.trough_shades[1]*mrn_gradient.trough_border_shades[1], &shade2);
1106 
1107 		pat = cairo_pattern_create_linear (x, y, horizontal ? x : width+x, horizontal ? height+y : y);
1108 		murrine_pattern_add_color_stop_rgba (pat, 0.00, &shade1, alpha);
1109 		murrine_pattern_add_color_stop_rgba (pat, 1.00, &shade2, alpha);
1110 
1111 		cairo_set_source (cr, pat);
1112 		cairo_pattern_destroy (pat);
1113 	}
1114 	else
1115 		murrine_set_color_rgba (cr, color, alpha);
1116 
1117 	cairo_stroke (cr);
1118 }
1119 
1120 void
murrine_draw_trough_border(cairo_t * cr,const MurrineRGB * color,double x,double y,double width,double height,int roundness,uint8 corners,MurrineGradients mrn_gradient,double alpha,boolean horizontal)1121 murrine_draw_trough_border (cairo_t *cr,
1122                             const MurrineRGB  *color,
1123                             double x, double y, double width, double height,
1124                             int roundness, uint8 corners,
1125                             MurrineGradients mrn_gradient, double alpha,
1126                             boolean horizontal)
1127 {
1128 	murrine_rounded_rectangle (cr, x, y, width, height, roundness, corners);
1129 	murrine_draw_trough_border_from_path (cr, color, x, y, width, height, mrn_gradient, alpha, horizontal);
1130 }
1131 
1132 void
rotate_mirror_translate(cairo_t * cr,double radius,double x,double y,boolean mirror_horizontally,boolean mirror_vertically)1133 rotate_mirror_translate (cairo_t *cr,
1134                          double radius, double x, double y,
1135                          boolean mirror_horizontally, boolean mirror_vertically)
1136 {
1137 	cairo_matrix_t matrix_rotate;
1138 	cairo_matrix_t matrix_mirror;
1139 	cairo_matrix_t matrix_result;
1140 
1141 	double r_cos = cos(radius);
1142 	double r_sin = sin(radius);
1143 
1144 	cairo_matrix_init (&matrix_rotate, r_cos, r_sin, r_sin, r_cos, x, y);
1145 
1146 	cairo_matrix_init (&matrix_mirror,
1147 	                   mirror_horizontally ? -1 : 1, 0, 0,
1148 	                   mirror_vertically ? -1 : 1, 0, 0);
1149 
1150 	cairo_matrix_multiply (&matrix_result, &matrix_mirror, &matrix_rotate);
1151 
1152 	cairo_set_matrix (cr, &matrix_result);
1153 }
1154 
1155 void
murrine_exchange_axis(cairo_t * cr,gint * x,gint * y,gint * width,gint * height)1156 murrine_exchange_axis (cairo_t  *cr,
1157                        gint     *x,
1158                        gint     *y,
1159                        gint     *width,
1160                        gint     *height)
1161 {
1162 	gint tmp;
1163 	cairo_matrix_t matrix;
1164 
1165 	cairo_translate (cr, *x, *y);
1166 	cairo_matrix_init (&matrix, 0, 1, 1, 0, 0, 0);
1167 
1168 	cairo_transform (cr, &matrix);
1169 
1170 	/* swap width/height */
1171 	tmp = *width;
1172 	*x = 0;
1173 	*y = 0;
1174 	*width = *height;
1175 	*height = tmp;
1176 }
1177 
1178 void
murrine_get_fill_color(MurrineRGB * color,const MurrineGradients * mrn_gradient)1179 murrine_get_fill_color (MurrineRGB *color,
1180                         const MurrineGradients *mrn_gradient)
1181 {
1182 	if (mrn_gradient->has_gradient_colors)
1183 	{
1184 		murrine_mix_color (&mrn_gradient->gradient_colors[1],
1185 		                   &mrn_gradient->gradient_colors[2],
1186 		                   0.5, color);
1187 	}
1188 }
1189 
1190 double
murrine_get_decreased_shade(double old,double factor)1191 murrine_get_decreased_shade (double old, double factor)
1192 {
1193 	if (old > 1.0)
1194 		return ((old-1.0)/factor+1.0);
1195 	else if (old < 1.0)
1196 		return (1.0-(1.0-old)/factor);
1197 
1198 	return old;
1199 }
1200 
1201 double
murrine_get_increased_shade(double old,double factor)1202 murrine_get_increased_shade (double old, double factor)
1203 {
1204 	if (old > 1.0)
1205 		return ((old-1.0)*factor+1.0);
1206 	else if (old < 1.0)
1207 		return (1.0-(1.0-old)*factor);
1208 
1209 	return old;
1210 }
1211 
1212 double
murrine_get_contrast(double old,double factor)1213 murrine_get_contrast (double old, double factor)
1214 {
1215 	if (factor == 1.0)
1216 		return old;
1217 
1218 	if (factor < 1.0)
1219 	{
1220 		if (old < 1.0)
1221 			return old+(1.0-old)*(1.0-factor);
1222 		else
1223 			return old-(old-1.0)*(1.0-factor);
1224 	}
1225 	else
1226 	{
1227 		if (old < 1.0)
1228 			return old-old*(factor-1.0);
1229 		else
1230 			return old+(old-1.0)*(factor-1.0);
1231 	}
1232 }
1233 
1234 double
murrine_get_inverted_shade(double old)1235 murrine_get_inverted_shade (double old)
1236 {
1237 	if (old == 1.0)
1238 		return old;
1239 
1240 	return CLAMP (2.0-old, 0.0, 2.0);
1241 }
1242 
1243 MurrineGradients
murrine_get_inverted_border_shades(MurrineGradients mrn_gradient)1244 murrine_get_inverted_border_shades (MurrineGradients mrn_gradient)
1245 {
1246 	MurrineGradients mrn_gradient_new = mrn_gradient;
1247 
1248 	mrn_gradient_new.border_shades[0] = mrn_gradient.border_shades[1];
1249 	mrn_gradient_new.border_shades[1] = mrn_gradient.border_shades[0];
1250 
1251 	return mrn_gradient_new;
1252 }
1253 
1254 MurrineGradients
murrine_get_decreased_gradient_shades(MurrineGradients mrn_gradient,double factor)1255 murrine_get_decreased_gradient_shades (MurrineGradients mrn_gradient, double factor)
1256 {
1257 	MurrineGradients mrn_gradient_new = mrn_gradient;
1258 
1259 	mrn_gradient_new.gradient_shades[0] = murrine_get_decreased_shade (mrn_gradient.gradient_shades[0], factor);
1260 	mrn_gradient_new.gradient_shades[1] = murrine_get_decreased_shade (mrn_gradient.gradient_shades[1], factor);
1261 	mrn_gradient_new.gradient_shades[2] = murrine_get_decreased_shade (mrn_gradient.gradient_shades[2], factor);
1262 	mrn_gradient_new.gradient_shades[3] = murrine_get_decreased_shade (mrn_gradient.gradient_shades[3], factor);
1263 
1264 	return mrn_gradient_new;
1265 }
1266