]> O.S.I.I.S - jp/vkvg.git/commitdiff
embed vkvg-svg, svg-viewer as in vkvg/tests
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sun, 9 Jan 2022 20:04:26 +0000 (21:04 +0100)
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>
Sun, 9 Jan 2022 20:04:26 +0000 (21:04 +0100)
CMakeLists.txt
external/vkvg-svg
tests/CMakeLists.txt
tests/vkvg-svg/svg-viewer.c [new file with mode: 0644]

index 032f784d72c36c9858f8519d8a02c92800a20f1f..114331b45aa3982527ec48678e2000519cd239c5 100644 (file)
@@ -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 $<TARGET_OBJECTS:vkvg-svg>)
+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 ()
index 98e6716f64b6830fe816f92bf7881ebd1762734e..704094fe6a28f1191563b1a35c4cdb2222b12c20 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 98e6716f64b6830fe816f92bf7881ebd1762734e
+Subproject commit 704094fe6a28f1191563b1a35c4cdb2222b12c20
index 73bfec8a28eaa9beb205a89fd244be36d8b7dd83..7aba8157a039d5735679f17f06923e3d5bde5afd 100644 (file)
@@ -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 (file)
index 0000000..5416e05
--- /dev/null
@@ -0,0 +1,339 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include <stdarg.h>
+#include <ctype.h>
+
+#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);
+}