Skip to content

Commit

Permalink
SVG: Try to find NanoSVG as a fallback rendering library when resvg i…
Browse files Browse the repository at this point in the history
…s not found
  • Loading branch information
HappySeaFox committed Nov 8, 2023
1 parent 3c4e2c9 commit 23ccbe7
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 33 deletions.
74 changes: 47 additions & 27 deletions src/sail-codecs/svg/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,34 +1,48 @@
find_library(SVG_LIBRARY resvg ${SAIL_CODEC_SVG_REQUIRED_OPTION})
find_path(SVG_INCLUDE_DIRS resvg.h ${SAIL_CODEC_SVG_REQUIRED_OPTION})
find_library(SVG_LIBRARY resvg)
find_path(SVG_INCLUDE_DIRS resvg.h)

# Fall back to NanoSVG
#
if (NOT SVG_LIBRARY OR NOT SVG_INCLUDE_DIRS)
return()
set(SVG_LIBRARY "")
find_path(SVG_INCLUDE_DIRS nanosvg.h ${SAIL_CODEC_SVG_REQUIRED_OPTION})

if (NOT SVG_INCLUDE_DIRS)
return()
else()
message("SVG: Using nanosvg")
endif()
else()
set(SAIL_RESVG ON)
message("SVG: Using resvg")
endif()

cmake_push_check_state(RESET)
set(CMAKE_REQUIRED_INCLUDES ${SVG_INCLUDE_DIRS})
if (SAIL_RESVG)
cmake_push_check_state(RESET)
set(CMAKE_REQUIRED_INCLUDES ${SVG_INCLUDE_DIRS})

check_c_source_compiles(
check_c_source_compiles(
"
#include <resvg.h>
int main(int argc, char *argv[]) {
resvg_fit_to resvg_fit_to = { RESVG_FIT_TO_ORIGINAL, 0 };
return 0;
}
"
#include <resvg.h>
int main(int argc, char *argv[]) {
resvg_fit_to resvg_fit_to = { RESVG_FIT_TO_ORIGINAL, 0 };
return 0;
}
"
HAVE_RESVG_FIT_TO
)
cmake_pop_check_state()

# This will add the following CMake rules to the CMake config for static builds so a client
# application links against the required dependencies:
#
# find_library(resvg_RELEASE_LIBRARY NAMES resvg)
# find_library(resvg_DEBUG_LIBRARY NAMES resvg)
# set_property(TARGET SAIL::sail-codecs APPEND PROPERTY INTERFACE_LINK_LIBRARIES $<$<CONFIG:Release>:${resvg_RELEASE_LIBRARY}> $<$<CONFIG:Debug>:${resvg_DEBUG_LIBRARY}>)
#
set(SAIL_CODECS_FIND_DEPENDENCIES ${SAIL_CODECS_FIND_DEPENDENCIES} "find_library,resvg,resvg" PARENT_SCOPE)
HAVE_RESVG_FIT_TO
)
cmake_pop_check_state()

# This will add the following CMake rules to the CMake config for static builds so a client
# application links against the required dependencies:
#
# find_library(resvg_RELEASE_LIBRARY NAMES resvg)
# find_library(resvg_DEBUG_LIBRARY NAMES resvg)
# set_property(TARGET SAIL::sail-codecs APPEND PROPERTY INTERFACE_LINK_LIBRARIES $<$<CONFIG:Release>:${resvg_RELEASE_LIBRARY}> $<$<CONFIG:Debug>:${resvg_DEBUG_LIBRARY}>)
#
set(SAIL_CODECS_FIND_DEPENDENCIES ${SAIL_CODECS_FIND_DEPENDENCIES} "find_library,resvg,resvg" PARENT_SCOPE)
endif()

# Common codec configuration
#
Expand All @@ -38,6 +52,12 @@ sail_codec(NAME svg
DEPENDENCY_INCLUDE_DIRS ${SVG_INCLUDE_DIRS}
DEPENDENCY_LIBS ${SVG_LIBRARY})

if (HAVE_RESVG_FIT_TO)
target_compile_definitions(${SAIL_CODEC_TARGET} PRIVATE SAIL_HAVE_RESVG_FIT_TO)
if (SAIL_RESVG)
target_compile_definitions(${SAIL_CODEC_TARGET} PRIVATE SAIL_RESVG)

if (HAVE_RESVG_FIT_TO)
target_compile_definitions(${SAIL_CODEC_TARGET} PRIVATE SAIL_HAVE_RESVG_FIT_TO)
endif()
else()
target_compile_definitions(${SAIL_CODEC_TARGET} PRIVATE SAIL_NANOSVG)
endif()
63 changes: 57 additions & 6 deletions src/sail-codecs/svg/svg.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,14 @@
#include <stddef.h>
#include <string.h>

#include <resvg.h>
#ifdef SAIL_RESVG
#include <resvg.h>
#else
#define NANOSVG_IMPLEMENTATION
#include <nanosvg.h>
#define NANOSVGRAST_IMPLEMENTATION
#include <nanosvgrast.h>
#endif

#include <sail-common/sail-common.h>

