Draw border on only some sides (issue #580, thanks @stophe)

This commit is contained in:
o9000 2016-05-17 21:59:43 +02:00
parent 5a5d8fd978
commit 78bc8b5c74
5 changed files with 85 additions and 15 deletions

View file

@ -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);

View file

@ -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);
}

View file

@ -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 {

View file

@ -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)

View file

@ -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);