From 78bc8b5c744c6b78f7853acb68855e4116ea704c Mon Sep 17 00:00:00 2001 From: o9000 Date: Tue, 17 May 2016 21:59:43 +0200 Subject: [PATCH] Draw border on only some sides (issue #580, thanks @stophe) --- src/config.c | 13 +++++++++++++ src/util/area.c | 32 ++++++++++++++++++++++---------- src/util/area.h | 11 +++++++++++ src/util/common.c | 43 ++++++++++++++++++++++++++++++++++++++----- src/util/common.h | 1 + 5 files changed, 85 insertions(+), 15 deletions(-) diff --git a/src/config.c b/src/config.c index 99eadb6..42c3de1 100644 --- a/src/config.c +++ b/src/config.c @@ -239,6 +239,19 @@ void add_entry(char *key, char *value) read_border_color_press = 0; } else if (strcmp(key, "border_width") == 0) { g_array_index(backgrounds, Background, backgrounds->len - 1).border.width = atoi(value); + } else if (strcmp(key, "border_sides") == 0) { + Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1); + bg->border.mask = 0; + if (strchr(value, 'l') || strchr(value, 'L')) + bg->border.mask |= BORDER_LEFT; + if (strchr(value, 'r') || strchr(value, 'R')) + bg->border.mask |= BORDER_RIGHT; + if (strchr(value, 't') || strchr(value, 'T')) + bg->border.mask |= BORDER_TOP; + if (strchr(value, 'b') || strchr(value, 'B')) + bg->border.mask |= BORDER_BOTTOM; + if (!bg->border.mask) + bg->border.width = 0; } else if (strcmp(key, "background_color") == 0) { Background *bg = &g_array_index(backgrounds, Background, backgrounds->len - 1); extract_values(value, &value1, &value2, &value3); diff --git a/src/util/area.c b/src/util/area.c index 2aee622..d7a0b7b 100644 --- a/src/util/area.c +++ b/src/util/area.c @@ -36,6 +36,7 @@ Area *mouse_over_area = NULL; void init_background(Background *bg) { memset(bg, 0, sizeof(Background)); + bg->border.mask = BORDER_TOP | BORDER_BOTTOM | BORDER_LEFT | BORDER_RIGHT; } void initialize_positions(void *obj, int offset) @@ -454,12 +455,18 @@ void draw_background(Area *a, cairo_t *c) a->bg->fill_color.rgb[1], a->bg->fill_color.rgb[2], a->bg->fill_color.alpha); + // Not sure about this draw_rect(c, - a->bg->border.width, - a->bg->border.width, - a->width - (2.0 * a->bg->border.width), - a->height - (2.0 * a->bg->border.width), + a->bg->border.mask & BORDER_LEFT ? a->bg->border.width : 0, + a->bg->border.mask & BORDER_TOP ? a->bg->border.width : 0, + a->width + - (a->bg->border.mask & BORDER_LEFT ? a->bg->border.width : 0) + - (a->bg->border.mask & BORDER_RIGHT ? a->bg->border.width : 0), + a->height + - (a->bg->border.mask & BORDER_TOP ? a->bg->border.width : 0) + - (a->bg->border.mask & BORDER_BOTTOM ? a->bg->border.width : 0), a->bg->border.radius - a->bg->border.width / 1.571); + cairo_fill(c); } @@ -485,12 +492,17 @@ void draw_background(Area *a, cairo_t *c) a->bg->border.color.rgb[1], a->bg->border.color.rgb[2], a->bg->border.color.alpha); - draw_rect(c, - a->bg->border.width / 2.0, - a->bg->border.width / 2.0, - a->width - a->bg->border.width, - a->height - a->bg->border.width, - a->bg->border.radius); + draw_rect_on_sides(c, + a->bg->border.mask & BORDER_LEFT ? a->bg->border.width / 2. : 0, + a->bg->border.mask & BORDER_TOP ? a->bg->border.width / 2.0 : 0, + a->width + - (a->bg->border.mask & BORDER_LEFT ? a->bg->border.width / 2. : 0) + - (a->bg->border.mask & BORDER_RIGHT ? a->bg->border.width / 2. : 0), + a->height + - (a->bg->border.mask & BORDER_TOP ? a->bg->border.width / 2. : 0) + - (a->bg->border.mask & BORDER_BOTTOM ? a->bg->border.width / 2. : 0), + a->bg->border.radius, + a->bg->border.mask); cairo_stroke(c); } diff --git a/src/util/area.h b/src/util/area.h index 62ae306..58dffca 100644 --- a/src/util/area.h +++ b/src/util/area.h @@ -124,6 +124,15 @@ typedef struct Color { double alpha; } Color; +typedef enum BorderMask { + BORDER_TOP = 1 << 0, + BORDER_BOTTOM = 1 << 1, + BORDER_LEFT = 1 << 2, + BORDER_RIGHT = 1 << 3 +} BorderMask; + +#define BORDER_ALL (BORDER_TOP | BORDER_BOTTOM | BORDER_LEFT | BORDER_RIGHT) + typedef struct Border { // It's essential that the first member is color Color color; @@ -131,6 +140,8 @@ typedef struct Border { int width; // Corner radius int radius; + // Mask: bitwise OR of BorderMask + int mask; } Border; typedef struct Background { diff --git a/src/util/common.c b/src/util/common.c index 5e82a8d..0ef7dec 100644 --- a/src/util/common.c +++ b/src/util/common.c @@ -508,20 +508,53 @@ Imlib_Image adjust_icon(Imlib_Image original, int alpha, int saturation, int bri void draw_rect(cairo_t *c, double x, double y, double w, double h, double r) { - if (r > 0.0) { - double c1 = 0.55228475 * r; + draw_rect_on_sides(c, x, y, w, h, r, BORDER_ALL); +} - cairo_move_to(c, x + r, y); +void draw_rect_on_sides(cairo_t *c, double x, double y, double w, double h, double r, int border_mask) +{ + double c1 = 0.55228475 * r; + cairo_move_to(c, x + r, y); + // Top line + if (border_mask & BORDER_TOP) cairo_rel_line_to(c, w - 2 * r, 0); + else + cairo_rel_move_to(c, w - 2 * r, y); + // Top right corner + if (r > 0 && (border_mask & BORDER_TOP) && (border_mask & BORDER_RIGHT)) cairo_rel_curve_to(c, c1, 0.0, r, c1, r, r); + else + cairo_rel_move_to(c, r, r); + // Right line + if (border_mask & BORDER_RIGHT) cairo_rel_line_to(c, 0, h - 2 * r); + else + cairo_rel_move_to(c, 0, h - 2 * r); + // Bottom right corner + if (r > 0 && (border_mask & BORDER_RIGHT) && (border_mask & BORDER_BOTTOM)) cairo_rel_curve_to(c, 0.0, c1, c1 - r, r, -r, r); + else + cairo_rel_move_to(c, -r, r); + // Bottom line + if (border_mask & BORDER_BOTTOM) cairo_rel_line_to(c, -w + 2 * r, 0); + else + cairo_rel_move_to(c, -w + 2 * r, 0); + // Bottom left corner + if (r > 0 && (border_mask & BORDER_LEFT) && (border_mask & BORDER_BOTTOM)) cairo_rel_curve_to(c, -c1, 0, -r, -c1, -r, -r); + else + cairo_rel_move_to(c, -r, -r); + // Left line + if (border_mask & BORDER_LEFT) cairo_rel_line_to(c, 0, -h + 2 * r); + else + cairo_rel_move_to(c, 0, -h + 2 * r); + // Top left corner + if (r > 0 && (border_mask & BORDER_LEFT) && (border_mask & BORDER_TOP)) cairo_rel_curve_to(c, 0, -c1, r - c1, -r, r, -r); - } else - cairo_rectangle(c, x, y, w, h); + else + cairo_rel_move_to(c, r, -r); } void clear_pixmap(Pixmap p, int x, int y, int w, int h) diff --git a/src/util/common.h b/src/util/common.h index 4cf537e..c2a907f 100644 --- a/src/util/common.h +++ b/src/util/common.h @@ -108,6 +108,7 @@ void draw_text(PangoLayout *layout, cairo_t *c, int posx, int posy, Color *color // Draws a rounded rectangle void draw_rect(cairo_t *c, double x, double y, double w, double h, double r); +void draw_rect_on_sides(cairo_t *c, double x, double y, double w, double h, double r, int border_mask); // Clears the pixmap (with transparent color) void clear_pixmap(Pixmap p, int x, int y, int w, int h);