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-xlib.h>
32 #include "common/util.h"
34 /** Convert text from any charset to UTF-8 using iconv
35 * \param iso the ISO string to convert
36 * \return NULL if error, otherwise pointer to the new converted string
39 draw_iso2utf8(char *iso
)
45 if(!(len
= a_strlen(iso
)))
48 if(!a_strcmp(nl_langinfo(CODESET
), "UTF-8"))
51 iso2utf8
= iconv_open("UTF-8", nl_langinfo(CODESET
));
52 if(iso2utf8
== (iconv_t
) -1)
55 warn("unable to convert text from %s to UTF-8, not available",
56 nl_langinfo(CODESET
));
58 warn("unable to convert text: %s\n", strerror(errno
));
63 utf8len
= (3 * len
) / 2 + 1;
64 utf8
= utf8p
= p_new(char, utf8len
);
66 if(iconv(iso2utf8
, &iso
, &len
, &utf8
, &utf8len
) == (size_t) -1)
68 warn("text conversion failed: %s\n", strerror(errno
));
73 if(iconv_close(iso2utf8
))
74 warn("error closing iconv");
79 /** Get a draw context
80 * \param disp Display ref
81 * \param phys_screen physical screen id
83 * \param height height
84 * \param dw Drawable object to store in DrawCtx
85 * \return draw context ref
88 draw_context_new(Display
*disp
, int phys_screen
, int width
, int height
, Drawable dw
)
90 DrawCtx
*d
= p_new(DrawCtx
, 1);
93 d
->phys_screen
= phys_screen
;
96 d
->depth
= DefaultDepth(disp
, phys_screen
);
97 d
->visual
= DefaultVisual(disp
, phys_screen
);
99 d
->surface
= cairo_xlib_surface_create(disp
, dw
, d
->visual
, width
, height
);
100 d
->cr
= cairo_create(d
->surface
);
101 d
->layout
= pango_cairo_create_layout(d
->cr
);
106 /** Delete a draw context
107 * \param ctx DrawCtx to delete
110 draw_context_delete(DrawCtx
**ctx
)
112 g_object_unref((*ctx
)->layout
);
113 cairo_surface_destroy((*ctx
)->surface
);
114 cairo_destroy((*ctx
)->cr
);
118 /** Create a new Pango font
119 * \param disp Display ref
120 * \param fontname Pango fontname (e.g. [FAMILY-LIST] [STYLE-OPTIONS] [SIZE])
124 draw_font_new(Display
*disp
, char *fontname
)
126 cairo_surface_t
*surface
;
129 font_t
*font
= p_new(font_t
, 1);
131 /* Create a dummy cairo surface, cairo context and pango layout in
132 * order to get font informations */
133 surface
= cairo_xlib_surface_create(disp
,
135 DefaultVisual(disp
, DefaultScreen(disp
)),
136 DisplayWidth(disp
, DefaultScreen(disp
)),
137 DisplayHeight(disp
, DefaultScreen(disp
)));
139 cr
= cairo_create(surface
);
140 layout
= pango_cairo_create_layout(cr
);
142 /* Get the font description used to set text on a PangoLayout */
143 font
->desc
= pango_font_description_from_string(fontname
);
144 pango_layout_set_font_description(layout
, font
->desc
);
147 pango_layout_get_pixel_size(layout
, NULL
, &font
->height
);
149 /* At the moment, we don't need ascent/descent but maybe it could
150 * be useful in the future... */
152 PangoContext
*context
;
153 PangoFontMetrics
*font_metrics
;
155 /* Get ascent and descent */
156 context
= pango_layout_get_context(layout
);
157 font_metrics
= pango_context_get_metrics(context
, font
->desc
, NULL
);
159 /* Values in PangoFontMetrics are given in Pango units */
160 font
->ascent
= PANGO_PIXELS(pango_font_metrics_get_ascent(font_metrics
));
161 font
->descent
= PANGO_PIXELS(pango_font_metrics_get_descent(font_metrics
));
163 pango_font_metrics_unref(font_metrics
);
166 g_object_unref(layout
);
168 cairo_surface_destroy(surface
);
174 * \param font font_t to delete
177 draw_font_delete(font_t
**font
)
179 pango_font_description_free((*font
)->desc
);
183 /** Draw text into a draw context
184 * \param ctx DrawCtx to draw to
185 * \param area area to draw to
186 * \param align alignment
187 * \param padding padding to add before drawing the text
188 * \param font font to use
189 * \param text text to draw
190 * \param enable shadow
191 * \param fg foreground color
192 * \param bg background color
195 draw_text(DrawCtx
*ctx
,
204 char *buf
= NULL
, *utf8
= NULL
;
206 draw_rectangle(ctx
, area
, 1.0, True
, style
.bg
);
208 if(!(len
= olen
= a_strlen(text
)))
211 /* try to convert it to UTF-8 */
212 if((utf8
= draw_iso2utf8(text
)))
215 len
= olen
= a_strlen(buf
);
218 buf
= a_strdup(text
);
220 /* check that the text is not too long */
221 while(len
&& (nw
= (draw_textwidth(ctx
->display
, style
.font
, buf
)) + padding
* 2) > area
.width
)
224 /* we can't blindly null the char, we need to check if it's not part of
225 * a multi byte char: if mbtowc return -1, we know that we must go back
226 * in the string to find the beginning of the multi byte char */
227 while(mbtowc(NULL
, buf
+ len
, a_strlen(buf
+ len
)) < 0)
232 return; /* too long */
243 pango_layout_set_text(ctx
->layout
, buf
, -1);
244 pango_layout_set_font_description(ctx
->layout
, style
.font
->desc
);
246 x
= area
.x
+ padding
;
247 y
= area
.y
+ (ctx
->height
- style
.font
->height
) / 2;
252 x
+= (area
.width
- nw
) / 2;
255 x
+= area
.width
- nw
;
261 if(style
.shadow_offset
> 0)
263 cairo_set_source_rgb(ctx
->cr
,
264 style
.shadow
.red
/ 65535.0,
265 style
.shadow
.green
/ 65535.0,
266 style
.shadow
.blue
/ 65535.0);
267 cairo_move_to(ctx
->cr
, x
+ style
.shadow_offset
, y
+ style
.shadow_offset
);
268 pango_cairo_update_layout(ctx
->cr
, ctx
->layout
);
269 pango_cairo_show_layout(ctx
->cr
, ctx
->layout
);
272 cairo_set_source_rgb(ctx
->cr
,
273 style
.fg
.red
/ 65535.0,
274 style
.fg
.green
/ 65535.0,
275 style
.fg
.blue
/ 65535.0);
276 cairo_move_to(ctx
->cr
, x
, y
);
277 pango_cairo_update_layout(ctx
->cr
, ctx
->layout
);
278 pango_cairo_show_layout(ctx
->cr
, ctx
->layout
);
283 /** Setup color-source for cairo (gradient or mono)
284 * \param ctx Draw context
285 * \param rect x,y to x+x_offset,y+y_offset
286 * \param color color to use at start (x,y)
287 * \param pcolor_center color at 50% of width
288 * \param pcolor_end color at pattern end (x + x_offset, y + y_offset)
289 * \return pat pattern or NULL; needs to get cairo_pattern_destroy()'ed;
291 static cairo_pattern_t
*
292 draw_setup_cairo_color_source(DrawCtx
*ctx
, area_t rect
,
293 XColor
*pcolor
, XColor
*pcolor_center
,
296 cairo_pattern_t
*pat
= NULL
;
298 /* no need for a real pattern: */
299 if(!pcolor_end
&& !pcolor_center
)
300 cairo_set_source_rgb(ctx
->cr
, pcolor
->red
/ 65535.0, pcolor
->green
/ 65535.0, pcolor
->blue
/ 65535.0);
303 pat
= cairo_pattern_create_linear(rect
.x
, rect
.y
, rect
.x
+ rect
.width
, rect
.y
+ rect
.height
);
305 /* pcolor is always set (so far in awesome) */
306 cairo_pattern_add_color_stop_rgb(pat
, 0, pcolor
->red
/ 65535.0,
307 pcolor
->green
/ 65535.0, pcolor
->blue
/ 65535.0);
310 cairo_pattern_add_color_stop_rgb(pat
, 0.5, pcolor_center
->red
/ 65535.0,
311 pcolor_center
->green
/ 65535.0, pcolor_center
->blue
/ 65535.0);
314 cairo_pattern_add_color_stop_rgb(pat
, 1, pcolor_end
->red
/ 65535.0,
315 pcolor_end
->green
/ 65535.0, pcolor_end
->blue
/ 65535.0);
317 cairo_pattern_add_color_stop_rgb(pat
, 1, pcolor
->red
/ 65535.0,
318 pcolor
->green
/ 65535.0, pcolor
->blue
/ 65535.0);
319 cairo_set_source(ctx
->cr
, pat
);
325 * \param ctx Draw context
326 * \param geometry geometry
327 * \param line_width line width
328 * \param filled fill rectangle?
329 * \param color color to use
332 draw_rectangle(DrawCtx
*ctx
, area_t geometry
, float line_width
, Bool filled
, XColor color
)
334 cairo_set_antialias(ctx
->cr
, CAIRO_ANTIALIAS_NONE
);
335 cairo_set_line_width(ctx
->cr
, line_width
);
336 cairo_set_miter_limit(ctx
->cr
, 0.0);
337 cairo_set_line_join(ctx
->cr
, CAIRO_LINE_JOIN_MITER
);
338 cairo_set_source_rgb(ctx
->cr
,
340 color
.green
/ 65535.0,
341 color
.blue
/ 65535.0);
344 cairo_rectangle(ctx
->cr
, geometry
.x
, geometry
.y
,
345 geometry
.width
, geometry
.height
);
350 cairo_rectangle(ctx
->cr
, geometry
.x
+ 1, geometry
.y
,
351 geometry
.width
- 1, geometry
.height
- 1);
352 cairo_stroke(ctx
->cr
);
356 /** Draw rectangle with gradient colors
357 * \param ctx Draw context
358 * \param geometry geometry
359 * \param line_width line width
360 * \param filled filled rectangle?
361 * \param pattern__x pattern start x coord
362 * \param pattern_width pattern width
363 * \param color color to use at start
364 * \param pcolor_center color at 50% of width
365 * \param pcolor_end color at pattern_start + pattern_width
368 draw_rectangle_gradient(DrawCtx
*ctx
, area_t geometry
, float line_width
, Bool filled
,
369 area_t pattern_rect
, XColor
*pcolor
,
370 XColor
*pcolor_center
, XColor
*pcolor_end
)
372 cairo_pattern_t
*pat
;
374 cairo_set_antialias(ctx
->cr
, CAIRO_ANTIALIAS_NONE
);
375 cairo_set_line_width(ctx
->cr
, line_width
);
376 cairo_set_miter_limit(ctx
->cr
, 0.0);
377 cairo_set_line_join(ctx
->cr
, CAIRO_LINE_JOIN_MITER
);
379 pat
= draw_setup_cairo_color_source(ctx
, pattern_rect
, pcolor
, pcolor_center
, pcolor_end
);
383 cairo_rectangle(ctx
->cr
, geometry
.x
, geometry
.y
, geometry
.width
, geometry
.height
);
388 cairo_rectangle(ctx
->cr
, geometry
.x
+ 1, geometry
.y
, geometry
.width
- 1, geometry
.height
- 1);
389 cairo_stroke(ctx
->cr
);
393 cairo_pattern_destroy(pat
);
396 /** Setup some cairo-things for drawing a graph
397 * \param ctx Draw context
400 draw_graph_setup(DrawCtx
*ctx
)
402 cairo_set_antialias(ctx
->cr
, CAIRO_ANTIALIAS_NONE
);
403 cairo_set_line_width(ctx
->cr
, 1.0);
404 /* without it, it can draw over the path on sharp angles (...too long lines) */
405 cairo_set_miter_limit(ctx
->cr
, 0.0);
406 cairo_set_line_join(ctx
->cr
, CAIRO_LINE_JOIN_MITER
);
410 * \param ctx Draw context
411 * \param x x-offset of widget
412 * \param y y-offset of widget
413 * \param w width in pixels
414 * \param from array of starting-point offsets to draw a graph-lines
415 * \param to array of end-point offsets to draw a graph-lines
416 * \param cur_index current position in data-array (cycles around)
417 * \param grow put new values to the left or to the right
418 * \param pcolor color at the left
419 * \param pcolor_center color in the center
420 * \param pcolor_end color at the right
423 draw_graph(DrawCtx
*ctx
, area_t rect
, int *from
, int *to
, int cur_index
,
424 Position grow
, area_t patt_rect
,
425 XColor
*pcolor
, XColor
*pcolor_center
, XColor
*pcolor_end
)
428 cairo_pattern_t
*pat
;
430 pat
= draw_setup_cairo_color_source(ctx
, patt_rect
,
431 pcolor
, pcolor_center
, pcolor_end
);
438 if(grow
== Right
) /* draw from right to left */
443 cairo_move_to(ctx
->cr
, x
, y
- from
[cur_index
]);
444 cairo_line_to(ctx
->cr
, x
, y
- to
[cur_index
]);
451 else /* draw from left to right */
455 cairo_move_to(ctx
->cr
, x
, y
- from
[cur_index
]);
456 cairo_line_to(ctx
->cr
, x
, y
- to
[cur_index
]);
464 cairo_stroke(ctx
->cr
);
467 cairo_pattern_destroy(pat
);
470 /** Draw a line into a graph-widget
471 * \param ctx Draw context
472 * \param x x-offset of widget
473 * \param y y-offset of widget
474 * \param w width in pixels
475 * \param to array of offsets to draw the line through...
476 * \param cur_index current position in data-array (cycles around)
477 * \param grow put new values to the left or to the right
478 * \param pcolor color at the left
479 * \param pcolor_center color in the center
480 * \param pcolor_end color at the right
483 draw_graph_line(DrawCtx
*ctx
, area_t rect
, int *to
, int cur_index
,
484 Position grow
, area_t patt_rect
,
485 XColor
*pcolor
, XColor
*pcolor_center
, XColor
*pcolor_end
)
488 int flag
= 0; /* used to prevent drawing a line from 0 to 0 values */
489 cairo_pattern_t
*pat
;
491 pat
= draw_setup_cairo_color_source(ctx
, patt_rect
, pcolor
, pcolor_center
, pcolor_end
);
497 if(grow
== Right
) /* draw from right to left */
500 cairo_move_to(ctx
->cr
, x
, y
- to
[cur_index
]);
504 /* x-1 (on the border), paints *from* the last point (... not included itself) */
505 /* may makes sense when you assume there is already some line drawn to it - anyway */
506 cairo_move_to(ctx
->cr
, x
- 1, y
- to
[cur_index
]);
509 for (i
= 0; i
< w
; i
++)
511 if (to
[cur_index
] > 0)
513 cairo_line_to(ctx
->cr
, x
, y
- to
[cur_index
]);
518 if(flag
) /* only draw from values > 0 to 0-values */
520 cairo_line_to(ctx
->cr
, x
, y
);
524 cairo_move_to(ctx
->cr
, x
, y
);
527 if (--cur_index
< 0) /* cycles around the index */
535 cairo_stroke(ctx
->cr
);
538 cairo_pattern_destroy(pat
);
542 * \param ctx Draw context to draw to
543 * \param x x coordinate
544 * \param y y coordinate
545 * \param r size of the circle
546 * \param filled fill circle?
547 * \param color color to use
550 draw_circle(DrawCtx
*ctx
, int x
, int y
, int r
, Bool filled
, XColor color
)
552 cairo_set_line_width(ctx
->cr
, 1.0);
553 cairo_set_source_rgb(ctx
->cr
, color
.red
/ 65535.0, color
.green
/ 65535.0, color
.blue
/ 65535.0);
555 cairo_new_sub_path(ctx
->cr
); /* don't draw from the old reference point to.. */
559 cairo_arc (ctx
->cr
, x
+ r
, y
+ r
, r
, 0, 2 * M_PI
);
563 cairo_arc (ctx
->cr
, x
+ r
, y
+ r
, r
- 1, 0, 2 * M_PI
);
565 cairo_stroke(ctx
->cr
);
568 /** Draw an image from ARGB data to a draw context.
569 * Data should be stored as an array of alpha, red, blue, green for each pixel
570 * and the array size should be w * h elements long.
571 * \param ctx Draw context to draw to
572 * \param x x coordinate
573 * \param y y coordinate
576 * \param wanted_h wanted height: if > 0, image will be resized
577 * \param data the image pixels array
579 void draw_image_from_argb_data(DrawCtx
*ctx
, int x
, int y
, int w
, int h
,
580 int wanted_h
, unsigned char *data
)
584 cairo_surface_t
*source
;
586 source
= cairo_image_surface_create_for_data(data
, CAIRO_FORMAT_ARGB32
, w
, h
,
587 #if CAIRO_VERSION_MAJOR < 1 || (CAIRO_VERSION_MAJOR == 1 && CAIRO_VERSION_MINOR < 5)
588 sizeof(unsigned char) * 4 * w
);
590 cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32
, w
));
592 cr
= cairo_create(ctx
->surface
);
593 if(wanted_h
> 0 && h
> 0)
595 ratio
= (double) wanted_h
/ (double) h
;
596 cairo_scale(cr
, ratio
, ratio
);
597 cairo_set_source_surface(cr
, source
, x
/ ratio
, y
/ ratio
);
600 cairo_set_source_surface(cr
, source
, x
, y
);
605 cairo_surface_destroy(source
);
609 draw_imlib_load_strerror(Imlib_Load_Error e
)
613 case IMLIB_LOAD_ERROR_FILE_DOES_NOT_EXIST
:
614 return "no such file or directory";
615 case IMLIB_LOAD_ERROR_FILE_IS_DIRECTORY
:
616 return "file is a directory";
617 case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_READ
:
618 return "read permission denied";
619 case IMLIB_LOAD_ERROR_NO_LOADER_FOR_FILE_FORMAT
:
620 return "no loader for file format";
621 case IMLIB_LOAD_ERROR_PATH_TOO_LONG
:
622 return "path too long";
623 case IMLIB_LOAD_ERROR_PATH_COMPONENT_NON_EXISTANT
:
624 return "path component non existant";
625 case IMLIB_LOAD_ERROR_PATH_COMPONENT_NOT_DIRECTORY
:
626 return "path compoment not a directory";
627 case IMLIB_LOAD_ERROR_PATH_POINTS_OUTSIDE_ADDRESS_SPACE
:
628 return "path points oustide address space";
629 case IMLIB_LOAD_ERROR_TOO_MANY_SYMBOLIC_LINKS
:
630 return "too many symbolic links";
631 case IMLIB_LOAD_ERROR_OUT_OF_MEMORY
:
632 return "out of memory";
633 case IMLIB_LOAD_ERROR_OUT_OF_FILE_DESCRIPTORS
:
634 return "out of file descriptors";
635 case IMLIB_LOAD_ERROR_PERMISSION_DENIED_TO_WRITE
:
636 return "write permission denied";
637 case IMLIB_LOAD_ERROR_OUT_OF_DISK_SPACE
:
638 return "out of disk space";
639 case IMLIB_LOAD_ERROR_UNKNOWN
:
640 return "unknown error, that's really bad";
641 case IMLIB_LOAD_ERROR_NONE
:
642 return "no error, oops";
645 return "unknown error";
648 /** Draw an image (PNG format only) from a file to a draw context
649 * \param ctx Draw context to draw to
650 * \param x x coordinate
651 * \param y y coordinate
652 * \param wanted_h wanted height: if > 0, image will be resized
653 * \param filename file name to draw
656 draw_image(DrawCtx
*ctx
, int x
, int y
, int wanted_h
, const char *filename
)
661 unsigned char *dataimg
, *rdataimg
;
663 Imlib_Load_Error e
= IMLIB_LOAD_ERROR_NONE
;
665 if(!(image
= imlib_load_image_with_error_return(filename
, &e
)))
666 return warn("cannot load image %s: %s\n", filename
, draw_imlib_load_strerror(e
));
668 imlib_context_set_image(image
);
669 h
= imlib_image_get_height();
670 w
= imlib_image_get_width();
674 data
= imlib_image_get_data_for_reading_only();
676 rdataimg
= dataimg
= p_new(unsigned char, size
* 4);
678 for(i
= 0; i
< size
; i
++, dataimg
+= 4)
680 dataimg
[3] = (data
[i
] >> 24) & 0xff; /* A */
681 /* cairo wants pre-multiplied alpha */
682 alpha
= dataimg
[3] / 255.0;
683 dataimg
[2] = ((data
[i
] >> 16) & 0xff) * alpha
; /* R */
684 dataimg
[1] = ((data
[i
] >> 8) & 0xff) * alpha
; /* G */
685 dataimg
[0] = (data
[i
] & 0xff) * alpha
; /* B */
688 draw_image_from_argb_data(ctx
, x
, y
, w
, h
, wanted_h
, rdataimg
);
694 /** Get an image size
695 * \param filename file name
696 * \return area_t structure with width and height set to image size
699 draw_get_image_size(const char *filename
)
701 area_t size
= { -1, -1, -1, -1, NULL
, NULL
};
703 Imlib_Load_Error e
= IMLIB_LOAD_ERROR_NONE
;
705 if((image
= imlib_load_image_with_error_return(filename
, &e
)))
707 imlib_context_set_image(image
);
709 size
.width
= imlib_image_get_width();
710 size
.height
= imlib_image_get_height();
715 warn("cannot load image %s: %s\n", filename
, draw_imlib_load_strerror(e
));
720 /** Rotate a drawable
721 * \param ctx Draw context to draw to
722 * \param dest Drawable to draw the result
723 * \param dest_w Drawable width
724 * \param dest_h Drawable height
725 * \param angle angle to rotate
726 * \param tx translate to this x coordinate
727 * \param ty translate to this y coordinate
728 * \return new rotated drawable
731 draw_rotate(DrawCtx
*ctx
, Drawable dest
, int dest_w
, int dest_h
,
732 double angle
, int tx
, int ty
)
734 cairo_surface_t
*surface
, *source
;
737 surface
= cairo_xlib_surface_create(ctx
->display
, dest
,
738 ctx
->visual
, dest_w
, dest_h
);
739 source
= cairo_xlib_surface_create(ctx
->display
, ctx
->drawable
,
740 ctx
->visual
, ctx
->width
, ctx
->height
);
741 cr
= cairo_create (surface
);
743 cairo_translate(cr
, tx
, ty
);
744 cairo_rotate(cr
, angle
);
746 cairo_set_source_surface(cr
, source
, 0.0, 0.0);
750 cairo_surface_destroy(source
);
751 cairo_surface_destroy(surface
);
754 /** Return the width of a text in pixel
755 * \param disp Display ref
756 * \param font font to use
757 * \param text the text
761 draw_textwidth(Display
*disp
, font_t
*font
, const char *text
)
763 cairo_surface_t
*surface
;
771 surface
= cairo_xlib_surface_create(disp
, DefaultScreen(disp
),
772 DefaultVisual(disp
, DefaultScreen(disp
)),
773 DisplayWidth(disp
, DefaultScreen(disp
)),
774 DisplayHeight(disp
, DefaultScreen(disp
)));
775 cr
= cairo_create(surface
);
776 layout
= pango_cairo_create_layout(cr
);
777 pango_layout_set_text(layout
, text
, -1);
778 pango_layout_set_font_description(layout
, font
->desc
);
779 pango_layout_get_pixel_extents(layout
, NULL
, &ext
);
780 g_object_unref(layout
);
782 cairo_surface_destroy(surface
);
787 /** Transform a string to a Alignment type.
788 * Recognized string are left, center or right. Everything else will be
789 * recognized as AlignAuto.
790 * \param align string with align text
791 * \return Alignment type
794 draw_align_get_from_str(const char *align
)
796 if(!a_strcmp(align
, "left"))
798 else if(!a_strcmp(align
, "center"))
800 else if(!a_strcmp(align
, "right"))
802 else if(!a_strcmp(align
, "flex"))
808 /** Initialize an X color
809 * \param disp display ref
810 * \param phys_screen Physical screen number
811 * \param colstr Color specification
812 * \param color XColor struct to store color to
813 * \return true if color allocation was successfull
816 draw_color_new(Display
*disp
, int phys_screen
, const char *colstr
, XColor
*color
)
821 if(!a_strlen(colstr
))
824 if(!(ret
= XAllocNamedColor(disp
,
825 DefaultColormap(disp
, phys_screen
),
829 warn("awesome: error, cannot allocate color '%s'\n", colstr
);
834 /** Init a style struct. Every value will be inherited from m
835 * if they are not set in the configuration section cfg.
836 * \param disp Display ref
837 * \param phys_screen Physical screen number
838 * \param cfg style configuration section
839 * \param c style to fill
840 * \param m style to use as template
843 draw_style_init(Display
*disp
, int phys_screen
, cfg_t
*cfg
,
844 style_t
*c
, style_t
*m
)
854 if((buf
= cfg_getstr(cfg
, "font")))
855 c
->font
= draw_font_new(disp
, buf
);
857 draw_color_new(disp
, phys_screen
,
858 cfg_getstr(cfg
, "fg"), &c
->fg
);
860 draw_color_new(disp
, phys_screen
,
861 cfg_getstr(cfg
, "bg"), &c
->bg
);
863 draw_color_new(disp
, phys_screen
,
864 cfg_getstr(cfg
, "border"), &c
->border
);
866 draw_color_new(disp
, phys_screen
,
867 cfg_getstr(cfg
, "shadow"), &c
->shadow
);
869 c
->shadow_offset
= cfg_getint(cfg
, "shadow_offset");
872 /** Remove a area from a list of them,
873 * spliting the space between several area that can overlap
874 * \param head list head
875 * \param elem area to remove
878 area_list_remove(area_t
**head
, area_t
*elem
)
880 area_t
*r
, inter
, *extra
, *rnext
;
882 for(r
= *head
; r
; r
= rnext
)
885 if(area_intersect_area(*r
, *elem
))
887 /* remove it from the list */
888 area_list_detach(head
, r
);
890 inter
= area_get_intersect_area(*r
, *elem
);
892 if(AREA_LEFT(inter
) > AREA_LEFT(*r
))
894 extra
= p_new(area_t
, 1);
897 extra
->width
= AREA_LEFT(inter
) - r
->x
;
898 extra
->height
= r
->height
;
899 area_list_append(head
, extra
);
902 if(AREA_TOP(inter
) > AREA_TOP(*r
))
904 extra
= p_new(area_t
, 1);
907 extra
->width
= r
->width
;
908 extra
->height
= AREA_TOP(inter
) - r
->y
;
909 area_list_append(head
, extra
);
912 if(AREA_RIGHT(inter
) < AREA_RIGHT(*r
))
914 extra
= p_new(area_t
, 1);
915 extra
->x
= AREA_RIGHT(inter
);
917 extra
->width
= AREA_RIGHT(*r
) - AREA_RIGHT(inter
);
918 extra
->height
= r
->height
;
919 area_list_append(head
, extra
);
922 if(AREA_BOTTOM(inter
) < AREA_BOTTOM(*r
))
924 extra
= p_new(area_t
, 1);
926 extra
->y
= AREA_BOTTOM(inter
);
927 extra
->width
= r
->width
;
928 extra
->height
= AREA_BOTTOM(*r
) - AREA_BOTTOM(inter
);
929 area_list_append(head
, extra
);
932 /* delete the elem since we removed it from the list */
938 // vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=80