36#include <fmt/format.h>
55static std::string
get_layer_id(
const NSVGshape &shape,
const int prefix)
57 return (shape.id_parent[0] ==
'\0') ? fmt::format(
"Layer_{:03d}", prefix) :
58 fmt::format(
"{:s}", shape.id_parent);
67 uint8_t(((pack) >> 24) & 0xFF)};
69 float(rgb_u[1]) / 255.0f,
70 float(rgb_u[2]) / 255.0f,
71 float(rgb_u[3]) / 255.0f};
91 avg_color /= stops.
size();
102 switch (NSVGpaintType(svg_paint.type)) {
103 case NSVG_PAINT_UNDEF:
105 case NSVG_PAINT_NONE:
107 case NSVG_PAINT_COLOR:
109 case NSVG_PAINT_LINEAR_GRADIENT:
111 case NSVG_PAINT_RADIAL_GRADIENT:
124 const int old_curves_num = curves.curves_num();
125 const int old_points_num = curves.points_num();
126 const Span<int> old_offsets = curves.offsets();
130 for (NSVGpath *path = shape.paths; path; path = path->next) {
131 if (path->npts == 0) {
134 BLI_assert(path->npts >= 1 && path->npts ==
int(path->npts / 3) * 3 + 1);
137 const int point_num = (path->npts + 2) / 3;
138 new_curve_offsets.
append(point_num);
143 new_curve_offsets.
append(0);
145 new_curve_offsets, old_points_num);
147 const IndexRange new_curves_range = {old_curves_num, new_points_by_curve.
size()};
149 const int points_num = new_points_by_curve.
total_size() + old_points_num;
152 if (old_curves_num > 0) {
156 .slice(old_curves_num, new_curve_offsets.
size())
157 .copy_from(new_curve_offsets);
159 curves.resize(points_num, curves_num);
160 curves.offsets_for_write().copy_from(new_offsets);
162 curves.tag_topology_changed();
164 return new_curves_range;
168 const NSVGshape &shape,
171 const int material_index)
175 const OffsetIndices points_by_curve = curves.points_by_curve();
179 curves.update_curve_types();
198 attributes.lookup_or_add_for_write_span<
ColorGeometry4f>(
"vertex_color",
203 materials.
span.slice(curves_range).fill(material_index);
205 fill_colors.span.slice(curves_range).fill(shape_color);
206 fill_opacities.
span.slice(curves_range).fill(shape_color.
a);
208 int curve_index = curves_range.
start();
209 for (NSVGpath *path = shape.paths; path; path = path->next) {
210 if (path->npts == 0) {
214 cyclic[curve_index] = bool(path->closed);
219 const IndexRange points = points_by_curve[curve_index];
220 for (
const int i : points.index_range()) {
221 const int point_index = points[i];
222 const float2 pos_center = svg_path_data[i * 3];
223 const float2 pos_handle_left = (i > 0) ? svg_path_data[i * 3 - 1] : pos_center;
224 const float2 pos_handle_right = (i < points.size() - 1) ? svg_path_data[i * 3 + 1] :
228 float3(pos_handle_left, 0.0f));
230 float3(pos_handle_right, 0.0f));
234 radii.span[point_index] = shape.strokeWidth * path_width_scale;
237 vertex_colors.span[point_index] = point_color;
238 point_opacities.span[point_index] = point_color.
a;
245 fill_colors.finish();
248 vertex_colors.finish();
249 point_opacities.finish();
250 curves.tag_positions_changed();
251 curves.tag_radii_changed();
256 const std::optional<Bounds<float3>> bounds = [&]() {
257 std::optional<Bounds<float3>> bounds;
270 const float3 offset = -bounds->center();
285 constexpr const char *svg_units =
"mm";
286 constexpr float svg_dpi = 96.0f;
292 NSVGimage *svg_data =
nullptr;
293 svg_data = nsvgParseFromFile(abs_filepath, svg_units, svg_dpi);
294 if (svg_data ==
nullptr) {
305 nsvgDelete(svg_data);
315 const float svg_scale = 0.001f * scene_unit_scale *
params_.
scale;
321 bool has_color_gradient =
false;
324 std::string prv_id =
"*";
326 for (NSVGshape *shape = svg_data->shapes; shape; shape = shape->next) {
328 if (prv_id != layer_id) {
336 TreeNode *layer_node = grease_pencil.find_node_by_name(layer_id);
337 if (layer_node && layer_node->
is_layer()) {
341 Layer &layer = grease_pencil.add_layer(layer_id);
348 if (drawing ==
nullptr) {
356 const bool is_fill = bool(shape->fill.type);
357 const bool is_stroke = bool(shape->stroke.type) || !is_fill;
358 const StringRefNull mat_name = (is_stroke ? (is_fill ?
"Both" :
"Stroke") :
"Fill");
359 const int material_index =
create_material(mat_name, is_stroke, is_fill);
361 if (
ELEM(shape->fill.type, NSVG_PAINT_LINEAR_GRADIENT, NSVG_PAINT_RADIAL_GRADIENT)) {
362 has_color_gradient =
true;
376 nsvgDelete(svg_data);
383 if (has_color_gradient) {
386 "SVG has gradients, Grease Pencil color will be approximated");
395 return importer.
read(filepath);
Low-level operations for curves.
Low-level operations for grease pencil.
const char * BKE_main_blendfile_path_from_global()
void BKE_report(ReportList *reports, eReportType type, const char *message)
#define BLI_assert_unreachable()
MINLINE void srgb_to_linearrgb_v4(float linear[4], const float srgb[4])
bool BLI_path_abs(char path[FILE_MAX], const char *basepath) ATTR_NONNULL(1
void void void BLI_path_split_file_part(const char *filepath, char *file, size_t file_maxncpy) ATTR_NONNULL(1
#define STRNCPY(dst, src)
@ GP_LAYER_TREE_NODE_USE_LIGHTS
MutableSpan< T > as_mutable_span()
constexpr int64_t one_after_last() const
constexpr bool is_empty() const
constexpr int64_t start() const
Span< NewT > constexpr cast() const
constexpr Span drop_back(int64_t n) const
constexpr int64_t size() const
constexpr IndexRange index_range() const
constexpr bool is_empty() const
constexpr const char * c_str() const
void append(const T &value)
void translate(const float3 &translation)
std::optional< Bounds< float3 > > bounds_min_max() const
bke::CurvesGeometry & strokes_for_write()
const bke::CurvesGeometry & strokes() const
void tag_positions_changed()
const Layer & as_layer() const
GreasePencilImporter(const IOContext &context, const ImportParams ¶ms)
int32_t create_material(StringRefNull name, bool stroke, bool fill)
Object * create_object(StringRefNull name)
const ImportParams params_
bool read(StringRefNull filepath)
OffsetIndices slice(const IndexRange range) const
draw_view in_light_buf[] float
Bounds< T > merge(const Bounds< T > &a, const Bounds< T > &b)
static void shape_attributes_to_curves(bke::CurvesGeometry &curves, const NSVGshape &shape, const IndexRange curves_range, const float4x4 &transform, const int material_index)
static void shift_to_bounds_center(GreasePencil &grease_pencil)
static ColorGeometry4f average_gradient_color(const NSVGgradient &svg_gradient)
bool import_svg(const IOContext &context, const ImportParams ¶ms, StringRefNull filepath)
static ColorGeometry4f unpack_nano_color(const uint pack)
static ColorGeometry4f convert_svg_color(const NSVGpaint &svg_paint)
static IndexRange extend_curves_geometry(bke::CurvesGeometry &curves, const NSVGshape &shape)
static std::string get_layer_id(const NSVGshape &shape, const int prefix)
MatBase< T, NumCol, NumRow > scale(const MatBase< T, NumCol, NumRow > &mat, const VectorT &scale)
T average(const VecBase< T, Size > &a)
VecBase< T, 3 > to_scale(const MatBase< T, NumCol, NumRow > &mat)
MatT from_rotation(const RotationT &rotation)
VecBase< T, 3 > transform_point(const CartesianBasis &basis, const VecBase< T, 3 > &v)
OffsetIndices< int > accumulate_counts_to_offsets(MutableSpan< int > counts_to_offsets, int start_offset=0)
VecBase< float, 4 > float4
ColorSceneLinear4f< eAlpha::Premultiplied > ColorGeometry4f
VecBase< float, 3 > float3
float wrap(float value, float max, float min)
MutableVArraySpan< T > span