2 * draw.c - draw functions
4 * Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include <cairo-xlib.h>
27 #include "common/util.h"
29 /** Get a draw context
30 * \param phys_screen physical screen id
32 * \param height height
33 * \return draw context ref
36 draw_context_new(Display
*disp
, int phys_screen
, int width
, int height
, Drawable dw
)
38 DrawCtx
*d
= p_new(DrawCtx
, 1);
41 d
->phys_screen
= phys_screen
;
44 d
->depth
= DefaultDepth(disp
, phys_screen
);
45 d
->visual
= DefaultVisual(disp
, phys_screen
);
51 /** Draw text into a draw context
56 * \param align alignment
57 * \param padding padding to add before drawing the text
58 * \param font font to use
59 * \param text text to draw
60 * \param fg foreground color
61 * \param bg background color
64 draw_text(DrawCtx
*ctx
,
68 XftFont
*font
, const char *text
,
74 cairo_font_face_t
*font_face
;
75 cairo_surface_t
*surface
;
78 draw_rectangle(ctx
, area
, True
, bg
);
80 olen
= len
= a_strlen(text
);
85 surface
= cairo_xlib_surface_create(ctx
->display
, ctx
->drawable
, ctx
->visual
, ctx
->width
, ctx
->height
);
86 cr
= cairo_create(surface
);
87 font_face
= cairo_ft_font_face_create_for_pattern(font
->pattern
);
88 cairo_set_font_face(cr
, font_face
);
89 cairo_set_font_size(cr
, font
->height
);
90 cairo_set_source_rgb(cr
, fg
.red
/ 65535.0, fg
.green
/ 65535.0, fg
.blue
/ 65535.0);
92 if(len
>= sizeof(buf
))
93 len
= sizeof(buf
) - 1;
94 memcpy(buf
, text
, len
);
96 while(len
&& (nw
= (draw_textwidth(ctx
->display
, font
, buf
)) + padding
* 2) > area
.width
)
99 return; /* too long */
113 cairo_move_to(cr
, area
.x
+ padding
, area
.y
+ font
->ascent
+ (ctx
->height
- font
->height
) / 2);
116 cairo_move_to(cr
, area
.x
+ (area
.width
- nw
) + padding
,
117 area
.y
+ font
->ascent
+ (ctx
->height
- font
->height
) / 2);
120 cairo_move_to(cr
, area
.x
+ ((area
.width
- nw
) / 2) + padding
,
121 area
.y
+ font
->ascent
+ (ctx
->height
- font
->height
) / 2);
124 cairo_show_text(cr
, buf
);
126 cairo_font_face_destroy(font_face
);
128 cairo_surface_destroy(surface
);
132 * \param ctx Draw context
133 * \param geometry geometry
134 * \param filled filled rectangle?
135 * \param color color to use
138 draw_rectangle(DrawCtx
*ctx
, Area geometry
, Bool filled
, XColor color
)
140 cairo_surface_t
*surface
;
143 surface
= cairo_xlib_surface_create(ctx
->display
, ctx
->drawable
, ctx
->visual
, ctx
->width
, ctx
->height
);
144 cr
= cairo_create (surface
);
146 cairo_set_antialias(cr
, CAIRO_ANTIALIAS_NONE
);
147 cairo_set_line_width(cr
, 1.0);
148 cairo_set_source_rgb(cr
, color
.red
/ 65535.0, color
.green
/ 65535.0, color
.blue
/ 65535.0);
151 cairo_rectangle(cr
, geometry
.x
, geometry
.y
, geometry
.width
, geometry
.height
);
155 cairo_rectangle(cr
, geometry
.x
+ 1, geometry
.y
, geometry
.width
- 1, geometry
.height
- 1);
160 cairo_surface_destroy(surface
);
163 /* draw_graph functions */
165 draw_graph_init(DrawCtx
*ctx
, cairo_surface_t
**pp_surface
, cairo_t
**pp_cr
)
167 *pp_surface
= cairo_xlib_surface_create(ctx
->display
, ctx
->drawable
, ctx
->visual
, ctx
->width
, ctx
->height
);
168 *pp_cr
= cairo_create (*pp_surface
);
170 cairo_set_antialias(*pp_cr
, CAIRO_ANTIALIAS_NONE
);
171 cairo_set_line_width(*pp_cr
, 1.0);
172 /* without it, it can draw over the path on sharp angles (...too long lines) */
173 cairo_set_line_join (*pp_cr
, CAIRO_LINE_JOIN_ROUND
);
177 draw_graph_end(cairo_surface_t
*surface
, cairo_t
*cr
)
180 cairo_surface_destroy(surface
);
183 /* draws a graph; it takes the line-lengths from *from and *to. It cycles
184 * backwards through those arrays (what have the length of w), beginning at
185 * position cur_index, until cur_index is reached again (wrapped around). */
187 draw_graph(cairo_t
*cr
, int x
, int y
, int w
, int *from
, int *to
, int cur_index
, XColor color
)
190 cairo_set_source_rgb(cr
, color
.red
/ 65535.0, color
.green
/ 65535.0, color
.blue
/ 65535.0);
195 cairo_move_to(cr
, x
, y
- from
[cur_index
]);
196 cairo_line_to(cr
, x
, y
- to
[cur_index
]);
205 draw_graph_line(cairo_t
*cr
, int x
, int y
, int w
, int *to
, int cur_index
, XColor color
)
208 int flag
= 0; /* used to prevent drawing a line from 0 to 0 values */
209 cairo_set_source_rgb(cr
, color
.red
/ 65535.0, color
.green
/ 65535.0, color
.blue
/ 65535.0);
211 /* x-1 (on the border), paints *from* the last point (... not included itself) */
212 /* makes sense when you assume there is already some line drawn to it. */
213 cairo_move_to(cr
, x
- 1, y
- to
[cur_index
]);
215 for (i
= 0; i
< w
; i
++)
217 if (to
[cur_index
] > 0)
219 cairo_line_to(cr
, x
, y
- to
[cur_index
]);
224 if(flag
) /* only draw from values > 0 to 0-values */
226 cairo_line_to(cr
, x
, y
);
230 cairo_move_to(cr
, x
, y
);
233 if (--cur_index
< 0) /* cycles around the index */
241 draw_circle(DrawCtx
*ctx
, int x
, int y
, int r
, Bool filled
, XColor color
)
243 cairo_surface_t
*surface
;
246 surface
= cairo_xlib_surface_create(ctx
->display
, ctx
->drawable
, ctx
->visual
, ctx
->width
, ctx
->height
);
247 cr
= cairo_create (surface
);
248 cairo_set_line_width(cr
, 1.0);
249 cairo_set_source_rgb(cr
, color
.red
/ 65535.0, color
.green
/ 65535.0, color
.blue
/ 65535.0);
252 cairo_arc (cr
, x
+ r
, y
+ r
, r
, 0, 2 * M_PI
);
256 cairo_arc (cr
, x
+ r
, y
+ r
, r
- 1, 0, 2 * M_PI
);
261 cairo_surface_destroy(surface
);
264 void draw_image_from_argb_data(DrawCtx
*ctx
, int x
, int y
, int w
, int h
,
265 int wanted_h
, unsigned char *data
)
268 cairo_surface_t
*surface
, *source
;
271 surface
= cairo_xlib_surface_create(ctx
->display
, ctx
->drawable
, ctx
->visual
, ctx
->width
, ctx
->height
);
272 source
= cairo_image_surface_create_for_data(data
, CAIRO_FORMAT_ARGB32
, w
, h
, 0);
273 cr
= cairo_create (surface
);
274 if(wanted_h
> 0 && h
> 0)
276 ratio
= (double) wanted_h
/ (double) h
;
277 cairo_scale(cr
, ratio
, ratio
);
278 cairo_set_source_surface(cr
, source
, x
/ ratio
, y
/ ratio
);
281 cairo_set_source_surface(cr
, source
, x
, y
);
285 cairo_surface_destroy(source
);
286 cairo_surface_destroy(surface
);
290 draw_image(DrawCtx
*ctx
, int x
, int y
, int wanted_h
, const char *filename
)
294 cairo_surface_t
*surface
, *source
;
296 cairo_status_t cairo_st
;
298 source
= cairo_xlib_surface_create(ctx
->display
, ctx
->drawable
, ctx
->visual
, ctx
->width
, ctx
->height
);
299 surface
= cairo_image_surface_create_from_png(filename
);
300 if((cairo_st
= cairo_surface_status(surface
)))
302 warn("failed to draw image %s: %s\n", filename
, cairo_status_to_string(cairo_st
));
305 cr
= cairo_create (source
);
306 if(wanted_h
> 0 && (h
= cairo_image_surface_get_height(surface
)) > 0)
308 ratio
= (double) wanted_h
/ (double) h
;
309 cairo_scale(cr
, ratio
, ratio
);
310 cairo_set_source_surface(cr
, surface
, x
/ ratio
, y
/ ratio
);
313 cairo_set_source_surface(cr
, surface
, x
, y
);
317 cairo_surface_destroy(source
);
318 cairo_surface_destroy(surface
);
322 draw_get_image_size(const char *filename
)
324 Area size
= { -1, -1, -1, -1 };
325 cairo_surface_t
*surface
;
326 cairo_status_t cairo_st
;
328 surface
= cairo_image_surface_create_from_png(filename
);
329 if((cairo_st
= cairo_surface_status(surface
)))
330 warn("failed to get image size %s: %s\n", filename
, cairo_status_to_string(cairo_st
));
333 cairo_image_surface_get_width(surface
);
336 size
.width
= cairo_image_surface_get_width(surface
);
337 size
.height
= cairo_image_surface_get_height(surface
);
338 cairo_surface_destroy(surface
);
345 draw_rotate(DrawCtx
*ctx
, int screen
, double angle
, int tx
, int ty
)
347 cairo_surface_t
*surface
, *source
;
349 Drawable newdrawable
;
351 newdrawable
= XCreatePixmap(ctx
->display
,
352 RootWindow(ctx
->display
, screen
),
353 ctx
->height
, ctx
->width
,
355 surface
= cairo_xlib_surface_create(ctx
->display
, newdrawable
, ctx
->visual
, ctx
->height
, ctx
->width
);
356 source
= cairo_xlib_surface_create(ctx
->display
, ctx
->drawable
, ctx
->visual
, ctx
->width
, ctx
->height
);
357 cr
= cairo_create (surface
);
359 cairo_translate(cr
, tx
, ty
);
360 cairo_rotate(cr
, angle
);
362 cairo_set_source_surface(cr
, source
, 0.0, 0.0);
366 cairo_surface_destroy(source
);
367 cairo_surface_destroy(surface
);
373 draw_textwidth(Display
*disp
, XftFont
*font
, char *text
)
375 cairo_surface_t
*surface
;
377 cairo_font_face_t
*font_face
;
378 cairo_text_extents_t te
;
383 surface
= cairo_xlib_surface_create(disp
, DefaultScreen(disp
),
384 DefaultVisual(disp
, DefaultScreen(disp
)),
385 DisplayWidth(disp
, DefaultScreen(disp
)),
386 DisplayHeight(disp
, DefaultScreen(disp
)));
387 cr
= cairo_create(surface
);
388 font_face
= cairo_ft_font_face_create_for_pattern(font
->pattern
);
389 cairo_set_font_face(cr
, font_face
);
390 cairo_set_font_size(cr
, font
->height
);
391 cairo_text_extents(cr
, text
, &te
);
393 cairo_surface_destroy(surface
);
394 cairo_font_face_destroy(font_face
);
396 return MAX(te
.x_advance
, te
.width
);
400 draw_get_align(const char *align
)
402 if(!a_strncmp(align
, "center", 6))
404 else if(!a_strncmp(align
, "right", 5))
410 /** Initialize an X color
411 * \param disp display ref
412 * \param screen Physical screen number
413 * \param colstr Color specification
414 * \return XColor struct
417 draw_color_new(Display
*disp
, int phys_screen
, const char *colstr
)
419 XColor screenColor
, exactColor
;
421 if(!XAllocNamedColor(disp
,
422 DefaultColormap(disp
, phys_screen
),
426 eprint("awesome: error, cannot allocate color '%s'\n", colstr
);
431 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80