From: Jean-Philippe Bruyère Date: Sun, 9 Jan 2022 20:04:26 +0000 (+0100) Subject: embed vkvg-svg, svg-viewer as in vkvg/tests X-Git-Tag: v0.3.0-beta~32 X-Git-Url: https://git.osiis.dedyn.io/?a=commitdiff_plain;h=e285821ccd00abe5ee96262fc3d76b74519975b2;p=jp%2Fvkvg.git embed vkvg-svg, svg-viewer as in vkvg/tests --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 032f784..114331b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -206,7 +206,10 @@ ENDIF () FILE(GLOB VKVG_SRC src/*.c) SET (VKVG_PUBLIC_HEADERS "include/vkvg.h") -IF (NOT VKVG_SVG) +IF (VKVG_SVG) + ADD_SUBDIRECTORY (external/vkvg-svg) + LIST (APPEND VKVG_SRC $) +ELSE() SET (VKVG_PUBLIC_HEADERS "${VKVG_PUBLIC_HEADERS};include/vkvg-svg.h") FILE(GLOB NSVG_SRC src/nsvg/*.c) LIST (APPEND VKVG_SRC ${NSVG_SRC}) @@ -400,10 +403,6 @@ IF (SHADERS_H) ENDFOREACH() ENDIF () -IF (VKVG_SVG AND NOT TARGET vkvk-svg) - ADD_SUBDIRECTORY (external/vkvg-svg) -ENDIF() - IF (BUILD_SHARED_LIBS) MESSAGE(STATUS "Build Shared library.") ELSE () diff --git a/external/vkvg-svg b/external/vkvg-svg index 98e6716..704094f 160000 --- a/external/vkvg-svg +++ b/external/vkvg-svg @@ -1 +1 @@ -Subproject commit 98e6716f64b6830fe816f92bf7881ebd1762734e +Subproject commit 704094fe6a28f1191563b1a35c4cdb2222b12c20 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 73bfec8..7aba815 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -57,6 +57,11 @@ file(GLOB TESTS "*.c" "perfs/*.c" ) + +IF (VKVG_SVG) + LIST (APPEND TESTS "vkvg-svg/svg-viewer.c") +ENDIF() + FOREACH(TEST ${TESTS}) buildtest(${TEST}) ENDFOREACH() diff --git a/tests/vkvg-svg/svg-viewer.c b/tests/vkvg-svg/svg-viewer.c new file mode 100644 index 0000000..5416e05 --- /dev/null +++ b/tests/vkvg-svg/svg-viewer.c @@ -0,0 +1,339 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "vkvg.h" +#include "vkvg-svg.h" +#include "vkengine.h" + +static VkvgDevice dev; +static VkvgSurface svgSurf = NULL; +static double scale = 1; + + +static char* filename = NULL; +static char* directory = NULL; +static DIR * pCurrentDir = NULL; +struct dirent *dir = NULL; +static int iconSize = -1; +static VkSampleCountFlags samples = VK_SAMPLE_COUNT_8_BIT; +static uint32_t width=512, height=512, margin = 10; +static double scrollX, scrollY; +static bool paused = false, repaintIconList = true; + + +struct stat file_stat; + +#define NORMAL_COLOR "\x1B[0m" +#define GREEN "\x1B[32m" +#define BLUE "\x1B[34m" + +static int svg_file_count; +static float maxScroll; + +int _count_svg_files () { + struct dirent *de; + rewinddir (pCurrentDir); + int i = 0; + while ((de = readdir(pCurrentDir)) != NULL) { + if(de->d_type != DT_DIR && !strcasecmp(strrchr(de->d_name, '\0') - 4, ".svg")) + i++; + } + return i; +} +void readSVG (VkEngine e) { + struct stat sb; + VkvgSurface newSvgSurf = NULL; + if (iconSize > 0 && pCurrentDir) { + if (!repaintIconList) + return; + char tmp[FILENAME_MAX]; + double x = 0, y = 0; + int cellSize = iconSize + margin; + int iconPerLine = ceil((double)(width-iconSize) / cellSize); + int lineToSkip = floor(scrollY / cellSize); + int iconToSkip = lineToSkip * iconPerLine; + + y = (lineToSkip * cellSize) - scrollY; + + newSvgSurf = vkvg_surface_create(dev, width, height); + VkvgContext ctx = vkvg_create(newSvgSurf); + + struct dirent *de; + rewinddir (pCurrentDir); + int i = 0; + while ((de = readdir(pCurrentDir)) != NULL) { + if(de->d_type != DT_DIR) { + if (!strcasecmp(strrchr(de->d_name, '\0') - 4, ".svg")) { + if (i >= iconToSkip) { + sprintf(tmp, "%s%s", directory, de->d_name); + VkvgSurface surf = vkvg_surface_create_from_svg (dev, iconSize, iconSize, tmp); + + if (surf) { + vkvg_set_source_surface(ctx, surf, x, y); + vkvg_paint(ctx); + vkvg_surface_destroy(surf); + } + x += iconSize + margin; + if (x > width - iconSize) { + x = 0; + y += iconSize + margin; + if (y >= height) + break; + } + } + i++; + } + } + } + vkvg_destroy(ctx); + repaintIconList = false; + }else if (filename) { + vkengine_set_title(e, filename); + if (stat(filename, &sb) == -1) { + printf ("Unable to stat file: %s\n", filename); + exit(EXIT_FAILURE); + } + if (sb.st_mtim.tv_sec == file_stat.st_mtim.tv_sec) + return; + file_stat = sb; + newSvgSurf = vkvg_surface_create_from_svg(dev, width, height, filename); + } else if (dir) { + char tmp[FILENAME_MAX]; + sprintf(tmp, "%s/%s", directory, dir->d_name); + vkengine_set_title(e, tmp); + if (stat(tmp, &sb) == -1) { + printf ("Unable to stat file: %s\n", tmp); + exit(EXIT_FAILURE); + } + if (sb.st_mtim.tv_sec == file_stat.st_mtim.tv_sec) + return; + file_stat = sb; + newSvgSurf = vkvg_surface_create_from_svg(dev, width, height, tmp); + } + + //vkengine_wait_idle(e); + + if (svgSurf) + vkvg_surface_destroy(svgSurf); + svgSurf = newSvgSurf; + + //vkengine_wait_idle(e); +#ifdef VKVG_DBG_STATS + vkvg_debug_stats_t dbgStats = vkvg_device_get_stats (dev); + vkvg_device_reset_stats (dev); + LOG("maximum point array size = %d\n", dbgStats.sizePoints); + LOG("maximum path array size = %d\n", dbgStats.sizePathes); + LOG("maximum size of host vertice cache = %d\n", dbgStats.sizeVertices); + LOG("maximum size of host index cache = %d\n", dbgStats.sizeIndices); + LOG("maximum size of vulkan vertex buffer = %d\n", dbgStats.sizeVBO); + LOG("maximum size of vulkan index buffer = %d\n", dbgStats.sizeIBO); +#endif + +} + +struct dirent *get_next_svg_file_in_current_directory (bool cycle) { + struct dirent *de; + while ((de = readdir(pCurrentDir)) != NULL) { + if(de->d_type != DT_DIR) { + if (!strcasecmp(strrchr(de->d_name, '\0') - 4, ".svg")) + return de; + } + } + if (!cycle) + return NULL; + rewinddir (pCurrentDir); + return get_next_svg_file_in_current_directory (false); +} + + +static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods) { + if (action == GLFW_RELEASE) + return; + switch (key) { + case GLFW_KEY_SPACE: + paused = !paused; + break; + case GLFW_KEY_R: + //recording = !recording; + file_stat = (struct stat){0}; + break; + case GLFW_KEY_ESCAPE : + glfwSetWindowShouldClose(window, GLFW_TRUE); + break; + case GLFW_KEY_ENTER : + if (!pCurrentDir) + break; + dir = get_next_svg_file_in_current_directory(true); + file_stat = (struct stat){0}; + break; + case GLFW_KEY_KP_ADD: + scale*=2.0; + file_stat = (struct stat){0}; + break; + case GLFW_KEY_KP_SUBTRACT: + scale/=2.0; + file_stat = (struct stat){0}; + break; + } +} +static void scroll_callback(GLFWwindow* window, double x, double y) { + if (iconSize == 0) + return; + scrollX -= x * 25; + scrollY -= y * 25; + if (scrollX < 0) + scrollX = 0; + if (scrollY < 0) + scrollY = 0; + else if (scrollY > maxScroll) + scrollY = maxScroll; + repaintIconList = true; +} + +void print_help_and_exit () { + printf("\nUsage: svgviewer [options] [svgfilepath]\n\n"); + printf("\t-d directory:\tdirectory containing svg files, cycle pressing Enter.\n"); + printf("\t\t\tif the -d option is not specified, svgfile path is mandatory.\n"); + printf("\t-i size:\tif -d option is present, display all svg files as a list with the size specified.\n"); + printf("\t-m margin:\tset margin for the -i option\n"); + printf("\n"); + exit(-1); +} + + +int main (int argc, char *argv[]){ + int i = 1; + + while (i < argc) { + int argLen = strlen(argv[i]); + if (argv[i][0] == '-') { + + if (argLen < 2) print_help_and_exit (); + + switch (argv[i][1]) { + case 'd': + if (argc < ++i + 1) print_help_and_exit(); + directory = argv[i]; + break; + case 'w': + if (argc < ++i + 1) print_help_and_exit(); + width = atoi(argv[i]); + break; + case 'h': + if (argc < ++i + 1) print_help_and_exit(); + height = atoi(argv[i]); + break; + case 's': + if (argc < ++i + 1) print_help_and_exit(); + samples = (VkSampleCountFlags)atoi(argv[i]); + break; + case 'i': + if (argc < ++i + 1) print_help_and_exit(); + iconSize = atoi(argv[i]); + break; + case 'm': + if (argc < ++i + 1) print_help_and_exit(); + margin = atoi(argv[++i]); + break; + default: + print_help_and_exit(); + } + } else + filename = argv[i]; + i++; + } + if (!filename && !directory) + print_help_and_exit(); + + VkEngine e = vkengine_create (VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU,VK_PRESENT_MODE_FIFO_KHR, width, height); + vkengine_set_key_callback (e, key_callback); + vkengine_set_scroll_callback(e, scroll_callback); + + dev = vkvg_device_create_from_vk_multisample (vkh_app_get_inst(e->app), + vkengine_get_physical_device(e), vkengine_get_device(e), vkengine_get_queue_fam_idx(e), 0, samples, false); + + VkvgSurface surf = vkvg_surface_create(dev, width, height); + + vkh_presenter_build_blit_cmd (e->renderer, vkvg_surface_get_vk_image(surf), width, height); + + if (directory) { + pCurrentDir = opendir(directory); + if(!pCurrentDir) { + printf ("Directory not found: %s\n", directory); + exit(EXIT_FAILURE); + } + dir = get_next_svg_file_in_current_directory(false); + if (!dir) { + printf ("No .svg file found in %s\n", directory); + closedir(pCurrentDir); + exit(EXIT_FAILURE); + } + if (iconSize > 0) { + svg_file_count = _count_svg_files(); + int cellSize = iconSize + margin; + int iconPerLine = ceil((double)(width-iconSize) / cellSize); + int visibleLines = ceil((double)(height) / cellSize); + int totLines = ceil((double)svg_file_count / iconPerLine); + maxScroll = (totLines-visibleLines) * cellSize; + } + } + + + + while (!vkengine_should_close (e)) { + //vkvg_log_level = VKVG_LOG_INFO_CMD; + readSVG (e); + //vkvg_log_level = VKVG_LOG_ERR; + + VkvgContext ctx = vkvg_create(surf); + vkvg_set_source_rgb(ctx,0.1,0.1,0.1); + vkvg_paint(ctx); + + if (svgSurf) { + vkvg_set_source_surface(ctx, svgSurf, 0, 0); + vkvg_paint(ctx); + } else { + vkvg_set_line_width(ctx,10); + vkvg_set_source_rgb(ctx,1,0,0); + vkvg_move_to(ctx, 0,0); + vkvg_line_to(ctx, 512,512); + vkvg_move_to(ctx, 0,512); + vkvg_line_to(ctx, 512,0); + vkvg_stroke(ctx); + + } + vkvg_destroy(ctx); + + glfwPollEvents(); + + if (!vkh_presenter_draw (e->renderer)){ + vkh_presenter_get_size (e->renderer, &width, &height); + vkvg_surface_destroy (surf); + surf = vkvg_surface_create(dev, width, height); + vkh_presenter_build_blit_cmd (e->renderer, vkvg_surface_get_vk_image(surf), width, height); + vkengine_wait_idle(e); + repaintIconList = true; + continue; + } + + } + + vkengine_wait_idle(e); + + if (svgSurf) + vkvg_surface_destroy(svgSurf); + vkvg_surface_destroy(surf); + vkvg_device_destroy(dev); + vkengine_destroy(e); + + if (pCurrentDir) + closedir(pCurrentDir); +}