Expand All @@ -39,8 +46,14 @@ struct svg_state {
struct sail_save_options *save_options;

bool frame_loaded;

#ifdef SAIL_RESVG
resvg_options *resvg_options;
resvg_render_tree *resvg_tree;
#else
NSVGimage *nsvg_image;
NSVGrasterizer *nsvg_rasterizer;
#endif
};

static sail_status_t alloc_svg_state(struct svg_state **svg_state) {
Expand All @@ -53,8 +66,14 @@ static sail_status_t alloc_svg_state(struct svg_state **svg_state) {
(*svg_state)->save_options = NULL;

(*svg_state)->frame_loaded = false;

#ifdef SAIL_RESVG
(*svg_state)->resvg_options = NULL;
(*svg_state)->resvg_tree = NULL;
#else
(*svg_state)->nsvg_image = NULL;
(*svg_state)->nsvg_rasterizer = NULL;
#endif

return SAIL_OK;
}
Expand All @@ -68,13 +87,17 @@ static void destroy_svg_state(struct svg_state *svg_state) {
sail_destroy_load_options(svg_state->load_options);
sail_destroy_save_options(svg_state->save_options);

#ifdef SAIL_RESVG
if (svg_state->resvg_options != NULL) {
resvg_options_destroy(svg_state->resvg_options);
}

if (svg_state->resvg_tree != NULL) {
resvg_tree_destroy(svg_state->resvg_tree);
}
#else
nsvgDeleteRasterizer(svg_state->nsvg_rasterizer);
nsvgDelete(svg_state->nsvg_image);
#endif

sail_free(svg_state);
}
Expand All @@ -100,6 +123,7 @@ SAIL_EXPORT sail_status_t sail_codec_load_init_v8_svg(struct sail_io *io, const
size_t image_size;
SAIL_TRY(sail_alloc_data_from_io_contents(io, &image_data, &image_size));

#ifdef SAIL_RESVG
svg_state->resvg_options = resvg_options_create();

const int result = resvg_parse_tree_from_data(image_data, image_size, svg_state->resvg_options, &svg_state->resvg_tree);
Expand All @@ -110,6 +134,23 @@ SAIL_EXPORT sail_status_t sail_codec_load_init_v8_svg(struct sail_io *io, const
SAIL_LOG_ERROR("SVG: Failed to load image");
SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE);
}
#else
svg_state->nsvg_image = nsvgParse(image_data, "px", 96.0f);

sail_free(image_data);

if (svg_state->nsvg_image == NULL) {
SAIL_LOG_ERROR("SVG: Failed to load image");
SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE);
}

svg_state->nsvg_rasterizer = nsvgCreateRasterizer();

if (svg_state->nsvg_rasterizer == NULL) {
SAIL_LOG_ERROR("SVG: Failed to create NanoSVG rasterizer");
SAIL_LOG_AND_RETURN(SAIL_ERROR_BROKEN_IMAGE);
}
#endif

return SAIL_OK;
}
Expand All @@ -135,10 +176,15 @@ SAIL_EXPORT sail_status_t sail_codec_load_seek_next_frame_v8_svg(void *state, st
image_local->source_image->compression = SAIL_COMPRESSION_NONE;
}

#ifdef SAIL_RESVG
const resvg_size image_size = resvg_get_image_size(svg_state->resvg_tree);

image_local->width = (unsigned)image_size.width;
image_local->height = (unsigned)image_size.height;
#else
image_local->width = (unsigned)svg_state->nsvg_image->width;
image_local->height = (unsigned)svg_state->nsvg_image->height;
#endif
image_local->pixel_format = SAIL_PIXEL_FORMAT_BPP32_RGBA;
image_local->bytes_per_line = sail_bytes_per_line(image_local->width, image_local->pixel_format);

Expand All @@ -153,11 +199,16 @@ SAIL_EXPORT sail_status_t sail_codec_load_frame_v8_svg(void *state, struct sail_

memset(image->pixels, 0, (size_t)image->bytes_per_line * image->height);

#ifdef SAIL_HAVE_RESVG_FIT_TO
const resvg_fit_to resvg_fit_to = { RESVG_FIT_TO_ORIGINAL, 0 };
resvg_render(svg_state->resvg_tree, resvg_fit_to, image->width, image->height, image->pixels);
#ifdef SAIL_RESVG
#ifdef SAIL_HAVE_RESVG_FIT_TO
const resvg_fit_to resvg_fit_to = { RESVG_FIT_TO_ORIGINAL, 0 };
resvg_render(svg_state->resvg_tree, resvg_fit_to, image->width, image->height, image->pixels);
#else
resvg_render(svg_state->resvg_tree, resvg_transform_identity(), image->width, image->height, image->pixels);
#endif
#else
resvg_render(svg_state->resvg_tree, resvg_transform_identity(), image->width, image->height, image->pixels);
nsvgRasterize(svg_state->nsvg_rasterizer, svg_state->nsvg_image, /* x */ 0, /* y */ 0, /* scale */ 1,
image->pixels, (int)image->width, (int)image->height, (int)image->bytes_per_line);
#endif

return SAIL_OK;
Expand Down

0 comments on commit 23ccbe7

Please sign in to comment.