diff --git a/README.md b/README.md index 887308f..2e913f0 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ Raven is a simple user interface library. - pango - pangocairo - xlib + - librsvg # Installing diff --git a/meson.build b/meson.build index 124830d..8b7754c 100644 --- a/meson.build +++ b/meson.build @@ -10,11 +10,13 @@ add_project_arguments('-g3', language : 'cpp') cairomm_dep = dependency('cairomm-1.0') pangocairo_dep = dependency('pangocairo') xlib_dep = dependency('x11') +librsvg_dep = dependency('librsvg-2.0') raven_dependencies = [ cairomm_dep, xlib_dep, - pangocairo_dep + pangocairo_dep, + librsvg_dep ] headers = include_directories('src') @@ -25,6 +27,7 @@ raven_source_files = [ './src/Painter.cpp', './src/Window.cpp', './src/Widget.cpp', + './src/SvgWidget.cpp', './src/ScrollContainer.cpp', './src/Button.cpp', './src/DocumentLayout.cpp', @@ -52,6 +55,7 @@ raven_header_files = [ './src/ScrollContainer.hpp', './src/Styles.hpp', './src/Widget.hpp', + './src/SvgWidget.hpp', './src/Window.hpp' ] diff --git a/src/SvgWidget.cpp b/src/SvgWidget.cpp new file mode 100644 index 0000000..982fcc0 --- /dev/null +++ b/src/SvgWidget.cpp @@ -0,0 +1,59 @@ +#include "SvgWidget.hpp" +#include "cairomm/context.h" +#include "cairomm/enums.h" +#include "cairomm/surface.h" + +namespace Raven { + +void SvgWidget::on_init() { + 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); + + set_style(&clear_widget_style); + + if (!m_handle) { + std::cerr << "could not load svg file: " << m_path << std::endl; + exit(EXIT_FAILURE); + } + + set_did_init(true); +} + +void SvgWidget::on_after_layout() { + auto width = rect().width(); + auto height = rect().height(); + + if (width == m_known_width && height == m_known_height) { + return; + } + + m_known_width = width; + m_known_height = height; + + RsvgRectangle viewport = { + .x = 0.0, + .y = 0.0, + .width = width, + .height = height, + }; + + m_image_surface = Cairo::ImageSurface::create(Cairo::Format::FORMAT_ARGB32, width, height); + m_image_context = Cairo::Context::create(m_image_surface); + + rsvg_handle_render_document(m_handle, m_image_context->cobj(), &viewport, NULL); +} + +void SvgWidget::on_paint() { + if (!m_image_surface) + return; + + painter()->cairo()->set_source(m_image_surface, 0, 0); + painter()->cairo()->paint(); +} + +SvgWidget::~SvgWidget() { + g_object_unref(m_file); + g_object_unref(m_handle); +} + +} diff --git a/src/SvgWidget.hpp b/src/SvgWidget.hpp new file mode 100644 index 0000000..7675fd3 --- /dev/null +++ b/src/SvgWidget.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include +#include "cairomm/context.h" +#include "cairomm/enums.h" +#include "cairomm/refptr.h" +#include "cairomm/surface.h" +#include "raven/Widget.hpp" +#include "librsvg/rsvg.h" + +namespace Raven { + +class SvgWidget : public Raven::Widget { +public: + SvgWidget(std::string path) + : Raven::Widget() + , m_path(path) {} + + ~SvgWidget(); + + std::string &path() { return m_path; } + void set_path(std::string path) { m_path = path; repaint(); } +protected: + void on_init(); + void on_after_layout(); + void on_paint(); +private: + std::string m_path; + RsvgHandle *m_handle; + GFile *m_file; + Cairo::RefPtr m_image_context; + Cairo::RefPtr m_image_surface; + double m_known_width { 0.0 }; + double m_known_height { 0.0 }; +}; + +}