add a way to pre-render svgs to fix duplication of surfaces

This commit is contained in:
hippoz 2022-07-31 23:14:16 +03:00
parent d07340217c
commit 43eec85adc
No known key found for this signature in database
GPG key ID: 7C52899193467641
7 changed files with 83 additions and 20 deletions

View file

@ -5,7 +5,7 @@ project(
) )
project_description = 'The Raven user interface library' project_description = 'The Raven user interface library'
add_project_arguments('-g3', language : 'cpp') add_project_arguments('-O3', language : 'cpp')
cairomm_dep = dependency('cairomm-1.0') cairomm_dep = dependency('cairomm-1.0')
pangocairo_dep = dependency('pangocairo') pangocairo_dep = dependency('pangocairo')
@ -22,6 +22,7 @@ raven_dependencies = [
headers = include_directories('src') headers = include_directories('src')
raven_source_files = [ raven_source_files = [
'./src/SvgUtil.cpp',
'./src/Box.cpp', './src/Box.cpp',
'./src/Styles.cpp', './src/Styles.cpp',
'./src/Painter.cpp', './src/Painter.cpp',
@ -38,6 +39,7 @@ raven_source_files = [
] ]
raven_header_files = [ raven_header_files = [
'./src/SvgUtil.hpp',
'./src/Logging.hpp', './src/Logging.hpp',
'./src/Box.hpp', './src/Box.hpp',
'./src/BoxLayout.hpp', './src/BoxLayout.hpp',

35
src/SvgUtil.cpp Normal file
View file

@ -0,0 +1,35 @@
#include "SvgUtil.hpp"
#include "librsvg/rsvg.h"
#include <iostream>
#include "cairomm/context.h"
namespace Raven {
Cairo::RefPtr<Cairo::ImageSurface> render_svg(std::string path, double x, double y, double width, double height) {
auto file = g_file_new_for_path(path.c_str());
auto handle = rsvg_handle_new_from_gfile_sync(file, RSVG_HANDLE_FLAGS_NONE, NULL, NULL);
if (!handle) {
std::cerr << "could not load svg file: " << path << std::endl;
exit(EXIT_FAILURE);
}
RsvgRectangle viewport = {
.x = x,
.y = y,
.width = width,
.height = height,
};
auto surface = Cairo::ImageSurface::create(Cairo::Format::FORMAT_ARGB32, width, height);
auto context = Cairo::Context::create(surface);
rsvg_handle_render_document(handle, context->cobj(), &viewport, NULL);
g_object_unref(file);
g_object_unref(handle);
return surface;
}
}

10
src/SvgUtil.hpp Normal file
View file

@ -0,0 +1,10 @@
#pragma once
#include "cairomm/refptr.h"
#include "cairomm/surface.h"
namespace Raven {
Cairo::RefPtr<Cairo::ImageSurface> render_svg(std::string path, double x, double y, double width, double height);
}

View file

@ -6,11 +6,16 @@
namespace Raven { namespace Raven {
void SvgWidget::on_init() { void SvgWidget::on_init() {
set_style(&clear_widget_style);
if (m_user_defined_surface) {
set_did_init(true);
return;
}
m_file = g_file_new_for_path(m_path.c_str()); m_file = g_file_new_for_path(m_path.c_str());
m_handle = rsvg_handle_new_from_gfile_sync(m_file, RSVG_HANDLE_FLAGS_NONE, NULL, NULL); m_handle = rsvg_handle_new_from_gfile_sync(m_file, RSVG_HANDLE_FLAGS_NONE, NULL, NULL);
set_style(&clear_widget_style);
if (!m_handle) { if (!m_handle) {
std::cerr << "could not load svg file: " << m_path << std::endl; std::cerr << "could not load svg file: " << m_path << std::endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@ -20,6 +25,10 @@ void SvgWidget::on_init() {
} }
void SvgWidget::on_after_layout() { void SvgWidget::on_after_layout() {
if (m_user_defined_surface) {
return;
}
auto width = rect().width(); auto width = rect().width();
auto height = rect().height(); auto height = rect().height();
@ -52,7 +61,9 @@ void SvgWidget::on_paint() {
} }
SvgWidget::~SvgWidget() { SvgWidget::~SvgWidget() {
if (m_file)
g_object_unref(m_file); g_object_unref(m_file);
if (m_handle)
g_object_unref(m_handle); g_object_unref(m_handle);
} }

View file

@ -16,6 +16,11 @@ public:
: Raven::Widget() : Raven::Widget()
, m_path(path) {} , m_path(path) {}
SvgWidget(Cairo::RefPtr<Cairo::ImageSurface> image_surface)
: Raven::Widget()
, m_image_surface(image_surface)
, m_user_defined_surface(true) {}
~SvgWidget(); ~SvgWidget();
std::string &path() { return m_path; } std::string &path() { return m_path; }
@ -26,12 +31,13 @@ protected:
void on_paint(); void on_paint();
private: private:
std::string m_path; std::string m_path;
RsvgHandle *m_handle; RsvgHandle *m_handle { nullptr };
GFile *m_file; GFile *m_file { nullptr };
Cairo::RefPtr<Cairo::Context> m_image_context; Cairo::RefPtr<Cairo::Context> m_image_context { nullptr };
Cairo::RefPtr<Cairo::ImageSurface> m_image_surface; Cairo::RefPtr<Cairo::ImageSurface> m_image_surface { nullptr };
double m_known_width { 0.0 }; double m_known_width { 0.0 };
double m_known_height { 0.0 }; double m_known_height { 0.0 };
bool m_user_defined_surface { false };
}; };
} }

View file

@ -115,6 +115,7 @@ void Widget::remove_child(std::shared_ptr<Widget> child) {
void Widget::clear_children() { void Widget::clear_children() {
m_children.clear(); m_children.clear();
m_children.shrink_to_fit();
reflow(); reflow();
} }

View file

@ -29,24 +29,22 @@ int main() {
top_bar->set_layout<Raven::BoxLayout>(Raven::Direction::Horizontal); top_bar->set_layout<Raven::BoxLayout>(Raven::Direction::Horizontal);
auto container_widget = main_widget->add<Raven::Widget>(); auto container_widget = main_widget->add<Raven::Widget>();
auto container_layout = container_widget->set_layout<Raven::BoxLayout>(Raven::Direction::Vertical); container_widget->set_layout<Raven::DocumentLayout>();
container_layout->set_spacing(5);
container_layout->set_margin(18);
container_widget->resize(400, 400);
auto new_button = top_bar->add<Raven::Button>("add"); auto new_button = top_bar->add<Raven::Button>("add");
new_button->rect().set_max_width(50); new_button->rect().set_max_width(50);
new_button->on_click = [container_widget]() { new_button->on_click = [&window, container_widget]() {
window.queue_microtask([container_widget]() {
for (int i = 0; i < 5000; i++) {
container_widget->add<Raven::Button>("hello"); container_widget->add<Raven::Button>("hello");
}
});
}; };
auto remove_button = top_bar->add<Raven::Button>("remove"); auto remove_button = top_bar->add<Raven::Button>("remove");
remove_button->on_click = [container_widget]() { remove_button->on_click = [container_widget]() {
if (container_widget->children().size() > 0) { container_widget->clear_children();
container_widget->remove_child(container_widget->children()[0]);
}
}; };
auto dummy_button = top_bar->add<Raven::Button>("dummy");
dummy_button->rect().set_max_width(60);
window.run(true); window.run(true);
return 0; return 0;