fix(renderer): Alignment blocks
This commit is contained in:
parent
beedc5ab84
commit
3e4a4ce78f
@ -189,15 +189,16 @@ namespace cairo {
|
||||
cairo_text_extents_t extents;
|
||||
f->textwidth(subset, &extents);
|
||||
|
||||
// Draw the background
|
||||
if (t.bg_rect.h != 0.0) {
|
||||
save();
|
||||
{
|
||||
cairo_set_operator(m_c, t.bg_operator);
|
||||
*this << t.bg;
|
||||
cairo_rectangle(m_c, t.bg_rect.x + *t.x_advance, t.bg_rect.y + *t.y_advance,
|
||||
t.bg_rect.w + extents.x_advance, t.bg_rect.h);
|
||||
cairo_fill(m_c);
|
||||
}
|
||||
restore();
|
||||
}
|
||||
|
||||
// Render subset
|
||||
auto fontextents = f->extents();
|
||||
@ -243,11 +244,16 @@ namespace cairo {
|
||||
m_points.emplace_front(make_pair<double, double>(0.0, 0.0));
|
||||
position(&m_points.front().first, &m_points.front().second);
|
||||
}
|
||||
m_activegroups++;
|
||||
cairo_save(m_c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
context& restore(bool restore_point = false) {
|
||||
if (!m_activegroups) {
|
||||
throw application_error("Unmatched calls to save/restore");
|
||||
}
|
||||
m_activegroups--;
|
||||
cairo_restore(m_c);
|
||||
if (restore_point && !m_points.empty()) {
|
||||
*this << abspos{m_points.front().first, m_points.front().first};
|
||||
@ -296,17 +302,25 @@ namespace cairo {
|
||||
return *this;
|
||||
}
|
||||
|
||||
context& clear() {
|
||||
context& clear(bool paint = true) {
|
||||
cairo_save(m_c);
|
||||
cairo_set_operator(m_c, CAIRO_OPERATOR_CLEAR);
|
||||
if (paint) {
|
||||
cairo_paint(m_c);
|
||||
} else {
|
||||
cairo_fill_preserve(m_c);
|
||||
}
|
||||
cairo_restore(m_c);
|
||||
return *this;
|
||||
}
|
||||
|
||||
context& clip() {
|
||||
context& clip(bool preserve = false) {
|
||||
if (preserve) {
|
||||
cairo_clip_preserve(m_c);
|
||||
} else {
|
||||
cairo_clip(m_c);
|
||||
cairo_new_path(m_c);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -342,6 +356,7 @@ namespace cairo {
|
||||
const logger& m_log;
|
||||
vector<shared_ptr<font>> m_fonts;
|
||||
std::deque<pair<double, double>> m_points;
|
||||
int m_activegroups{0};
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -109,8 +109,9 @@ class renderer
|
||||
unique_ptr<cairo::context> m_context;
|
||||
unique_ptr<cairo::xcb_surface> m_surface;
|
||||
map<alignment, alignment_block> m_blocks;
|
||||
cairo_pattern_t* m_cornermask{};
|
||||
|
||||
cairo_operator_t m_comp_bg{CAIRO_OPERATOR_OVER};
|
||||
cairo_operator_t m_comp_bg{CAIRO_OPERATOR_SOURCE};
|
||||
cairo_operator_t m_comp_fg{CAIRO_OPERATOR_OVER};
|
||||
cairo_operator_t m_comp_ol{CAIRO_OPERATOR_OVER};
|
||||
cairo_operator_t m_comp_ul{CAIRO_OPERATOR_OVER};
|
||||
@ -127,8 +128,6 @@ class renderer
|
||||
|
||||
bool m_fixedcenter;
|
||||
string m_snapshot_dst;
|
||||
|
||||
cairo_pattern_t* m_cornermask{};
|
||||
};
|
||||
|
||||
POLYBAR_NS_END
|
||||
|
@ -665,7 +665,6 @@ bool bar::on(const signals::eventqueue::start&) {
|
||||
|
||||
m_log.trace("bar: Draw empty bar");
|
||||
m_renderer->begin(m_opts.inner_area());
|
||||
m_renderer->fill_background();
|
||||
m_renderer->end();
|
||||
|
||||
m_sig.emit(signals::ui::ready{});
|
||||
|
@ -259,26 +259,30 @@ void renderer::end() {
|
||||
|
||||
// Capture the concatenated block contents
|
||||
// so that it can be masked with the corner pattern
|
||||
if (m_cornermask != nullptr) {
|
||||
m_context->push();
|
||||
}
|
||||
|
||||
// Draw the background on the new layer to make up for
|
||||
// the areas not covered by the alignment blocks
|
||||
fill_background();
|
||||
|
||||
for (auto&& b : m_blocks) {
|
||||
if (block_w(b.first) && b.second.pattern != nullptr) {
|
||||
flush(b.first);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_pattern_t* blockcontents{};
|
||||
m_context->pop(&blockcontents);
|
||||
|
||||
if (m_cornermask != nullptr) {
|
||||
cairo_pattern_t* pattern{nullptr};
|
||||
m_context->pop(&pattern);
|
||||
m_context->save();
|
||||
{
|
||||
*m_context << pattern;
|
||||
*m_context << blockcontents;
|
||||
m_context->mask(m_cornermask);
|
||||
} else {
|
||||
*m_context << blockcontents;
|
||||
m_context->paint();
|
||||
}
|
||||
m_context->restore();
|
||||
}
|
||||
|
||||
m_context->destroy(&blockcontents);
|
||||
} else {
|
||||
fill_background();
|
||||
}
|
||||
|
||||
m_context->restore();
|
||||
@ -293,55 +297,47 @@ void renderer::end() {
|
||||
* Flush contents of given alignment block
|
||||
*/
|
||||
void renderer::flush(alignment a) {
|
||||
if (m_blocks[a].pattern == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_context->save();
|
||||
|
||||
double x = static_cast<int>(block_x(a) + 0.5);
|
||||
double y = static_cast<int>(block_y(a) + 0.5);
|
||||
double w = static_cast<int>(block_w(a) + 0.5);
|
||||
double h = static_cast<int>(block_h(a) + 0.5);
|
||||
double xw = x + w;
|
||||
bool fits{xw <= m_rect.x + m_rect.width};
|
||||
|
||||
m_log.trace_x("renderer: flush(%i geom=%gx%g+%g+%g)", static_cast<int>(a), w, h, x, y);
|
||||
m_log.trace("renderer: flush(%i geom=%gx%g+%g+%g, falloff=%i)", static_cast<int>(a), w, h, x, y, !fits);
|
||||
|
||||
m_surface->flush();
|
||||
m_context->save();
|
||||
{
|
||||
// Set block shape
|
||||
*m_context << cairo::abspos{0.0, 0.0};
|
||||
*m_context << cairo::rect{m_rect.x + x, m_rect.y + y, w, h};
|
||||
|
||||
m_context->clip();
|
||||
*m_context << CAIRO_OPERATOR_CLEAR;
|
||||
m_context->paint();
|
||||
m_context->reset_clip();
|
||||
*m_context << CAIRO_OPERATOR_OVER;
|
||||
// Restrict drawing to the block rectangle
|
||||
m_context->clip(true);
|
||||
|
||||
// Clear the area covered by the block
|
||||
m_context->clear();
|
||||
|
||||
*m_context << cairo::translate{x, 0.0};
|
||||
*m_context << m_blocks[a].pattern;
|
||||
|
||||
if (xw <= m_rect.width) {
|
||||
m_context->paint();
|
||||
} else {
|
||||
double sx = w - (xw - m_rect.width);
|
||||
vector<unsigned int> falloff{0xFFFFFFFF, 0x00FFFFFF};
|
||||
cairo_pattern_t* pattern{};
|
||||
|
||||
m_context->push();
|
||||
*m_context << cairo::linear_gradient{sx - 40.0, 0.0, sx, 0.0, falloff};
|
||||
*m_context << CAIRO_OPERATOR_SOURCE;
|
||||
m_context->paint();
|
||||
m_context->pop(&pattern);
|
||||
m_context->mask(pattern);
|
||||
m_context->destroy(&pattern);
|
||||
|
||||
// clang-format off
|
||||
rgba bg1{m_bar.background}; bg1.a = 0.0;
|
||||
rgba bg2{m_bar.background}; bg2.a = 0.4;
|
||||
// clang-format on
|
||||
*m_context << cairo::linear_gradient{sx - 40.0, 0.0, sx, 0.0, {bg1, bg2}};
|
||||
*m_context << CAIRO_OPERATOR_OVER;
|
||||
m_context->paint();
|
||||
if (!fits) {
|
||||
// Paint falloff gradient at the end of the visible block
|
||||
// to indicate that the content expands past the canvas
|
||||
double fx = w - (xw - m_rect.width);
|
||||
double fsize = std::max(5.0, std::min(std::abs(fx), 30.0));
|
||||
m_log.trace("renderer: Drawing falloff (pos=%g, size=%g)", fx, fsize);
|
||||
*m_context << cairo::linear_gradient{fx - fsize, 0.0, fx, 0.0, {0x00000000, 0xFF000000}};
|
||||
m_context->paint(0.25);
|
||||
}
|
||||
|
||||
*m_context << cairo::abspos{0.0, 0.0};
|
||||
m_context->destroy(&m_blocks[a].pattern);
|
||||
}
|
||||
m_context->restore();
|
||||
}
|
||||
|
||||
@ -372,6 +368,7 @@ void renderer::flush() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
m_surface->flush();
|
||||
m_connection.copy_area(m_pixmap, m_window, m_gcontext, 0, 0, 0, 0, m_bar.size.w, m_bar.size.h);
|
||||
m_connection.flush();
|
||||
|
||||
@ -391,15 +388,26 @@ void renderer::flush() {
|
||||
*/
|
||||
double renderer::block_x(alignment a) const {
|
||||
switch (a) {
|
||||
case alignment::CENTER:
|
||||
case alignment::CENTER: {
|
||||
double base_pos{0.0};
|
||||
double min_pos{0.0};
|
||||
if (!m_fixedcenter || m_rect.width / 2.0 + block_w(a) / 2.0 > m_rect.width - block_w(alignment::RIGHT)) {
|
||||
return std::max((m_rect.width - block_w(alignment::RIGHT) + block_w(alignment::LEFT)) / 2.0 - block_w(a) / 2.0,
|
||||
block_w(alignment::LEFT) + BLOCK_GAP);
|
||||
base_pos = (m_rect.width - block_w(alignment::RIGHT) + block_w(alignment::LEFT)) / 2.0;
|
||||
} else {
|
||||
return std::max(m_rect.width / 2.0 - block_w(a) / 2.0, block_w(alignment::LEFT));
|
||||
base_pos = m_rect.width / 2.0;
|
||||
}
|
||||
if ((min_pos = block_w(alignment::LEFT))) {
|
||||
min_pos += BLOCK_GAP;
|
||||
}
|
||||
return std::max(base_pos - block_w(a) / 2.0, min_pos);
|
||||
}
|
||||
case alignment::RIGHT: {
|
||||
double gap{0.0};
|
||||
if (block_w(alignment::LEFT) || block_w(alignment::CENTER)) {
|
||||
gap = BLOCK_GAP;
|
||||
}
|
||||
return std::max(m_rect.width - block_w(a), block_x(alignment::CENTER) + gap + block_w(alignment::CENTER));
|
||||
}
|
||||
case alignment::RIGHT:
|
||||
return std::max(m_rect.width - block_w(a), block_x(alignment::CENTER) + BLOCK_GAP + block_w(alignment::CENTER));
|
||||
default:
|
||||
return 0.0;
|
||||
}
|
||||
@ -570,13 +578,11 @@ void renderer::draw_text(const string& contents) {
|
||||
block.align = m_align;
|
||||
block.contents = contents;
|
||||
block.font = m_font;
|
||||
block.bg = 0;
|
||||
block.bg_rect = cairo::rect{0.0, 0.0, 0.0, 0.0};
|
||||
block.bg_operator = m_comp_bg;
|
||||
block.x_advance = &m_blocks[m_align].x;
|
||||
block.y_advance = &m_blocks[m_align].y;
|
||||
block.bg_rect = cairo::rect{0.0, 0.0, 0.0, 0.0};
|
||||
|
||||
if (m_bg && m_bg != m_bar.background) {
|
||||
if (m_bg) {
|
||||
block.bg = m_bg;
|
||||
block.bg_operator = m_comp_bg;
|
||||
block.bg_rect.x = m_rect.x;
|
||||
|
Loading…
Reference in New Issue
Block a user