UI: SVG Thumbnails #109567

Merged
Harley Acheson merged 11 commits from Harley/blender:SvgThumbs into main 2023-07-12 22:39:30 +02:00
2 changed files with 43 additions and 18 deletions
Showing only changes of commit a5965efc60 - Show all commits

View File

@ -185,18 +185,6 @@ const ImFileType IMB_FILE_TYPES[] = {
/*filetype*/ IMB_FTYPE_PSD,
/*default_save_role*/ COLOR_ROLE_DEFAULT_FLOAT,
},
{
/*init*/ nullptr,
/*exit*/ nullptr,
/*is_a*/ imb_is_a_svg,
/*load*/ imb_load_svg,
/*load_filepath*/ nullptr,
/*load_filepath_thumbnail*/ imb_load_filepath_thumbnail_svg,
/*save*/ nullptr,
/*flag*/ 0,
/*filetype*/ IMB_FTYPE_SVG,
/*default_save_role*/ COLOR_ROLE_DEFAULT_BYTE,
},
#ifdef WITH_WEBP
{
/*init*/ nullptr,
@ -211,6 +199,18 @@ const ImFileType IMB_FILE_TYPES[] = {
/*default_save_role*/ COLOR_ROLE_DEFAULT_BYTE,
},
#endif
{
Harley marked this conversation as resolved
Review

There should be a code-comment explaining why only the thumbnail callback is set as it's not obvious.

There should be a code-comment explaining why only the thumbnail callback is set as it's not obvious.
/*init*/ nullptr,
/*exit*/ nullptr,
/*is_a*/ imb_is_a_svg,
/*load*/ imb_load_svg,
/*load_filepath*/ nullptr,
/*load_filepath_thumbnail*/ imb_load_filepath_thumbnail_svg,
/*save*/ nullptr,
/*flag*/ 0,
/*filetype*/ IMB_FTYPE_SVG,
/*default_save_role*/ COLOR_ROLE_DEFAULT_BYTE,
},
{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, 0, 0, 0},
};

View File

@ -17,13 +17,19 @@ extern "C" {
bool imb_is_a_svg(const uchar *mem, size_t size)
Harley marked this conversation as resolved Outdated

Also note here, that only thumbnails are supported and why.

Also note here, that only thumbnails are supported and why.

It's not so obvious where this kind of info should be included, I'd prefer the file header, as this comment isn't a doc-string for the function, e.g.

/* SPDX-FileCopyrightText: 2023 Blender Foundation
 *
 * SPDX-License-Identifier: GPL-2.0-or-later */

/** \file
 * \ingroup imbuf
 *
 * SVG vector graphics format support for the purpose of thumbnail-display.
 * While loading these as an #ImBuf is trivial to support, it would expose
 * limitations of NANOSVG and users may end up needing more advanced options
 * spesific to loading vector graphics (such as resolution control), see #109567 for details.
 */
It's not so obvious where this kind of info should be included, I'd prefer the file header, as this comment isn't a doc-string for the function, e.g. ``` /* SPDX-FileCopyrightText: 2023 Blender Foundation * * SPDX-License-Identifier: GPL-2.0-or-later */ /** \file * \ingroup imbuf * * SVG vector graphics format support for the purpose of thumbnail-display. * While loading these as an #ImBuf is trivial to support, it would expose * limitations of NANOSVG and users may end up needing more advanced options * spesific to loading vector graphics (such as resolution control), see #109567 for details. */ ```
{
char *str = (char *)mem;
str[size - 1] = '\0';
return strstr(str, "<svg") != nullptr;
char sample[1024];
const int sample_size = MIN2(size, sizeof(sample));
memcpy(&sample[0], mem, sample_size);
sample[sample_size - 1] = '\0';
return strstr(sample, "<svg") != nullptr;
}
ImBuf *imb_load_svg(const uchar *mem, size_t size, int /* flags */, char colorspace[IM_MAX_SPACE])
{
if (!imb_is_a_svg(mem, size)) {
return nullptr;
}
NSVGimage *image = nullptr;
char *data = (char *)malloc(size + 1);
@ -38,8 +44,21 @@ ImBuf *imb_load_svg(const uchar *mem, size_t size, int /* flags */, char colorsp
return nullptr;
}
const int w = int(image->width);
const int h = int(image->height);
if (image->width == 0 || image->height == 0) {
nsvgDelete(image);
return nullptr;
}
int w = int(image->width);
int h = int(image->height);
int scale = 1;
/* Increase to a nice size if small since these are vectors. */
while (MAX2(w, h) < 1024) {
scale *= 2;
w *= scale;
h *= scale;
}
NSVGrasterizer *rast = nsvgCreateRasterizer();
if (rast == nullptr) {
@ -51,7 +70,7 @@ ImBuf *imb_load_svg(const uchar *mem, size_t size, int /* flags */, char colorsp
ImBuf *ibuf = IMB_allocImBuf(w, h, 32, IB_rect);
if (ibuf != nullptr) {
nsvgRasterize(rast, image, 0, 0, 1.0f, ibuf->byte_buffer.data, w, h, w * 4);
nsvgRasterize(rast, image, 0, 0, float(scale), ibuf->byte_buffer.data, w, h, w * 4);
nsvgDeleteRasterizer(rast);
nsvgDelete(image);
IMB_flipy(ibuf);
@ -67,10 +86,16 @@ ImBuf *imb_load_filepath_thumbnail_svg(const char *filepath,
size_t *r_height)
{
NSVGimage *image = nsvgParseFromFile(filepath, "px", 96.0f);
if (image == nullptr) {
return nullptr;
}
if (image->width == 0 || image->height == 0) {
nsvgDelete(image);
return nullptr;
}
int w = int(image->width);
int h = int(image->height);