From cd71b96cf8d2c0d7fb201ba8a81482a55a5e7509 Mon Sep 17 00:00:00 2001 From: Simon Date: Tue, 16 Feb 2021 23:17:16 +0100 Subject: [PATCH] feat: Rounded bar border (#2359) * Added rounded border * Added feature to the changelog * Changed implementation for better customisation * Bugfixes * Removed commented code * Removed unused method * Removed duplicate lines * Moved degree to be a private constant Co-authored-by: Simon --- CHANGELOG.md | 2 + include/cairo/context.hpp | 20 ++++++--- include/cairo/types.hpp | 7 ++++ src/components/renderer.cpp | 84 +++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7eea9695..70244358 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `internal/cpu`: `format-warn`, `label-warn`, `warn-percentage = 80` - `internal/fs`: `format-warn`, `label-warn`, `warn-percentage = 90` - `internal/memory`: `format-warn`, `label-warn`, `warn-percentage = 90` +- `radius` now affects the bar border as well + ([`#1566`](https://github.com/polybar/polybar/issues/1566)) - Per-corner corner radius with `radius-{bottom,top}-{left,right}` ([`#2294`](https://github.com/polybar/polybar/issues/2294)) - `internal/network`: `speed-unit = B/s` can be used to customize how network diff --git a/include/cairo/context.hpp b/include/cairo/context.hpp index 42e692f5..da01e027 100644 --- a/include/cairo/context.hpp +++ b/include/cairo/context.hpp @@ -116,12 +116,19 @@ namespace cairo { } context& operator<<(const rounded_corners& c) { - double d = M_PI / 180.0; cairo_new_sub_path(m_c); - cairo_arc(m_c, c.x + c.w - c.radius.top_right, c.y + c.radius.top_right, c.radius.top_right, -90 * d, 0 * d); - cairo_arc(m_c, c.x + c.w - c.radius.bottom_right, c.y + c.h - c.radius.bottom_right, c.radius.bottom_right, 0 * d, 90 * d); - cairo_arc(m_c, c.x + c.radius.bottom_left, c.y + c.h - c.radius.bottom_left, c.radius.bottom_left, 90 * d, 180 * d); - cairo_arc(m_c, c.x + c.radius.top_left, c.y + c.radius.top_left, c.radius.top_left, 180 * d, 270 * d); + cairo_arc(m_c, c.x + c.w - c.radius.top_right, c.y + c.radius.top_right, c.radius.top_right, -90 * degree, 0 * degree); + cairo_arc(m_c, c.x + c.w - c.radius.bottom_right, c.y + c.h - c.radius.bottom_right, c.radius.bottom_right, 0 * degree, 90 * degree); + cairo_arc(m_c, c.x + c.radius.bottom_left, c.y + c.h - c.radius.bottom_left, c.radius.bottom_left, 90 * degree, 180 * degree); + cairo_arc(m_c, c.x + c.radius.top_left, c.y + c.radius.top_left, c.radius.top_left, 180 * degree, 270 * degree); + cairo_close_path(m_c); + return *this; + } + + context& operator<<(const circle_segment& segment) { + cairo_new_sub_path(m_c); + cairo_arc(m_c, segment.x, segment.y, segment.radius, segment.angle_from * degree, segment.angle_to * degree); + cairo_line_to(m_c, segment.x, segment.y); cairo_close_path(m_c); return *this; } @@ -338,6 +345,9 @@ namespace cairo { vector> m_fonts; std::deque> m_points; int m_activegroups{0}; + + private: + const double degree = M_PI / 180.0; }; } // namespace cairo diff --git a/include/cairo/types.hpp b/include/cairo/types.hpp index d0d81970..ac762dc3 100644 --- a/include/cairo/types.hpp +++ b/include/cairo/types.hpp @@ -54,6 +54,13 @@ namespace cairo { double h; struct radius radius; }; + struct circle_segment { + double x; + double y; + double angle_from; + double angle_to; + double radius; + }; struct textblock { alignment align; string contents; diff --git a/src/components/renderer.cpp b/src/components/renderer.cpp index 83feacf2..929ec90b 100644 --- a/src/components/renderer.cpp +++ b/src/components/renderer.cpp @@ -578,11 +578,65 @@ void renderer::fill_borders() { m_context->save(); *m_context << m_comp_border; + // Draw round border corners + + if (m_bar.radius.top_left) { + cairo::circle_segment borderTL; + borderTL.radius = m_bar.borders.at(edge::LEFT).size + m_bar.radius.top_left; + borderTL.x = m_bar.borders.at(edge::LEFT).size + m_bar.radius.top_left; + borderTL.y = m_bar.borders.at(edge::TOP).size + m_bar.radius.top_left; + borderTL.angle_from = 180; + borderTL.angle_to = 270; + (*m_context << borderTL << m_bar.borders.at(edge::LEFT).color).fill(); + } + + if (m_bar.radius.bottom_left) { + cairo::circle_segment borderBL; + borderBL.radius = m_bar.borders.at(edge::LEFT).size + m_bar.radius.bottom_left; + borderBL.x = m_bar.borders.at(edge::LEFT).size + m_bar.radius.bottom_left; + borderBL.y = m_bar.size.h - (m_bar.borders.at(edge::BOTTOM).size + m_bar.radius.bottom_left); + borderBL.angle_from = 90; + borderBL.angle_to = 180; + (*m_context << borderBL << m_bar.borders.at(edge::LEFT).color).fill(); + } + + if (m_bar.radius.top_right) { + cairo::circle_segment borderTR; + borderTR.radius = m_bar.borders.at(edge::RIGHT).size + m_bar.radius.top_right; + borderTR.x = m_bar.size.w - (m_bar.borders.at(edge::RIGHT).size + m_bar.radius.top_right); + borderTR.y = m_bar.borders.at(edge::TOP).size + m_bar.radius.top_right; + borderTR.angle_from = -90; + borderTR.angle_to = 0; + (*m_context << borderTR << m_bar.borders.at(edge::RIGHT).color).fill(); + } + + if (m_bar.radius.bottom_right) { + cairo::circle_segment borderBR; + borderBR.radius = m_bar.borders.at(edge::RIGHT).size + m_bar.radius.bottom_right; + borderBR.x = m_bar.size.w - (m_bar.borders.at(edge::RIGHT).size + m_bar.radius.bottom_right); + borderBR.y = m_bar.size.h - (m_bar.borders.at(edge::BOTTOM).size + m_bar.radius.bottom_right); + borderBR.angle_from = 0; + borderBR.angle_to = 90; + (*m_context << borderBR << m_bar.borders.at(edge::RIGHT).color).fill(); + } + + // Draw straight horizontal / vertical borders + if (m_bar.borders.at(edge::TOP).size) { cairo::rect top{0.0, 0.0, 0.0, 0.0}; top.x += m_bar.borders.at(edge::LEFT).size; top.w += m_bar.size.w - m_bar.borders.at(edge::LEFT).size - m_bar.borders.at(edge::RIGHT).size; top.h += m_bar.borders.at(edge::TOP).size; + + if (m_bar.radius.top_left) { + top.x += m_bar.radius.top_left; + top.w -= m_bar.radius.top_left; + } + + if (m_bar.radius.top_right) { + top.w -= m_bar.radius.top_right; + } + m_log.trace_x("renderer: border T(%.0f, #%08x)", top.h, m_bar.borders.at(edge::TOP).color); (*m_context << top << m_bar.borders.at(edge::TOP).color).fill(); } @@ -593,6 +647,16 @@ void renderer::fill_borders() { bottom.y += m_bar.size.h - m_bar.borders.at(edge::BOTTOM).size; bottom.w += m_bar.size.w - m_bar.borders.at(edge::LEFT).size - m_bar.borders.at(edge::RIGHT).size; bottom.h += m_bar.borders.at(edge::BOTTOM).size; + + if (m_bar.radius.bottom_left) { + bottom.x += m_bar.radius.bottom_left; + bottom.w -= m_bar.radius.bottom_left; + } + + if (m_bar.radius.bottom_right) { + bottom.w -= m_bar.radius.bottom_right; + } + m_log.trace_x("renderer: border B(%.0f, #%08x)", bottom.h, m_bar.borders.at(edge::BOTTOM).color); (*m_context << bottom << m_bar.borders.at(edge::BOTTOM).color).fill(); } @@ -601,6 +665,16 @@ void renderer::fill_borders() { cairo::rect left{0.0, 0.0, 0.0, 0.0}; left.w += m_bar.borders.at(edge::LEFT).size; left.h += m_bar.size.h; + + if (m_bar.radius.top_left) { + left.y += m_bar.radius.top_left + m_bar.borders.at(edge::TOP).size; + left.h -= m_bar.radius.top_left + m_bar.borders.at(edge::TOP).size; + } + + if (m_bar.radius.bottom_left) { + left.h -= m_bar.radius.bottom_left + m_bar.borders.at(edge::BOTTOM).size; + } + m_log.trace_x("renderer: border L(%.0f, #%08x)", left.w, m_bar.borders.at(edge::LEFT).color); (*m_context << left << m_bar.borders.at(edge::LEFT).color).fill(); } @@ -610,6 +684,16 @@ void renderer::fill_borders() { right.x += m_bar.size.w - m_bar.borders.at(edge::RIGHT).size; right.w += m_bar.borders.at(edge::RIGHT).size; right.h += m_bar.size.h; + + if (m_bar.radius.top_right) { + right.y += m_bar.radius.top_right + m_bar.borders.at(edge::TOP).size; + right.h -= m_bar.radius.top_right + m_bar.borders.at(edge::TOP).size; + } + + if (m_bar.radius.bottom_right) { + right.h -= m_bar.radius.bottom_right + m_bar.borders.at(edge::BOTTOM).size; + } + m_log.trace_x("renderer: border R(%.0f, #%08x)", right.w, m_bar.borders.at(edge::RIGHT).color); (*m_context << right << m_bar.borders.at(edge::RIGHT).color).fill(); }