refactor(renderer): Use redirection groups instead of pixmaps
This commit is contained in:
parent
d2eeac9b22
commit
c7f33e2567
@ -111,6 +111,11 @@ namespace cairo {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context& operator<<(const translate& d) {
|
||||||
|
cairo_translate(m_c, d.x, d.y);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
context& operator<<(const linear_gradient& l) {
|
context& operator<<(const linear_gradient& l) {
|
||||||
if (l.steps.size() >= 2) {
|
if (l.steps.size() >= 2) {
|
||||||
auto pattern = cairo_pattern_create_linear(l.x1, l.y1, l.x2, l.y2);
|
auto pattern = cairo_pattern_create_linear(l.x1, l.y1, l.x2, l.y2);
|
||||||
@ -274,10 +279,30 @@ namespace cairo {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context& mask(cairo_pattern_t* pattern) {
|
||||||
|
cairo_mask(m_c, pattern);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
context& pop(cairo_pattern_t** pattern) {
|
||||||
|
*pattern = cairo_pop_group(m_c);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
context& push() {
|
||||||
|
cairo_push_group(m_c);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
context& destroy(cairo_pattern_t** pattern) {
|
||||||
|
cairo_pattern_destroy(*pattern);
|
||||||
|
*pattern = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
context& clear() {
|
context& clear() {
|
||||||
cairo_save(m_c);
|
cairo_save(m_c);
|
||||||
cairo_set_operator(m_c, CAIRO_OPERATOR_SOURCE);
|
cairo_set_operator(m_c, CAIRO_OPERATOR_CLEAR);
|
||||||
cairo_set_source_rgba(m_c, 0.0, 0.0, 0.0, 0.0);
|
|
||||||
cairo_paint(m_c);
|
cairo_paint(m_c);
|
||||||
cairo_restore(m_c);
|
cairo_restore(m_c);
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -41,6 +41,10 @@ namespace cairo {
|
|||||||
double dx;
|
double dx;
|
||||||
double dy;
|
double dy;
|
||||||
};
|
};
|
||||||
|
struct translate {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
};
|
||||||
struct linear_gradient {
|
struct linear_gradient {
|
||||||
double x1;
|
double x1;
|
||||||
double y1;
|
double y1;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <cairo/cairo.h>
|
||||||
|
|
||||||
#include "cairo/fwd.hpp"
|
#include "cairo/fwd.hpp"
|
||||||
#include "common.hpp"
|
#include "common.hpp"
|
||||||
@ -21,7 +22,7 @@ class logger;
|
|||||||
using std::map;
|
using std::map;
|
||||||
|
|
||||||
struct alignment_block {
|
struct alignment_block {
|
||||||
xcb_pixmap_t pixmap;
|
cairo_pattern_t* pattern;
|
||||||
double x;
|
double x;
|
||||||
double y;
|
double y;
|
||||||
};
|
};
|
||||||
@ -58,7 +59,9 @@ class renderer
|
|||||||
double block_x(alignment a) const;
|
double block_x(alignment a) const;
|
||||||
double block_y(alignment a) const;
|
double block_y(alignment a) const;
|
||||||
double block_w(alignment a) const;
|
double block_w(alignment a) const;
|
||||||
|
double block_h(alignment a) const;
|
||||||
|
|
||||||
|
void flush(alignment a);
|
||||||
void highlight_clickable_areas();
|
void highlight_clickable_areas();
|
||||||
|
|
||||||
bool on(const signals::ui::request_snapshot& evt);
|
bool on(const signals::ui::request_snapshot& evt);
|
||||||
@ -122,6 +125,8 @@ class renderer
|
|||||||
|
|
||||||
bool m_fixedcenter;
|
bool m_fixedcenter;
|
||||||
string m_snapshot_dst;
|
string m_snapshot_dst;
|
||||||
|
|
||||||
|
cairo_pattern_t* m_cornermask{};
|
||||||
};
|
};
|
||||||
|
|
||||||
POLYBAR_NS_END
|
POLYBAR_NS_END
|
||||||
|
@ -102,15 +102,9 @@ renderer::renderer(
|
|||||||
|
|
||||||
m_log.trace("renderer: Allocate alignment blocks");
|
m_log.trace("renderer: Allocate alignment blocks");
|
||||||
{
|
{
|
||||||
const auto create_block = [&](alignment a) {
|
m_blocks.emplace(alignment::LEFT, alignment_block{nullptr, 0.0, 0.0});
|
||||||
auto pid = m_connection.generate_id();
|
m_blocks.emplace(alignment::CENTER, alignment_block{nullptr, 0.0, 0.0});
|
||||||
m_connection.create_pixmap_checked(m_depth, pid, m_pixmap, m_bar.size.w, m_bar.size.h);
|
m_blocks.emplace(alignment::RIGHT, alignment_block{nullptr, 0.0, 0.0});
|
||||||
m_blocks.emplace(a, alignment_block{pid, 0.0, 0.0});
|
|
||||||
};
|
|
||||||
|
|
||||||
create_block(alignment::LEFT);
|
|
||||||
create_block(alignment::CENTER);
|
|
||||||
create_block(alignment::RIGHT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_log.trace("renderer: Allocate cairo components");
|
m_log.trace("renderer: Allocate cairo components");
|
||||||
@ -155,7 +149,8 @@ renderer::renderer(
|
|||||||
auto fonts_loaded = false;
|
auto fonts_loaded = false;
|
||||||
for (const auto& f : fonts) {
|
for (const auto& f : fonts) {
|
||||||
vector<string> fd{string_util::split(f, ';')};
|
vector<string> fd{string_util::split(f, ';')};
|
||||||
auto font = cairo::make_font(*m_context, string(fd[0]), fd.size() > 1 ? std::atoi(fd[1].c_str()) : 0, dpi_x, dpi_y);
|
auto font =
|
||||||
|
cairo::make_font(*m_context, string(fd[0]), fd.size() > 1 ? std::atoi(fd[1].c_str()) : 0, dpi_x, dpi_y);
|
||||||
m_log.info("Loaded font \"%s\" (name=%s, file=%s)", fd[0], font->name(), font->file());
|
m_log.info("Loaded font \"%s\" (name=%s, file=%s)", fd[0], font->name(), font->file());
|
||||||
*m_context << move(font);
|
*m_context << move(font);
|
||||||
fonts_loaded = true;
|
fonts_loaded = true;
|
||||||
@ -214,20 +209,35 @@ void renderer::begin() {
|
|||||||
m_ul = m_bar.underline.color;
|
m_ul = m_bar.underline.color;
|
||||||
m_ol = m_bar.overline.color;
|
m_ol = m_bar.overline.color;
|
||||||
|
|
||||||
|
// Clear canvas
|
||||||
|
m_context->clear();
|
||||||
m_context->save();
|
m_context->save();
|
||||||
|
|
||||||
// Clear canvas
|
// Create corner mask
|
||||||
m_surface->set_drawable(m_pixmap, m_bar.size.w, m_bar.size.h);
|
if (m_bar.radius != 0.0) {
|
||||||
m_context->clear();
|
m_context->save();
|
||||||
|
m_context->push();
|
||||||
|
// clang-format off
|
||||||
|
*m_context << cairo::rounded_corners{
|
||||||
|
static_cast<double>(m_rect.x),
|
||||||
|
static_cast<double>(m_rect.y),
|
||||||
|
static_cast<double>(m_rect.width),
|
||||||
|
static_cast<double>(m_rect.height), m_bar.radius};
|
||||||
|
// clang-format on
|
||||||
|
*m_context << rgba{1.0, 1.0, 1.0, 1.0};
|
||||||
|
m_context->fill();
|
||||||
|
m_context->pop(&m_cornermask);
|
||||||
|
m_context->restore();
|
||||||
|
}
|
||||||
|
|
||||||
fill_borders();
|
fill_borders();
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
m_context->clip(cairo::rect{
|
m_context->clip(cairo::rect{
|
||||||
static_cast<double>(m_rect.x),
|
static_cast<double>(m_rect.x),
|
||||||
static_cast<double>(m_rect.y),
|
static_cast<double>(m_rect.y),
|
||||||
static_cast<double>(m_rect.width),
|
static_cast<double>(m_rect.width),
|
||||||
static_cast<double>(m_rect.height)});
|
static_cast<double>(m_rect.height)});
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
fill_background();
|
fill_background();
|
||||||
@ -247,8 +257,6 @@ void renderer::end() {
|
|||||||
rgba bg1{m_bar.background}; bg1.a = 0.0;
|
rgba bg1{m_bar.background}; bg1.a = 0.0;
|
||||||
rgba bg2{m_bar.background}; bg2.a = 1.0;
|
rgba bg2{m_bar.background}; bg2.a = 1.0;
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
m_surface->set_drawable(b.second.pixmap, m_bar.size.w, m_bar.size.h);
|
|
||||||
m_context->save();
|
m_context->save();
|
||||||
*m_context << cairo::linear_gradient{x - 40.0, 0.0, x, 0.0, {bg1, bg2}};
|
*m_context << cairo::linear_gradient{x - 40.0, 0.0, x, 0.0, {bg1, bg2}};
|
||||||
m_context->paint();
|
m_context->paint();
|
||||||
@ -262,39 +270,47 @@ void renderer::end() {
|
|||||||
a.end_x += block_x(a.align) + m_rect.x;
|
a.end_x += block_x(a.align) + m_rect.x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flush(m_align);
|
||||||
|
|
||||||
m_context->restore();
|
m_context->restore();
|
||||||
|
m_surface->flush();
|
||||||
|
|
||||||
flush();
|
flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flush contents of given alignment block
|
||||||
|
*/
|
||||||
|
void renderer::flush(alignment a) {
|
||||||
|
if (a != alignment::NONE) {
|
||||||
|
double x = block_x(a);
|
||||||
|
double y = block_y(a);
|
||||||
|
double w = block_w(a);
|
||||||
|
double h = block_h(a);
|
||||||
|
|
||||||
|
m_surface->flush();
|
||||||
|
m_context->pop(&m_blocks[m_align].pattern);
|
||||||
|
|
||||||
|
m_context->save();
|
||||||
|
{
|
||||||
|
*m_context << cairo::rect{m_rect.x + x, m_rect.y + y, w, h};
|
||||||
|
*m_context << cairo::translate{x, 0.0};
|
||||||
|
*m_context << m_blocks[a].pattern;
|
||||||
|
m_context->paint();
|
||||||
|
m_surface->flush();
|
||||||
|
}
|
||||||
|
m_context->restore();
|
||||||
|
m_surface->flush();
|
||||||
|
m_context->destroy(&m_blocks[a].pattern);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flush pixmap contents onto the target window
|
* Flush pixmap contents onto the target window
|
||||||
*/
|
*/
|
||||||
void renderer::flush() {
|
void renderer::flush() {
|
||||||
m_log.trace_x("renderer: flush");
|
m_log.trace_x("renderer: flush");
|
||||||
|
|
||||||
m_surface->set_drawable(m_pixmap, m_bar.size.w, m_bar.size.h);
|
|
||||||
m_surface->flush();
|
|
||||||
|
|
||||||
for (auto&& b : m_blocks) {
|
|
||||||
double x = m_rect.x + block_x(b.first);
|
|
||||||
double y = m_rect.y + block_y(b.first);
|
|
||||||
double w = m_rect.x + m_rect.width - x;
|
|
||||||
double h = m_rect.y + m_rect.height - y;
|
|
||||||
|
|
||||||
if (w > 0.0) {
|
|
||||||
m_log.trace_x("renderer: copy alignment block (x=%.0f y=%.0f w=%.0f h=%.0f)", x, y, w, h);
|
|
||||||
m_connection.copy_area(b.second.pixmap, m_pixmap, m_gcontext, m_rect.x, m_rect.y, x, y, w, h);
|
|
||||||
m_connection.flush();
|
|
||||||
} else {
|
|
||||||
m_log.trace_x("renderer: ignoring empty alignment block");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_surface->dirty();
|
|
||||||
m_surface->flush();
|
|
||||||
|
|
||||||
highlight_clickable_areas();
|
highlight_clickable_areas();
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -363,6 +379,13 @@ double renderer::block_w(alignment a) const {
|
|||||||
return m_blocks.at(a).x;
|
return m_blocks.at(a).x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get block height for given alignment
|
||||||
|
*/
|
||||||
|
double renderer::block_h(alignment) const {
|
||||||
|
return m_rect.height;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reserve space at given edge
|
* Reserve space at given edge
|
||||||
*/
|
*/
|
||||||
@ -405,16 +428,6 @@ void renderer::fill_background() {
|
|||||||
m_context->save();
|
m_context->save();
|
||||||
*m_context << static_cast<cairo_operator_t>(m_comp_bg);
|
*m_context << static_cast<cairo_operator_t>(m_comp_bg);
|
||||||
|
|
||||||
if (m_bar.radius != 0.0) {
|
|
||||||
// clang-format off
|
|
||||||
*m_context << cairo::rounded_corners{
|
|
||||||
static_cast<double>(m_rect.x),
|
|
||||||
static_cast<double>(m_rect.y),
|
|
||||||
static_cast<double>(m_rect.width),
|
|
||||||
static_cast<double>(m_rect.height), m_bar.radius};
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_bar.background_steps.empty()) {
|
if (!m_bar.background_steps.empty()) {
|
||||||
m_log.trace_x("renderer: gradient background (steps=%lu)", m_bar.background_steps.size());
|
m_log.trace_x("renderer: gradient background (steps=%lu)", m_bar.background_steps.size());
|
||||||
*m_context << cairo::linear_gradient{0.0, 0.0 + m_rect.y, 0.0, 0.0 + m_rect.height, m_bar.background_steps};
|
*m_context << cairo::linear_gradient{0.0, 0.0 + m_rect.y, 0.0, 0.0 + m_rect.height, m_bar.background_steps};
|
||||||
@ -423,8 +436,8 @@ void renderer::fill_background() {
|
|||||||
*m_context << m_bar.background;
|
*m_context << m_bar.background;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_bar.radius != 0.0) {
|
if (m_cornermask != nullptr) {
|
||||||
m_context->fill();
|
m_context->mask(m_cornermask);
|
||||||
} else {
|
} else {
|
||||||
m_context->paint();
|
m_context->paint();
|
||||||
}
|
}
|
||||||
@ -621,12 +634,11 @@ bool renderer::on(const signals::parser::change_alignment& evt) {
|
|||||||
auto align = static_cast<const alignment&>(evt.cast());
|
auto align = static_cast<const alignment&>(evt.cast());
|
||||||
if (align != m_align) {
|
if (align != m_align) {
|
||||||
m_log.trace_x("renderer: change_alignment(%i)", static_cast<int>(align));
|
m_log.trace_x("renderer: change_alignment(%i)", static_cast<int>(align));
|
||||||
|
flush(m_align);
|
||||||
|
m_context->push();
|
||||||
m_align = align;
|
m_align = align;
|
||||||
m_blocks[m_align].x = 0.0;
|
m_blocks[m_align].x = 0.0;
|
||||||
m_blocks[m_align].y = 0.0;
|
m_blocks[m_align].y = 0.0;
|
||||||
m_surface->set_drawable(m_blocks.at(m_align).pixmap, m_bar.size.w, m_bar.size.h);
|
|
||||||
m_context->clear();
|
|
||||||
fill_background();
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user