cosmetic
[awesome.git] / draw.c
blob7d467d195e1c3e659b8e6d5a8356d39fad1d7efb
1 /*
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.
22 #include <cairo.h>
23 #include <cairo-ft.h>
24 #include <cairo-xlib.h>
25 #include <math.h>
26 #include "util.h"
27 #include "config.h"
29 extern AwesomeConf globalconf;
31 /** Get a draw context
32 * \param phys_screen physical screen id
33 * \param width width
34 * \param height height
35 * \return draw context ref
37 DrawCtx *
38 draw_get_context(int phys_screen, int width, int height)
40 DrawCtx *d = p_new(DrawCtx, 1);
42 d->phys_screen = phys_screen;
43 d->width = width;
44 d->height = height;
45 d->depth = DefaultDepth(globalconf.display, phys_screen);
46 d->visual = DefaultVisual(globalconf.display, phys_screen);
47 d->drawable = XCreatePixmap(globalconf.display,
48 RootWindow(globalconf.display, phys_screen),
49 width, height, d->depth);
51 return d;
54 /** Free a draw context and its drawable
55 * \param ctx the draw context to free
57 void
58 draw_free_context(DrawCtx *ctx)
60 XFreePixmap(globalconf.display, ctx->drawable);
61 p_delete(&ctx);
64 /** Draw text into a draw context
65 * \param x x coord
66 * \param y y coord
67 * \param w width
68 * \param h height
69 * \param align alignment
70 * \param padding padding to add before drawing the text
71 * \param font font to use
72 * \param text text to draw
73 * \param fg foreground color
74 * \param bg background color
76 void
77 draw_text(DrawCtx *ctx,
78 Area area,
79 int align,
80 int padding,
81 XftFont *font, const char *text,
82 XColor fg, XColor bg)
84 int nw = 0;
85 static char buf[256];
86 size_t len, olen;
87 cairo_font_face_t *font_face;
88 cairo_surface_t *surface;
89 cairo_t *cr;
91 draw_rectangle(ctx, area, True, bg);
93 olen = len = a_strlen(text);
95 if(!len)
96 return;
98 surface = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height);
99 cr = cairo_create(surface);
100 font_face = cairo_ft_font_face_create_for_pattern(font->pattern);
101 cairo_set_font_face(cr, font_face);
102 cairo_set_font_size(cr, font->height);
103 cairo_set_source_rgb(cr, fg.red / 65535.0, fg.green / 65535.0, fg.blue / 65535.0);
105 if(len >= sizeof(buf))
106 len = sizeof(buf) - 1;
107 memcpy(buf, text, len);
108 buf[len] = 0;
109 while(len && (nw = (draw_textwidth(font, buf)) + padding * 2) > area.width)
110 buf[--len] = 0;
111 if(nw > area.width)
112 return; /* too long */
113 if(len < olen)
115 if(len > 1)
116 buf[len - 1] = '.';
117 if(len > 2)
118 buf[len - 2] = '.';
119 if(len > 3)
120 buf[len - 3] = '.';
123 switch(align)
125 case AlignLeft:
126 cairo_move_to(cr, area.x + padding, area.y + font->ascent + (ctx->height - font->height) / 2);
127 break;
128 case AlignRight:
129 cairo_move_to(cr, area.x + (area.width - nw) + padding,
130 area.y + font->ascent + (ctx->height - font->height) / 2);
131 break;
132 default:
133 cairo_move_to(cr, area.x + ((area.width - nw) / 2) + padding,
134 area.y + font->ascent + (ctx->height - font->height) / 2);
135 break;
137 cairo_show_text(cr, buf);
139 cairo_font_face_destroy(font_face);
140 cairo_destroy(cr);
141 cairo_surface_destroy(surface);
144 /** Draw rectangle
145 * \param ctx Draw context
146 * \param geometry geometry
147 * \param filled filled rectangle?
148 * \param color color to use
150 void
151 draw_rectangle(DrawCtx *ctx, Area geometry, Bool filled, XColor color)
153 cairo_surface_t *surface;
154 cairo_t *cr;
156 surface = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height);
157 cr = cairo_create (surface);
159 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
160 cairo_set_line_width(cr, 1.0);
161 cairo_set_source_rgb(cr, color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0);
162 if(filled)
164 cairo_rectangle(cr, geometry.x, geometry.y, geometry.width, geometry.height);
165 cairo_fill(cr);
167 else
168 cairo_rectangle(cr, geometry.x + 1, geometry.y, geometry.width - 1, geometry.height - 1);
170 cairo_stroke(cr);
172 cairo_destroy(cr);
173 cairo_surface_destroy(surface);
176 /* draws a graph; it takes the line-lengths from 'h' (w = size of h)
177 * It cycles backwards through it, beginning at position h_index, until
178 * h_index is reached again (wrapped around). */
180 void
181 draw_graph(DrawCtx *ctx, int x, int y, int w, int *h, int h_index, XColor color)
183 cairo_surface_t *surface;
184 cairo_t *cr;
185 int i;
187 surface = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height);
188 cr = cairo_create (surface);
190 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
191 cairo_set_line_width(cr, 1.0);
192 cairo_set_source_rgb(cr, color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0);
194 i = -1;
195 while(++i < w)
197 cairo_move_to(cr, x, y);
198 cairo_line_to(cr, x, y - h[h_index]);
199 x++;
201 if (--h_index < 0)
202 h_index = w - 1;
205 cairo_stroke(cr);
207 cairo_destroy(cr);
208 cairo_surface_destroy(surface);
211 void
212 draw_circle(DrawCtx *ctx, int x, int y, int r, Bool filled, XColor color)
214 cairo_surface_t *surface;
215 cairo_t *cr;
217 surface = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height);
218 cr = cairo_create (surface);
219 cairo_set_line_width(cr, 1.0);
220 cairo_set_source_rgb(cr, color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0);
221 if(filled)
223 cairo_arc (cr, x + r, y + r, r, 0, 2 * M_PI);
224 cairo_fill(cr);
226 else
227 cairo_arc (cr, x + r, y + r, r - 1, 0, 2 * M_PI);
229 cairo_stroke(cr);
231 cairo_destroy(cr);
232 cairo_surface_destroy(surface);
235 void draw_image_from_argb_data(DrawCtx *ctx, int x, int y, int w, int h,
236 int wanted_h, unsigned char *data)
238 double ratio;
239 cairo_surface_t *surface, *source;
240 cairo_t *cr;
242 surface = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height);
243 source = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, w, h, 0);
244 cr = cairo_create (surface);
245 if(wanted_h > 0 && h > 0)
247 ratio = (double) wanted_h / (double) h;
248 cairo_scale(cr, ratio, ratio);
249 cairo_set_source_surface(cr, source, x / ratio, y / ratio);
251 else
252 cairo_set_source_surface(cr, source, x, y);
253 cairo_paint(cr);
255 cairo_destroy(cr);
256 cairo_surface_destroy(source);
257 cairo_surface_destroy(surface);
260 void
261 draw_image(DrawCtx *ctx, int x, int y, int wanted_h, const char *filename)
263 double ratio;
264 int h;
265 cairo_surface_t *surface, *source;
266 cairo_t *cr;
268 source = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height);
269 surface = cairo_image_surface_create_from_png(filename);
270 cr = cairo_create (source);
271 if(wanted_h > 0 && (h = cairo_image_surface_get_height(surface)) > 0)
273 ratio = (double) wanted_h / (double) h;
274 cairo_scale(cr, ratio, ratio);
275 cairo_set_source_surface(cr, surface, x / ratio, y / ratio);
277 else
278 cairo_set_source_surface(cr, surface, x, y);
279 cairo_paint(cr);
281 cairo_destroy(cr);
282 cairo_surface_destroy(source);
283 cairo_surface_destroy(surface);
286 Area
287 draw_get_image_size(const char *filename)
289 Area size;
290 cairo_surface_t *surface;
292 surface = cairo_image_surface_create_from_png(filename);
293 cairo_image_surface_get_width(surface);
294 size.x = 0;
295 size.y = 0;
296 size.width = cairo_image_surface_get_width(surface);
297 size.height = cairo_image_surface_get_height(surface);
298 cairo_surface_destroy(surface);
300 return size;
303 Drawable
304 draw_rotate(DrawCtx *ctx, int screen, double angle, int tx, int ty)
306 cairo_surface_t *surface, *source;
307 cairo_t *cr;
308 Drawable newdrawable;
310 newdrawable = XCreatePixmap(globalconf.display,
311 RootWindow(globalconf.display, screen),
312 ctx->height, ctx->width,
313 ctx->depth);
314 surface = cairo_xlib_surface_create(globalconf.display, newdrawable, ctx->visual, ctx->height, ctx->width);
315 source = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height);
316 cr = cairo_create (surface);
318 cairo_translate(cr, tx, ty);
319 cairo_rotate(cr, angle);
321 cairo_set_source_surface(cr, source, 0.0, 0.0);
322 cairo_paint(cr);
324 cairo_destroy(cr);
325 cairo_surface_destroy(source);
326 cairo_surface_destroy(surface);
328 return newdrawable;
331 unsigned short
332 draw_textwidth(XftFont *font, char *text)
334 cairo_surface_t *surface;
335 cairo_t *cr;
336 cairo_font_face_t *font_face;
337 cairo_text_extents_t te;
339 if (!a_strlen(text))
340 return 0;
342 surface = cairo_xlib_surface_create(globalconf.display, DefaultScreen(globalconf.display),
343 DefaultVisual(globalconf.display, DefaultScreen(globalconf.display)),
344 DisplayWidth(globalconf.display, DefaultScreen(globalconf.display)),
345 DisplayHeight(globalconf.display, DefaultScreen(globalconf.display)));
346 cr = cairo_create(surface);
347 font_face = cairo_ft_font_face_create_for_pattern(font->pattern);
348 cairo_set_font_face(cr, font_face);
349 cairo_set_font_size(cr, font->height);
350 cairo_text_extents(cr, text, &te);
351 cairo_destroy(cr);
352 cairo_surface_destroy(surface);
353 cairo_font_face_destroy(font_face);
355 return MAX(te.x_advance, te.width);
358 Alignment
359 draw_get_align(const char *align)
361 if(!a_strncmp(align, "center", 6))
362 return AlignCenter;
363 else if(!a_strncmp(align, "right", 5))
364 return AlignRight;
366 return AlignLeft;
369 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80