32#include <fmt/format.h>
55 return fmt::format(
"#{:02X}{:02X}{:02X}", r, g,
b);
60 const float stroke_opacity,
67 node.append_attribute(
"stroke").set_value(stroke_hex.c_str());
68 node.append_attribute(
"stroke-opacity").set_value(stroke_color.
a * stroke_opacity);
70 node.append_attribute(
"fill").set_value(
"none");
71 node.append_attribute(
"stroke-linecap").set_value(round_cap ?
"round" :
"square");
76 const float layer_opacity)
82 node.append_attribute(
"fill").set_value(stroke_hex.c_str());
83 node.append_attribute(
"stroke").set_value(
"none");
84 node.append_attribute(
"fill-opacity").set_value(fill_color.
a * layer_opacity);
92 const float thickness,
93 const std::string &hexcolor)
95 pugi::xml_node rect_node = node.append_child(
"rect");
96 rect_node.append_attribute(
"x").set_value(x);
97 rect_node.append_attribute(
"y").set_value(y);
98 rect_node.append_attribute(
"width").set_value(width);
99 rect_node.append_attribute(
"height").set_value(height);
100 rect_node.append_attribute(
"fill").set_value(
"none");
101 if (thickness > 0.0f) {
102 rect_node.append_attribute(
"stroke").set_value(hexcolor.c_str());
103 rect_node.append_attribute(
"stroke-width").set_value(thickness);
129 std::optional<float> width);
130 pugi::xml_node
write_path(pugi::xml_node node,
140 const int frame_number = scene.r.cfra;
160 const Object *ob = info.object;
164 pugi::xml_node clip_node = node.append_child(
"clipPath");
165 clip_node.append_attribute(
"id").
set_value(
166 (
"clip-path" + std::to_string(frame_number)).c_str());
171 pugi::xml_node frame_node = node.append_child(
"g");
172 std::string frametxt =
"blender_frame_" + std::to_string(frame_number);
173 frame_node.append_attribute(
"id").set_value(frametxt.c_str());
177 frame_node.append_attribute(
"clip-path")
178 .set_value((
"url(#clip-path" + std::to_string(frame_number) +
")").c_str());
181 pugi::xml_node ob_node = frame_node.append_child(
"g");
185 ob_node.append_attribute(
"id").set_value(obtxt);
193 if (!layer->is_visible()) {
196 const Drawing *drawing = grease_pencil_eval->get_drawing_at(*layer, frame_number);
197 if (drawing ==
nullptr) {
202 const std::string txt =
"Layer: " + layer->name();
203 ob_node.append_child(pugi::node_comment).set_value(txt.c_str());
205 pugi::xml_node layer_node = ob_node.append_child(
"g");
206 layer_node.append_attribute(
"id").set_value(layer->name().c_str());
220 const float4x4 layer_to_world = layer.to_world_space(
object);
226 const std::optional<float> width,
227 const bool round_cap,
228 const bool is_outline) {
230 pugi::xml_node element_node =
write_path(layer_node, layer_to_world, positions, cyclic);
237 layer_node, layer_to_world, positions, cyclic, width);
254 pugi::xml_node decl =
main_doc_.prepend_child(pugi::node_declaration);
255 decl.append_attribute(
"version") =
"1.0";
256 decl.append_attribute(
"encoding") =
"UTF-8";
258 pugi::xml_node comment =
main_doc_.append_child(pugi::node_comment);
259 std::string txt = std::string(
" Generator: Blender, ") +
svg_exporter_name +
" - " +
261 comment.set_value(txt.c_str());
263 pugi::xml_node doctype =
main_doc_.append_child(pugi::node_doctype);
265 "svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" "
266 "\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"");
271 pugi::xml_node main_node =
main_doc_.append_child(
"svg");
272 main_node.append_attribute(
"version").set_value(
"1.0");
273 main_node.append_attribute(
"x").set_value(
"0px");
274 main_node.append_attribute(
"y").set_value(
"0px");
275 main_node.append_attribute(
"xmlns").set_value(
"http://www.w3.org/2000/svg");
277 std::string width = std::to_string(
render_rect_.size().x);
278 std::string height = std::to_string(
render_rect_.size().y);
280 main_node.append_attribute(
"width").set_value((width +
"px").c_str());
281 main_node.append_attribute(
"height").set_value((height +
"px").c_str());
282 std::string viewbox =
"0 0 " + width +
" " + height;
283 main_node.append_attribute(
"viewBox").set_value(viewbox.c_str());
292 pugi::xml_node element_node = node.append_child(
"polygon");
295 for (
const int i : positions.index_range()) {
301 txt.append(std::to_string(screen_co.x) +
"," +
305 element_node.append_attribute(
"points").set_value(txt.c_str());
314 const std::optional<float> width)
316 pugi::xml_node element_node = node.append_child(cyclic ?
"polygon" :
"polyline");
319 element_node.append_attribute(
"stroke-width").set_value(*width);
323 for (
const int i : positions.index_range()) {
329 txt.append(std::to_string(screen_co.x) +
"," +
333 element_node.append_attribute(
"points").set_value(txt.c_str());
343 pugi::xml_node element_node = node.append_child(
"path");
345 std::string txt =
"M";
346 for (
const int i : positions.index_range()) {
352 txt.append(std::to_string(screen_co.x) +
"," +
360 element_node.append_attribute(
"d").set_value(txt.c_str());
371 std::wstring wstr(filepath_16);
372 result =
main_doc_.save_file(wstr.c_str());
Low-level operations for curves.
Low-level operations for grease pencil.
General operations, lookup, etc. for materials.
void BLI_kdtree_nd_ free(KDTree *tree)
void linearrgb_to_srgb_v3_v3(float srgb[3], const float linear[3])
#define SNPRINTF(dst, format,...)
Object * DEG_get_evaluated_object(const Depsgraph *depsgraph, Object *object)
Object is a sort of wrapper for general info.
constexpr const char * c_str() const
GreasePencilExporter(const IOContext &context, const ExportParams ¶ms)
blender::Bounds< float2 > render_rect_
std::optional< float4x4 > camera_persmat_
const ExportParams params_
void prepare_render_params(Scene &scene, int frame_number)
void foreach_stroke_in_layer(const Object &object, const bke::greasepencil::Layer &layer, const bke::greasepencil::Drawing &drawing, WriteStrokeFn stroke_fn)
Vector< ObjectInfo > retrieve_objects() const
float2 project_to_screen(const float4x4 &transform, const float3 &position) const
pugi::xml_node write_polygon(pugi::xml_node node, const float4x4 &transform, Span< float3 > positions)
void export_grease_pencil_layer(pugi::xml_node node, const Object &object, const bke::greasepencil::Layer &layer, const bke::greasepencil::Drawing &drawing)
pugi::xml_document main_doc_
void export_grease_pencil_objects(pugi::xml_node node, int frame_number)
bool export_scene(Scene &scene, StringRefNull filepath)
void write_document_header()
pugi::xml_node write_main_node()
bool write_to_file(StringRefNull filepath)
pugi::xml_node write_path(pugi::xml_node node, const float4x4 &transform, Span< float3 > positions, bool cyclic)
pugi::xml_node write_polyline(pugi::xml_node node, const float4x4 &transform, Span< float3 > positions, bool cyclic, std::optional< float > width)
local_group_size(16, 16) .push_constant(Type b
static std::string rgb_to_hexstr(const float color[3])
static void write_fill_color_attribute(pugi::xml_node node, const ColorGeometry4f &fill_color, const float layer_opacity)
bool export_svg(const IOContext &context, const ExportParams ¶ms, Scene &scene, StringRefNull filepath)
constexpr const char * svg_exporter_name
static void write_rect(pugi::xml_node node, const float x, const float y, const float width, const float height, const float thickness, const std::string &hexcolor)
static void write_stroke_color_attribute(pugi::xml_node node, const ColorGeometry4f &stroke_color, const float stroke_opacity, const bool round_cap)
constexpr const char * svg_exporter_version
void set_value(const SocketType &input, const Node &other, const SocketType &other_input)
wchar_t * alloc_utf16_from_8(const char *in8, size_t add)