tornavis/source/blender/imbuf/intern/format_svg.cc

67 lines
1.9 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* 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
* specific to loading vector graphics (such as resolution control), see #109567 for details.
*/
#include "IMB_colormanagement.h"
#include "IMB_filetype.h"
#include "IMB_imbuf_types.h"
#include "nanosvg.h"
#include "nanosvgrast.h"
ImBuf *imb_load_filepath_thumbnail_svg(const char *filepath,
const int /*flags*/,
const size_t max_thumb_size,
char colorspace[],
size_t *r_width,
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);
/* Return full size of the image. */
*r_width = size_t(w);
*r_height = size_t(h);
NSVGrasterizer *rast = nsvgCreateRasterizer();
if (rast == nullptr) {
nsvgDelete(image);
return nullptr;
}
colorspace_set_default_role(colorspace, IM_MAX_SPACE, COLOR_ROLE_DEFAULT_BYTE);
const float scale = float(max_thumb_size) / std::max(w, h);
const int dest_w = std::max(int(w * scale), 1);
const int dest_h = std::max(int(h * scale), 1);
ImBuf *ibuf = IMB_allocImBuf(dest_w, dest_h, 32, IB_rect);
if (ibuf != nullptr) {
nsvgRasterize(rast, image, 0, 0, scale, ibuf->byte_buffer.data, dest_w, dest_h, dest_w * 4);
nsvgDeleteRasterizer(rast);
nsvgDelete(image);
IMB_flipy(ibuf);
}
return ibuf;
}