1 /* The Unico Theming Engine for Gtk+.
2  * Copyright (C) 2011 Canonical Ltd
3  *
4  * This library is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * version 2.1 as published by the Free Software Foundation.
7  *
8  * This library is distributed  in the hope that it will be useful,
9  * but  WITHOUT ANY WARRANTY; without even  the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11  * Lesser General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public
14  * License  along  with  this library;  if not,  write to  the Free
15  * Software Foundation, Inc., 51  Franklin St, Fifth Floor, Boston,
16  * MA 02110-1301, USA.
17  *
18  * Authored by Andrea Cimitan <andrea.cimitan@canonical.com>
19  *
20  */
21 
22 #include <cairo.h>
23 #include <gtk/gtk.h>
24 
25 #include "unico-cairo-support.h"
26 #include "unico-support.h"
27 #include "unico-types.h"
28 
29 void
unico_cairo_round_rect(cairo_t * cr,gdouble x,gdouble y,gdouble width,gdouble height,gint radius,guint sides,GtkJunctionSides junction)30 unico_cairo_round_rect (cairo_t         *cr,
31                         gdouble          x,
32                         gdouble          y,
33                         gdouble          width,
34                         gdouble          height,
35                         gint             radius,
36                         guint            sides,
37                         GtkJunctionSides junction)
38 {
39   radius = CLAMP (radius, 0, MIN (width / 2, height / 2));
40 
41   if (sides & SIDE_RIGHT)
42     {
43       if (radius == 0 ||
44           (junction & GTK_JUNCTION_CORNER_TOPRIGHT))
45         cairo_move_to (cr, x + width, y);
46       else
47         {
48           cairo_new_sub_path (cr);
49 
50           cairo_arc (cr, x + width - radius, y + radius, radius, - G_PI / 4, 0);
51         }
52 
53       if (radius == 0 ||
54           (junction & GTK_JUNCTION_CORNER_BOTTOMRIGHT))
55         cairo_line_to (cr, x + width, y + height);
56       else
57         cairo_arc (cr, x + width - radius, y + height - radius, radius, 0, G_PI / 4);
58     }
59 
60   if (sides & SIDE_BOTTOM)
61     {
62       if (radius != 0 &&
63           ! (junction & GTK_JUNCTION_CORNER_BOTTOMRIGHT))
64         {
65           if ((sides & SIDE_RIGHT) == 0)
66             cairo_new_sub_path (cr);
67 
68           cairo_arc (cr, x + width - radius, y + height - radius, radius, G_PI / 4, G_PI / 2);
69         }
70       else if ((sides & SIDE_RIGHT) == 0)
71         cairo_move_to (cr, x + width, y + height);
72 
73       if (radius == 0 ||
74           (junction & GTK_JUNCTION_CORNER_BOTTOMLEFT))
75         cairo_line_to (cr, x, y + height);
76       else
77         cairo_arc (cr, x + radius, y + height - radius, radius, G_PI / 2, 3 * (G_PI / 4));
78     }
79   else
80     cairo_move_to (cr, x, y + height);
81 
82   if (sides & SIDE_LEFT)
83     {
84       if (radius != 0 &&
85           ! (junction & GTK_JUNCTION_CORNER_BOTTOMLEFT))
86         {
87           if ((sides & SIDE_BOTTOM) == 0)
88             cairo_new_sub_path (cr);
89 
90           cairo_arc (cr, x + radius, y + height - radius, radius, 3 * (G_PI / 4), G_PI);
91         }
92       else if ((sides & SIDE_BOTTOM) == 0)
93         cairo_move_to (cr, x, y + height);
94 
95       if (radius == 0 ||
96           (junction & GTK_JUNCTION_CORNER_TOPLEFT))
97         cairo_line_to (cr, x, y);
98       else
99         cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI + G_PI / 4);
100     }
101 
102   if (sides & SIDE_TOP)
103     {
104       if (radius != 0 &&
105           ! (junction & GTK_JUNCTION_CORNER_TOPLEFT))
106         {
107           if ((sides & SIDE_LEFT) == 0)
108             cairo_new_sub_path (cr);
109 
110           cairo_arc (cr, x + radius, y + radius, radius, 5 * (G_PI / 4), 3 * (G_PI / 2));
111         }
112       else if ((sides & SIDE_LEFT) == 0)
113         cairo_move_to (cr, x, y);
114 
115       if (radius == 0 ||
116           (junction & GTK_JUNCTION_CORNER_TOPRIGHT))
117         cairo_line_to (cr, x + width, y);
118       else
119         cairo_arc (cr, x + width - radius, y + radius, radius, 3 * (G_PI / 2), - G_PI / 4);
120     }
121 }
122 
123 void
unico_cairo_round_rect_inner(cairo_t * cr,gdouble x,gdouble y,gdouble width,gdouble height,gint radius,guint sides,GtkJunctionSides junction)124 unico_cairo_round_rect_inner (cairo_t         *cr,
125                               gdouble          x,
126                               gdouble          y,
127                               gdouble          width,
128                               gdouble          height,
129                               gint             radius,
130                               guint            sides,
131                               GtkJunctionSides junction)
132 {
133   gdouble line_width;
134 
135   line_width = cairo_get_line_width (cr);
136 
137   /* center the rounded rectangle using line_width */
138   unico_cairo_round_rect (cr, x + line_width / 2.0,
139                           y + line_width / 2.0,
140                           width - line_width,
141                           height - line_width,
142                           radius, sides, junction);
143 }
144