change warn() message and use simply , as strtok delimiter
[awesome.git] / draw.c
blobf15a1259d54390626b0c047a30a4c3d1233a1ccf
1 /*
2 * draw.c - draw functions
4 * Copyright © 2007 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 "layout.h"
27 #include "util.h"
28 #include "draw.h"
30 extern AwesomeConf globalconf;
32 /** Get a draw context
33 * \param phys_screen physical screen id
34 * \param width width
35 * \param height height
36 * \return draw context ref
38 DrawCtx *
39 draw_get_context(int phys_screen, int width, int height)
41 DrawCtx *d = p_new(DrawCtx, 1);
43 d->phys_screen = phys_screen;
44 d->width = width;
45 d->height = height;
46 d->depth = DefaultDepth(globalconf.display, phys_screen);
47 d->visual = DefaultVisual(globalconf.display, phys_screen);
48 d->drawable = XCreatePixmap(globalconf.display,
49 RootWindow(globalconf.display, phys_screen),
50 width, height, d->depth);
52 return d;
55 /** Free a draw context and its drawable
56 * \param ctx the draw context to free
58 void
59 draw_free_context(DrawCtx *ctx)
61 XFreePixmap(globalconf.display, ctx->drawable);
62 p_delete(&ctx);
65 /** Draw text into a draw context
66 * \param x x coord
67 * \param y y coord
68 * \param w width
69 * \param h height
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, int x, int y, int w, int h, int padding, XftFont *font, const char *text, XColor fg, XColor bg)
79 int nw = 0;
80 static char buf[256];
81 size_t len, olen;
82 cairo_font_face_t *font_face;
83 cairo_surface_t *surface;
84 cairo_t *cr;
86 draw_rectangle(ctx, x, y, w, h, True, bg);
88 olen = len = a_strlen(text);
90 if(!len)
91 return;
93 surface = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height);
94 cr = cairo_create(surface);
95 font_face = cairo_ft_font_face_create_for_pattern(font->pattern);
96 cairo_set_font_face(cr, font_face);
97 cairo_set_font_size(cr, font->height);
98 cairo_set_source_rgb(cr, fg.red / 65535.0, fg.green / 65535.0, fg.blue / 65535.0);
100 if(len >= sizeof(buf))
101 len = sizeof(buf) - 1;
102 memcpy(buf, text, len);
103 buf[len] = 0;
104 while(len && (nw = (textwidth(font, buf)) + padding * 2) > w)
105 buf[--len] = 0;
106 if(nw > w)
107 return; /* too long */
108 if(len < olen)
110 if(len > 1)
111 buf[len - 1] = '.';
112 if(len > 2)
113 buf[len - 2] = '.';
114 if(len > 3)
115 buf[len - 3] = '.';
118 cairo_move_to(cr, x + padding, y + font->ascent + (ctx->height - font->height) / 2);
119 cairo_show_text(cr, buf);
121 cairo_font_face_destroy(font_face);
122 cairo_destroy(cr);
123 cairo_surface_destroy(surface);
126 void
127 draw_rectangle(DrawCtx *ctx, int x, int y, int w, int h, Bool filled, XColor color)
129 cairo_surface_t *surface;
130 cairo_t *cr;
132 surface = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height);
133 cr = cairo_create (surface);
135 cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
136 cairo_set_line_width(cr, 1.0);
137 cairo_set_source_rgb(cr, color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0);
138 if(filled)
140 cairo_rectangle(cr, x, y, w, h);
141 cairo_fill(cr);
143 else
144 cairo_rectangle(cr, x + 1, y, w - 1, h - 1);
146 cairo_stroke(cr);
148 cairo_destroy(cr);
149 cairo_surface_destroy(surface);
152 void
153 draw_circle(DrawCtx *ctx, int x, int y, int r, Bool filled, XColor color)
155 cairo_surface_t *surface;
156 cairo_t *cr;
158 surface = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height);
159 cr = cairo_create (surface);
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_arc (cr, x + r, y + r, r, 0, 2 * M_PI);
165 cairo_fill(cr);
167 else
168 cairo_arc (cr, x + r, y + r, r - 1, 0, 2 * M_PI);
170 cairo_stroke(cr);
172 cairo_destroy(cr);
173 cairo_surface_destroy(surface);
176 void draw_image_from_argb_data(DrawCtx *ctx, int x, int y, int w, int h,
177 int wanted_h, unsigned char *data)
179 double ratio;
180 cairo_surface_t *surface, *source;
181 cairo_t *cr;
183 surface = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height);
184 source = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, w, h, 0);
185 cr = cairo_create (surface);
186 if(wanted_h > 0 && h > 0)
188 ratio = (double) wanted_h / (double) h;
189 cairo_scale(cr, ratio, ratio);
190 cairo_set_source_surface(cr, source, x / ratio, y / ratio);
192 else
193 cairo_set_source_surface(cr, source, x, y);
194 cairo_paint(cr);
196 cairo_destroy(cr);
197 cairo_surface_destroy(source);
198 cairo_surface_destroy(surface);
201 void
202 draw_image(DrawCtx *ctx, int x, int y, int wanted_h, const char *filename)
204 double ratio;
205 int h;
206 cairo_surface_t *surface, *source;
207 cairo_t *cr;
209 source = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height);
210 surface = cairo_image_surface_create_from_png(filename);
211 cr = cairo_create (source);
212 if(wanted_h > 0 && (h = cairo_image_surface_get_height(surface)) > 0)
214 ratio = (double) wanted_h / (double) h;
215 cairo_scale(cr, ratio, ratio);
216 cairo_set_source_surface(cr, surface, x / ratio, y / ratio);
218 else
219 cairo_set_source_surface(cr, surface, x, y);
220 cairo_paint(cr);
222 cairo_destroy(cr);
223 cairo_surface_destroy(source);
224 cairo_surface_destroy(surface);
229 Area
230 draw_get_image_size(const char *filename)
232 Area size;
233 cairo_surface_t *surface;
235 surface = cairo_image_surface_create_from_png(filename);
236 cairo_image_surface_get_width(surface);
237 size.width = cairo_image_surface_get_width(surface);
238 size.height = cairo_image_surface_get_height(surface);
239 cairo_surface_destroy(surface);
241 return size;
244 Drawable
245 draw_rotate(DrawCtx *ctx, int screen, double angle, int tx, int ty)
247 cairo_surface_t *surface, *source;
248 cairo_t *cr;
249 Drawable newdrawable;
251 newdrawable = XCreatePixmap(globalconf.display,
252 RootWindow(globalconf.display, screen),
253 ctx->height, ctx->width,
254 ctx->depth);
255 surface = cairo_xlib_surface_create(globalconf.display, newdrawable, ctx->visual, ctx->height, ctx->width);
256 source = cairo_xlib_surface_create(globalconf.display, ctx->drawable, ctx->visual, ctx->width, ctx->height);
257 cr = cairo_create (surface);
259 cairo_translate(cr, tx, ty);
260 cairo_rotate(cr, angle);
262 cairo_set_source_surface(cr, source, 0.0, 0.0);
263 cairo_paint(cr);
265 cairo_destroy(cr);
266 cairo_surface_destroy(source);
267 cairo_surface_destroy(surface);
269 return newdrawable;
272 unsigned short
273 textwidth(XftFont *font, char *text)
275 cairo_surface_t *surface;
276 cairo_t *cr;
277 cairo_font_face_t *font_face;
278 cairo_text_extents_t te;
280 if (!a_strlen(text))
281 return 0;
283 surface = cairo_xlib_surface_create(globalconf.display, DefaultScreen(globalconf.display),
284 DefaultVisual(globalconf.display, DefaultScreen(globalconf.display)),
285 DisplayWidth(globalconf.display, DefaultScreen(globalconf.display)),
286 DisplayHeight(globalconf.display, DefaultScreen(globalconf.display)));
287 cr = cairo_create(surface);
288 font_face = cairo_ft_font_face_create_for_pattern(font->pattern);
289 cairo_set_font_face(cr, font_face);
290 cairo_set_font_size(cr, font->height);
291 cairo_text_extents(cr, text, &te);
292 cairo_destroy(cr);
293 cairo_surface_destroy(surface);
294 cairo_font_face_destroy(font_face);
296 return MAX(te.x_advance, te.width);
299 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80