1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
// SPDX-License-Identifier: GPL-2.0-or-later
/**
* SVG to Pixbuf renderer
*
* Author:
* Michael Kowalski
*
* Copyright (C) 2020-2021 Michael Kowalski
*
* Released under GNU GPL v2+, read the file 'COPYING' for more information.
*/
#include "svg-renderer.h"
#include "io/file.h"
#include "xml/repr.h"
#include "object/sp-root.h"
#include "display/cairo-utils.h"
#include "helper/pixbuf-ops.h"
#include "util/units.h"
namespace Inkscape {
Glib::ustring rgba_to_css_color(double r, double g, double b) {
char buffer[16];
sprintf(buffer, "#%02x%02x%02x",
static_cast<int>(r * 0xff + 0.5),
static_cast<int>(g * 0xff + 0.5),
static_cast<int>(b * 0xff + 0.5)
);
return Glib::ustring(buffer);
}
Glib::ustring rgba_to_css_color(const Gdk::RGBA& color) {
return rgba_to_css_color(color.get_red(), color.get_green(), color.get_blue());
}
Glib::ustring rgba_to_css_color(const SPColor& color) {
float rgb[3];
color.get_rgb_floatv(rgb);
return rgba_to_css_color(rgb[0], rgb[1], rgb[2]);
}
Glib::ustring double_to_css_value(double value) {
char buffer[32];
// arbitrarily chosen precision
sprintf(buffer, "%.4f", value);
return Glib::ustring(buffer);
}
std::shared_ptr<SPDocument> load_document(const char* svg_file_path) {
auto file = Gio::File::create_for_path(svg_file_path);
return std::shared_ptr<SPDocument>(ink_file_open(file, nullptr));
}
svg_renderer::svg_renderer(const char* svg_file_path): svg_renderer(load_document(svg_file_path)) {
}
svg_renderer::svg_renderer(std::shared_ptr<SPDocument> document) {
_document = document;
if (document) {
_root = _document->getRoot();
}
if (!_root) throw std::runtime_error("Cannot find root element in svg document");
}
size_t svg_renderer::set_style(const Glib::ustring& selector, const char* name, const Glib::ustring& value) {
auto objects = _document->getObjectsBySelector(selector);
for (auto el : objects) {
if (SPCSSAttr* css = sp_repr_css_attr(el->getRepr(), "style")) {
sp_repr_css_set_property(css, name, value.c_str());
el->changeCSS(css, "style");
sp_repr_css_attr_unref(css);
}
}
return objects.size();
}
double svg_renderer::get_width_px() const {
return _document->getWidth().value("px");
}
double svg_renderer::get_height_px() const {
return _document->getHeight().value("px");
}
Inkscape::Pixbuf *svg_renderer::do_render(double scale)
{
auto dpi = 96 * scale;
auto area = *(_document->preferredBounds());
auto checkerboard_ptr = _checkerboard ? &*_checkerboard : nullptr;
return sp_generate_internal_bitmap(_document.get(), area, dpi, {}, false, checkerboard_ptr, scale);
}
Glib::RefPtr<Gdk::Pixbuf> svg_renderer::render(double scale) {
auto pixbuf = do_render(scale);
if (!pixbuf) return Glib::RefPtr<Gdk::Pixbuf>();
// ref it
auto raw = Glib::wrap(pixbuf->getPixbufRaw(), true);
delete pixbuf;
return raw;
}
Cairo::RefPtr<Cairo::Surface> svg_renderer::render_surface(double scale) {
auto pixbuf = do_render(scale);
if (!pixbuf) return Cairo::RefPtr<Cairo::Surface>();
// ref it by saying that we have no reference
auto surface = Cairo::RefPtr<Cairo::Surface>(new Cairo::Surface(pixbuf->getSurfaceRaw(), false));
delete pixbuf;
return surface;
}
void svg_renderer::set_checkerboard_color(unsigned int rgba) {
_checkerboard.emplace(rgba);
}
} // namespace
|