comparison src/aosd/aosd_style.c @ 569:d401f87f89f7 trunk

[svn] - added Audacious OSD, yet-another-written-from-scratch plugin to display OSD, based on Ghosd library; currently untied from configure, to compile it you have to run make in its directory; will be added to configure after some testing
author giacomo
date Mon, 29 Jan 2007 06:40:04 -0800
parents
children 7ad870f10241
comparison
equal deleted inserted replaced
568:8c64b5abdcda 569:d401f87f89f7
1 /*
2 *
3 * Author: Giacomo Lozito <james@develia.org>, (C) 2005-2007
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 *
19 */
20
21 #include "aosd_style.h"
22 #include "aosd_style_private.h"
23 #include "aosd_cfg.h"
24 #include <glib.h>
25 #include <glib/gi18n.h>
26 #include <X11/Xlib.h>
27 #include <cairo/cairo.h>
28 #include <pango/pangocairo.h>
29 #include "ghosd.h"
30 #include "ghosd-text.h"
31
32
33 /* HOW TO ADD A NEW DECORATION STYLE
34 --------------------------------------------------------------------------
35 First, add a new decoration style code; then, provide the decoration style
36 information by adding a new entry in the aosd_deco_styles[] array (name,
37 render function, etc.); add the new decoration style code in the array
38 of decoration style codes, and update the define containing the array size.
39 The render function uses three parameters; the Ghosd instance, the cairo
40 object you use to draw, and a aosd_deco_style_data_t object that contains
41 user-defined options (look into aosd_style.h and aosd_cfg.h for details).
42 Have fun! :)
43 */
44
45
46 /* decoration style codes ( the code values do not need to be sequential ) */
47 enum
48 {
49 AOSD_DECO_STYLE_RECT = 0,
50 AOSD_DECO_STYLE_ROUNDRECT = 1,
51 AOSD_DECO_STYLE_CONCAVERECT = 2
52 };
53
54 /* decoration style codes array size */
55 #define AOSD_DECO_STYLE_CODES_ARRAY_SIZE 3
56
57 /* decoration style codes array */
58 gint aosd_deco_style_codes[] =
59 {
60 AOSD_DECO_STYLE_RECT,
61 AOSD_DECO_STYLE_ROUNDRECT,
62 AOSD_DECO_STYLE_CONCAVERECT
63 };
64
65 /* prototypes of render functions */
66 static void aosd_deco_rfunc_rect ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
67 static void aosd_deco_rfunc_roundrect ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
68 static void aosd_deco_rfunc_concaverect ( Ghosd * , cairo_t * , aosd_deco_style_data_t * );
69
70 /* map decoration style codes to decoration objects */
71 aosd_deco_style_t aosd_deco_styles[] =
72 {
73 [AOSD_DECO_STYLE_RECT] = { N_("Rectangle") ,
74 aosd_deco_rfunc_rect ,
75 2 , { 10 , 10 , 10 , 10 } },
76
77 [AOSD_DECO_STYLE_ROUNDRECT] = { N_("Rounded Rectangle") ,
78 aosd_deco_rfunc_roundrect ,
79 2 , { 10 , 10 , 10 , 10 } },
80
81 [AOSD_DECO_STYLE_CONCAVERECT] = { N_("Concave Rectangle") ,
82 aosd_deco_rfunc_concaverect ,
83 2 , { 10 , 10 , 10 , 10 } }
84 };
85
86
87
88 /* DECORATION STYLE API */
89
90
91 void
92 aosd_deco_style_get_codes_array ( gint ** array , gint * array_size )
93 {
94 *array = aosd_deco_style_codes;
95 *array_size = AOSD_DECO_STYLE_CODES_ARRAY_SIZE;
96 return;
97 }
98
99
100 void
101 aosd_deco_style_get_padding ( gint deco_code ,
102 gint * ptop , gint * pbottom ,
103 gint * pleft , gint * pright )
104 {
105 if ( ptop != NULL ) *ptop = aosd_deco_styles[deco_code].padding.top;
106 if ( pbottom != NULL ) *pbottom = aosd_deco_styles[deco_code].padding.bottom;
107 if ( pleft != NULL ) *pleft = aosd_deco_styles[deco_code].padding.left;
108 if ( pright != NULL ) *pright = aosd_deco_styles[deco_code].padding.right;
109 return;
110 }
111
112
113 const gchar *
114 aosd_deco_style_get_desc ( gint deco_code )
115 {
116 return aosd_deco_styles[deco_code].desc;
117 }
118
119
120 gint
121 aosd_deco_style_get_numcol ( gint deco_code )
122 {
123 return aosd_deco_styles[deco_code].colors_num;
124 }
125
126
127 void
128 aosd_deco_style_render ( gint deco_code , gpointer ghosd , gpointer cr , gpointer user_data )
129 {
130 aosd_deco_styles[deco_code].render_func( (Ghosd*)ghosd , (cairo_t*)cr , user_data );
131 }
132
133
134 gint
135 aosd_deco_style_get_first_code ( void )
136 {
137 return AOSD_DECO_STYLE_RECT;
138 }
139
140
141 gint
142 aosd_deco_style_get_max_numcol ( void )
143 {
144 gint i = 0;
145 gint max_numcol = 0;
146
147 for ( i = 0 ; i < AOSD_DECO_STYLE_CODES_ARRAY_SIZE ; i++ )
148 {
149 gint numcol = aosd_deco_style_get_numcol( aosd_deco_style_codes[i] );
150 if ( numcol > max_numcol )
151 max_numcol = numcol;
152 }
153
154 return max_numcol;
155 }
156
157
158
159 /* RENDER FUNCTIONS */
160
161 static void
162 aosd_deco_rfunc_rect( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
163 {
164 /* decoration information
165 ----------------------
166 draws a simple rectangular decoration; uses 2 colors
167 (user color 1 and 2) and 1 font (user font 1), with optional shadow
168 */
169 PangoLayout *osd_layout = data->layout;
170 aosd_color_t color0 = g_array_index( data->decoration->colors , aosd_color_t , 0 );
171 aosd_color_t color1 = g_array_index( data->decoration->colors , aosd_color_t , 1 );
172 aosd_color_t textcolor0 = data->text->fonts_color[0];
173 aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
174 gboolean draw_shadow = data->text->fonts_draw_shadow[0];
175 gint width = 0, height = 0;
176
177 pango_layout_get_pixel_size( osd_layout , &width , &height );
178
179 /* draw rectangle container */
180 cairo_set_source_rgba( cr , (gdouble)color0.red / 65535 , (gdouble)color0.green / 65535 ,
181 (gdouble)color0.blue / 65535 , (gdouble)color0.alpha / 65535 );
182 cairo_rectangle( cr , 0 , 0 ,
183 aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left + width +
184 aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.right,
185 aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top + height +
186 aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.bottom );
187 cairo_fill_preserve( cr );
188 cairo_set_source_rgba( cr , (gdouble)color1.red / 65535 , (gdouble)color1.green / 65535 ,
189 (gdouble)color1.blue / 65535 , (gdouble)color1.alpha / 65535 );
190 cairo_stroke( cr );
191
192 if ( draw_shadow == TRUE )
193 {
194 /* draw text shadow */
195 cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
196 (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
197 cairo_move_to( cr,
198 aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left + 2 ,
199 aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top + 2 );
200 pango_cairo_show_layout( cr , osd_layout );
201 }
202
203 /* draw text */
204 cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
205 (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
206 cairo_move_to( cr,
207 aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.left ,
208 aosd_deco_styles[AOSD_DECO_STYLE_RECT].padding.top );
209 pango_cairo_show_layout( cr , osd_layout );
210 }
211
212
213 static void
214 aosd_deco_rfunc_roundrect ( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
215 {
216 /* decoration information
217 ----------------------
218 draws a rectangular decoration with rounded angles; uses 2 colors
219 (user color 1 and 2) and 1 font (user font 1), with optional shadow
220 */
221 PangoLayout *osd_layout = data->layout;
222 aosd_color_t color0 = g_array_index( data->decoration->colors , aosd_color_t , 0 );
223 aosd_color_t color1 = g_array_index( data->decoration->colors , aosd_color_t , 1 );
224 aosd_color_t textcolor0 = data->text->fonts_color[0];
225 aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
226 gboolean draw_shadow = data->text->fonts_draw_shadow[0];
227 gint width = 0, height = 0;
228
229 pango_layout_get_pixel_size( osd_layout , &width , &height );
230
231 /* draw rounded-rectangle container */
232 cairo_set_source_rgba( cr , (gdouble)color0.red / 65535 , (gdouble)color0.green / 65535 ,
233 (gdouble)color0.blue / 65535 , (gdouble)color0.alpha / 65535 );
234 cairo_move_to( cr , aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left , 0 );
235 cairo_arc( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
236 aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top ,
237 10. , -G_PI_2 , 0. );
238 cairo_arc( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
239 aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top + height ,
240 10. , -4. * G_PI_2 , -3. * G_PI_2 );
241 cairo_arc( cr , aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
242 aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top + height ,
243 10. , -3. * G_PI_2 , -2. * G_PI_2 );
244 cairo_arc( cr , aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
245 aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top ,
246 10. , -2. * G_PI_2 , -G_PI_2 );
247 cairo_close_path( cr );
248 cairo_fill_preserve( cr );
249 cairo_set_source_rgba( cr , (gdouble)color1.red / 65535 , (gdouble)color1.green / 65535 ,
250 (gdouble)color1.blue / 65535 , (gdouble)color1.alpha / 65535 );
251 cairo_stroke( cr );
252
253 if ( draw_shadow == TRUE )
254 {
255 /* draw text shadow */
256 cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
257 (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
258 cairo_move_to( cr ,
259 aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left + 2 ,
260 aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top + 2 );
261 pango_cairo_show_layout( cr , osd_layout );
262 }
263
264 /* draw text */
265 cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
266 (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
267 cairo_move_to( cr ,
268 aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.left ,
269 aosd_deco_styles[AOSD_DECO_STYLE_ROUNDRECT].padding.top );
270 pango_cairo_show_layout( cr , osd_layout );
271 }
272
273
274 static void
275 aosd_deco_rfunc_concaverect ( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data )
276 {
277 /* decoration information
278 ----------------------
279 draws a rectangle with concave angles; uses 2 colors
280 (user color 1 and 2) and 1 font (user font 1), with optional shadow
281 */
282 PangoLayout *osd_layout = data->layout;
283 aosd_color_t color0 = g_array_index( data->decoration->colors , aosd_color_t , 0 );
284 aosd_color_t color1 = g_array_index( data->decoration->colors , aosd_color_t , 1 );
285 aosd_color_t textcolor0 = data->text->fonts_color[0];
286 aosd_color_t shadowcolor0 = data->text->fonts_shadow_color[0];
287 gboolean draw_shadow = data->text->fonts_draw_shadow[0];
288 gint width = 0, height = 0;
289
290 pango_layout_get_pixel_size( osd_layout , &width , &height );
291
292 /* draw jigsaw-piece-like container */
293 cairo_set_source_rgba( cr , (gdouble)color0.red / 65535 , (gdouble)color0.green / 65535 ,
294 (gdouble)color0.blue / 65535 , (gdouble)color0.alpha / 65535 );
295 cairo_move_to( cr , aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left , 0 );
296 cairo_arc_negative( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + 2 ,
297 aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top - 2 ,
298 8. , -G_PI_2 , 0. );
299 cairo_arc_negative( cr , width + aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + 2 ,
300 aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top + height + 2 ,
301 8. , -4. * G_PI_2 , -3. * G_PI_2 );
302 cairo_arc_negative( cr , aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left - 2 ,
303 aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top + height + 2 ,
304 8. , -3. * G_PI_2 , -2. * G_PI_2 );
305 cairo_arc_negative( cr , aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left - 2 ,
306 aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top - 2 ,
307 8. , -2. * G_PI_2 , -G_PI_2 );
308 cairo_close_path( cr );
309 cairo_fill_preserve( cr );
310 cairo_set_source_rgba( cr , (gdouble)color1.red / 65535 , (gdouble)color1.green / 65535 ,
311 (gdouble)color1.blue / 65535 , (gdouble)color1.alpha / 65535 );
312 cairo_stroke( cr );
313
314 if ( draw_shadow == TRUE )
315 {
316 /* draw text shadow */
317 cairo_set_source_rgba( cr , (gdouble)shadowcolor0.red / 65535 , (gdouble)shadowcolor0.green / 65535 ,
318 (gdouble)shadowcolor0.blue / 65535 , (gdouble)shadowcolor0.alpha / 65535 );
319 cairo_move_to( cr ,
320 aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left + 2 ,
321 aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top + 2 );
322 pango_cairo_show_layout( cr , osd_layout );
323 }
324
325 /* draw text */
326 cairo_set_source_rgba( cr , (gdouble)textcolor0.red / 65535 , (gdouble)textcolor0.green / 65535 ,
327 (gdouble)textcolor0.blue / 65535 , (gdouble)textcolor0.alpha / 65535 );
328 cairo_move_to( cr ,
329 aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.left ,
330 aosd_deco_styles[AOSD_DECO_STYLE_CONCAVERECT].padding.top );
331 pango_cairo_show_layout( cr , osd_layout );
332 }