Ver Fonte

Added CMake presets, core-only standalone, errors to stderr

Chlumsky há 2 anos atrás
pai
commit
34baf1706e
6 ficheiros alterados com 542 adições e 60 exclusões
  1. 7 4
      CMakeLists.txt
  2. 239 0
      CMakePresets.json
  3. 170 0
      cmake/CMakePresets.json
  4. 4 0
      core/generator-config.h
  5. 121 55
      main.cpp
  6. 1 1
      vcpkg.json

+ 7 - 4
CMakeLists.txt

@@ -12,10 +12,6 @@ option(MSDFGEN_INSTALL "Generate installation target" OFF)
 option(MSDFGEN_DYNAMIC_RUNTIME "Link dynamic runtime library instead of static" OFF)
 option(BUILD_SHARED_LIBS "Generate dynamic library files instead of static" OFF)
 
-if(MSDFGEN_CORE_ONLY AND MSDFGEN_BUILD_STANDALONE)
-    message(WARNING "Option MSDFGEN_CORE_ONLY ignored - extensions are required for standalone executable")
-    set(MSDFGEN_CORE_ONLY OFF)
-endif()
 if(MSDFGEN_CORE_ONLY AND MSDFGEN_USE_VCPKG)
     message(STATUS "Option MSDFGEN_USE_VCPKG ignored due to MSDFGEN_CORE_ONLY - core has no dependencies")
     set(MSDFGEN_USE_VCPKG OFF)
@@ -140,6 +136,7 @@ if(NOT MSDFGEN_CORE_ONLY)
     set_target_properties(msdfgen-ext PROPERTIES PUBLIC_HEADER "${MSDFGEN_EXT_HEADERS}")
     set_property(TARGET msdfgen-ext PROPERTY MSVC_RUNTIME_LIBRARY "${MSDFGEN_MSVC_RUNTIME}")
     target_compile_definitions(msdfgen-ext PUBLIC MSDFGEN_USE_LIBPNG)
+    target_compile_definitions(msdfgen-ext INTERFACE MSDFGEN_EXTENSIONS)
     target_link_libraries(msdfgen-ext PRIVATE msdfgen::msdfgen-core Freetype::Freetype tinyxml2::tinyxml2 PNG::PNG)
     target_include_directories(msdfgen-ext
         PUBLIC
@@ -171,6 +168,8 @@ if(NOT MSDFGEN_CORE_ONLY)
     add_library(msdfgen-full INTERFACE)
     add_library(msdfgen::msdfgen ALIAS msdfgen-full)
     target_link_libraries(msdfgen-full INTERFACE msdfgen::msdfgen-core msdfgen::msdfgen-ext)
+else()
+    add_library(msdfgen::msdfgen ALIAS msdfgen-core)
 endif()
 
 # Standalone executable
@@ -187,6 +186,10 @@ if(MSDFGEN_BUILD_STANDALONE)
     set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT msdfgen)
 endif()
 
+# Hide ZERO_CHECK and ALL_BUILD targets
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER meta)
+
 # Installation
 if(MSDFGEN_INSTALL)
     include(GNUInstallDirs)

+ 239 - 0
CMakePresets.json

@@ -0,0 +1,239 @@
+{
+    "version": 4,
+    "cmakeMinimumRequired": {
+        "major": 3,
+        "minor": 23,
+        "patch": 0
+    },
+    "include": [
+        "cmake/CMakePresets.json"
+    ],
+    "configurePresets": [
+        {
+            "name": "win64",
+            "displayName": "Windows x64 default config (static, vcpkg, Skia)",
+            "inherits": [ "win64-base", "vcpkg", "skia" ]
+        }, {
+            "name": "win32",
+            "displayName": "Windows x86 default config (static, vcpkg, Skia)",
+            "inherits": [ "win32-base", "vcpkg", "skia" ]
+        }, {
+            "name": "win64-omp",
+            "displayName": "Windows x64 config with OpenMP (static, vcpkg, Skia)",
+            "inherits": [ "win64-base", "openmp", "vcpkg", "skia" ],
+            "binaryDir": "${sourceDir}/build/win64-omp"
+        }, {
+            "name": "win32-omp",
+            "displayName": "Windows x86 config with OpenMP (static, vcpkg, Skia)",
+            "inherits": [ "win32-base", "openmp", "vcpkg", "skia" ],
+            "binaryDir": "${sourceDir}/build/win32-omp"
+        }, {
+            "name": "win64-dynamic",
+            "displayName": "Windows x64 dynamic config (vcpkg, Skia)",
+            "inherits": [ "win64-base", "vcpkg", "skia", "dynamic-runtime", "dynamic-lib" ],
+            "binaryDir": "${sourceDir}/build/win64-dynamic"
+        }, {
+            "name": "win32-dynamic",
+            "displayName": "Windows x86 dynamic config (vcpkg, Skia)",
+            "inherits": [ "win32-base", "vcpkg", "skia", "dynamic-runtime", "dynamic-lib" ],
+            "binaryDir": "${sourceDir}/build/win32-dynamic"
+        }, {
+            "name": "win64-no-skia",
+            "displayName": "Windows x64 config without Skia (static, vcpkg)",
+            "inherits": [ "win64-base", "vcpkg", "no-skia" ]
+        }, {
+            "name": "win32-no-skia",
+            "displayName": "Windows x86 config without Skia (static, vcpkg)",
+            "inherits": [ "win32-base", "vcpkg", "no-skia" ]
+        }, {
+            "name": "win64-core",
+            "displayName": "Windows x64 core-only config (static)",
+            "inherits": [ "win64-base", "core-only" ],
+            "binaryDir": "${sourceDir}/build/win64-core"
+        }, {
+            "name": "win32-core",
+            "displayName": "Windows x86 core-only config (static)",
+            "inherits": [ "win32-base", "core-only" ],
+            "binaryDir": "${sourceDir}/build/win32-core"
+        },
+
+        {
+            "name": "osx-vcpkg-rel",
+            "displayName": "Mac OS release config with vcpkg and Skia (static)",
+            "inherits": [ "osx-rel-base", "vcpkg", "skia" ]
+        }, {
+            "name": "osx-vcpkg-dbg",
+            "displayName": "Mac OS debug config with vcpkg and Skia (static)",
+            "inherits": [ "osx-dbg-base", "vcpkg", "skia" ]
+        }, {
+            "name": "osx-no-skia-rel",
+            "displayName": "Mac OS release config with system libraries and no Skia (static, install)",
+            "inherits": [ "osx-rel-base", "no-vcpkg", "no-skia", "install" ]
+        }, {
+            "name": "osx-no-skia-dbg",
+            "displayName": "Mac OS debug config with system libraries and no Skia (static, install)",
+            "inherits": [ "osx-dbg-base", "no-vcpkg", "no-skia", "install" ]
+        }, {
+            "name": "osx-core-rel",
+            "displayName": "Mac OS release core-only config (static, install)",
+            "inherits": [ "osx-rel-base", "core-only", "install" ],
+            "binaryDir": "${sourceDir}/build/osx-core-rel"
+        }, {
+            "name": "osx-core-dbg",
+            "displayName": "Mac OS debug core-only config (static, install)",
+            "inherits": [ "osx-dbg-base", "core-only", "install" ],
+            "binaryDir": "${sourceDir}/build/osx-core-dbg"
+        },
+
+        {
+            "name": "linux-vcpkg-rel",
+            "displayName": "Linux release config with vcpkg and Skia (static)",
+            "inherits": [ "linux-rel-base", "vcpkg", "skia" ]
+        }, {
+            "name": "linux-vcpkg-dbg",
+            "displayName": "Linux debug config with vcpkg and Skia (static)",
+            "inherits": [ "linux-dbg-base", "vcpkg", "skia" ]
+        }, {
+            "name": "linux-no-skia-rel",
+            "displayName": "Linux release config with system libraries and no Skia (static, install)",
+            "inherits": [ "linux-rel-base", "no-vcpkg", "no-skia", "install" ]
+        }, {
+            "name": "linux-no-skia-dbg",
+            "displayName": "Linux debug config with system libraries and no Skia (static, install)",
+            "inherits": [ "linux-dbg-base", "no-vcpkg", "no-skia", "install" ]
+        }, {
+            "name": "linux-core-rel",
+            "displayName": "Linux release core-only config (static, install)",
+            "inherits": [ "linux-rel-base", "core-only", "install" ],
+            "binaryDir": "${sourceDir}/build/linux-core-rel"
+        }, {
+            "name": "linux-core-dbg",
+            "displayName": "Linux debug core-only config (static, install)",
+            "inherits": [ "linux-dbg-base", "core-only", "install" ],
+            "binaryDir": "${sourceDir}/build/linux-core-dbg"
+        }
+    ],
+    "buildPresets": [
+        {
+            "name": "win64-rel",
+            "configurePreset": "win64",
+            "configuration": "Release"
+        }, {
+            "name": "win64-dbg",
+            "configurePreset": "win64",
+            "configuration": "Debug"
+        }, {
+            "name": "win32-rel",
+            "configurePreset": "win32",
+            "configuration": "Release"
+        }, {
+            "name": "win32-dbg",
+            "configurePreset": "win32",
+            "configuration": "Debug"
+        }, {
+            "name": "win64-omp-rel",
+            "configurePreset": "win64-omp",
+            "configuration": "Release"
+        }, {
+            "name": "win64-omp-dbg",
+            "configurePreset": "win64-omp",
+            "configuration": "Debug"
+        }, {
+            "name": "win32-omp-rel",
+            "configurePreset": "win32-omp",
+            "configuration": "Release"
+        }, {
+            "name": "win32-omp-dbg",
+            "configurePreset": "win32-omp",
+            "configuration": "Debug"
+        }, {
+            "name": "win64-dynamic-rel",
+            "configurePreset": "win64-dynamic",
+            "configuration": "Release"
+        }, {
+            "name": "win64-dynamic-dbg",
+            "configurePreset": "win64-dynamic",
+            "configuration": "Debug"
+        }, {
+            "name": "win32-dynamic-rel",
+            "configurePreset": "win32-dynamic",
+            "configuration": "Release"
+        }, {
+            "name": "win32-dynamic-dbg",
+            "configurePreset": "win32-dynamic",
+            "configuration": "Debug"
+        }, {
+            "name": "win64-no-skia-rel",
+            "configurePreset": "win64-no-skia",
+            "configuration": "Release"
+        }, {
+            "name": "win64-no-skia-dbg",
+            "configurePreset": "win64-no-skia",
+            "configuration": "Debug"
+        }, {
+            "name": "win32-no-skia-rel",
+            "configurePreset": "win32-no-skia",
+            "configuration": "Release"
+        }, {
+            "name": "win32-no-skia-dbg",
+            "configurePreset": "win32-no-skia",
+            "configuration": "Debug"
+        }, {
+            "name": "win64-core-rel",
+            "configurePreset": "win64-core",
+            "configuration": "Release"
+        }, {
+            "name": "win64-core-dbg",
+            "configurePreset": "win64-core",
+            "configuration": "Debug"
+        }, {
+            "name": "win32-core-rel",
+            "configurePreset": "win32-core",
+            "configuration": "Release"
+        }, {
+            "name": "win32-core-dbg",
+            "configurePreset": "win32-core",
+            "configuration": "Debug"
+        },
+
+        {
+            "name": "osx-vcpkg-rel",
+            "configurePreset": "osx-vcpkg-rel"
+        }, {
+            "name": "osx-vcpkg-dbg",
+            "configurePreset": "osx-vcpkg-dbg"
+        }, {
+            "name": "osx-no-skia-rel",
+            "configurePreset": "osx-no-skia-rel"
+        }, {
+            "name": "osx-no-skia-dbg",
+            "configurePreset": "osx-no-skia-dbg"
+        }, {
+            "name": "osx-core-rel",
+            "configurePreset": "osx-core-rel"
+        }, {
+            "name": "osx-core-dbg",
+            "configurePreset": "osx-core-dbg"
+        },
+        
+        {
+            "name": "linux-vcpkg-rel",
+            "configurePreset": "linux-vcpkg-rel"
+        }, {
+            "name": "linux-vcpkg-dbg",
+            "configurePreset": "linux-vcpkg-dbg"
+        }, {
+            "name": "linux-no-skia-rel",
+            "configurePreset": "linux-no-skia-rel"
+        }, {
+            "name": "linux-no-skia-dbg",
+            "configurePreset": "linux-no-skia-dbg"
+        }, {
+            "name": "linux-core-rel",
+            "configurePreset": "linux-core-rel"
+        }, {
+            "name": "linux-core-dbg",
+            "configurePreset": "linux-core-dbg"
+        }
+    ]
+}

+ 170 - 0
cmake/CMakePresets.json

@@ -0,0 +1,170 @@
+{
+    "version": 4,
+    "cmakeMinimumRequired": {
+        "major": 3,
+        "minor": 23,
+        "patch": 0
+    },
+    "configurePresets": [
+        {
+            "name": "release-only",
+            "displayName": "Release only configuration",
+            "hidden": true,
+            "cacheVariables": {
+                "CMAKE_BUILD_TYPE": "Release"
+            }
+        }, {
+            "name": "debug-only",
+            "displayName": "Debug only configuration",
+            "hidden": true,
+            "cacheVariables": {
+                "CMAKE_BUILD_TYPE": "Debug"
+            }
+        }, {
+            "name": "win64-base",
+            "displayName": "Windows 64-bit base configuration",
+            "hidden": true,
+            "architecture": "x64",
+            "binaryDir": "${sourceDir}/build/win64",
+            "condition": {
+                "type": "equals",
+                "lhs": "${hostSystemName}",
+                "rhs": "Windows"
+            }
+        }, {
+            "name": "win32-base",
+            "displayName": "Windows 32-bit base configuration",
+            "hidden": true,
+            "architecture": "Win32",
+            "binaryDir": "${sourceDir}/build/win32",
+            "condition": {
+                "type": "equals",
+                "lhs": "${hostSystemName}",
+                "rhs": "Windows"
+            }
+        }, {
+            "name": "osx-base",
+            "displayName": "Mac OS base configuration",
+            "hidden": true,
+            "binaryDir": "${sourceDir}/build/osx",
+            "condition": {
+                "type": "equals",
+                "lhs": "${hostSystemName}",
+                "rhs": "Darwin"
+            }
+        }, {
+            "name": "osx-rel-base",
+            "displayName": "Mac OS base release configuration",
+            "inherits": [ "osx-base", "release-only" ],
+            "hidden": true,
+            "binaryDir": "${sourceDir}/build/osx-rel"
+        }, {
+            "name": "osx-dbg-base",
+            "displayName": "Mac OS base debug configuration",
+            "inherits": [ "osx-base", "debug-only" ],
+            "hidden": true,
+            "binaryDir": "${sourceDir}/build/osx-dbg"
+        }, {
+            "name": "linux-base",
+            "displayName": "Linux base configuration",
+            "hidden": true,
+            "binaryDir": "${sourceDir}/build/linux",
+            "condition": {
+                "type": "equals",
+                "lhs": "${hostSystemName}",
+                "rhs": "Linux"
+            }
+        }, {
+            "name": "linux-rel-base",
+            "displayName": "Linux base release configuration",
+            "inherits": [ "linux-base", "release-only" ],
+            "hidden": true,
+            "binaryDir": "${sourceDir}/build/linux-rel"
+        }, {
+            "name": "linux-dbg-base",
+            "displayName": "Linux base debug configuration",
+            "inherits": [ "linux-base", "debug-only" ],
+            "hidden": true,
+            "binaryDir": "${sourceDir}/build/linux-dbg"
+        }, {
+            "name": "core-only",
+            "displayName": "Configuration with extensions disabled",
+            "hidden": true,
+            "cacheVariables": {
+                "MSDFGEN_CORE_ONLY": "ON",
+                "MSDFGEN_USE_VCPKG": "OFF",
+                "MSDFGEN_USE_SKIA": "OFF"
+            }
+        }, {
+            "name": "vcpkg",
+            "displayName": "Configuration with vcpkg as dependency management system",
+            "hidden": true,
+            "cacheVariables": {
+                "MSDFGEN_USE_VCPKG": "ON"
+            }
+        }, {
+            "name": "no-vcpkg",
+            "displayName": "Configuration with dependencies not managed by vcpkg",
+            "hidden": true,
+            "cacheVariables": {
+                "MSDFGEN_USE_VCPKG": "OFF"
+            }
+        }, {
+            "name": "openmp",
+            "displayName": "Configuration with OpenMP enabled",
+            "hidden": true,
+            "cacheVariables": {
+                "MSDFGEN_USE_OPENMP": "ON"
+            }
+        }, {
+            "name": "skia",
+            "displayName": "Configuration with Skia geometry preprocessing",
+            "hidden": true,
+            "cacheVariables": {
+                "MSDFGEN_USE_SKIA": "ON"
+            }
+        }, {
+            "name": "no-skia",
+            "displayName": "Configuration without Skia geometry preprocessing",
+            "hidden": true,
+            "cacheVariables": {
+                "MSDFGEN_USE_SKIA": "OFF"
+            }
+        }, {
+            "name": "install",
+            "displayName": "Configuration with installation targets",
+            "hidden": true,
+            "cacheVariables": {
+                "MSDFGEN_INSTALL": "ON"
+            }
+        }, {
+            "name": "static-runtime",
+            "displayName": "Configuration that links against the static runtime",
+            "hidden": true,
+            "cacheVariables": {
+                "MSDFGEN_DYNAMIC_RUNTIME": "OFF"
+            }
+        }, {
+            "name": "dynamic-runtime",
+            "displayName": "Configuration that links against the dynamic runtime",
+            "hidden": true,
+            "cacheVariables": {
+                "MSDFGEN_DYNAMIC_RUNTIME": "ON"
+            }
+        }, {
+            "name": "static-lib",
+            "displayName": "Configuration that builds and links msdfgen statically",
+            "hidden": true,
+            "cacheVariables": {
+                "BUILD_SHARED_LIBS": "OFF"
+            }
+        }, {
+            "name": "dynamic-lib",
+            "displayName": "Configuration that builds and links msdfgen dynamically",
+            "hidden": true,
+            "cacheVariables": {
+                "BUILD_SHARED_LIBS": "ON"
+            }
+        }
+    ]
+}

+ 4 - 0
core/generator-config.h

@@ -4,6 +4,10 @@
 #include <cstdlib>
 #include "BitmapRef.hpp"
 
+#ifndef MSDFGEN_PUBLIC
+#define MSDFGEN_PUBLIC // for DLL import/export
+#endif
+
 namespace msdfgen {
 
 /// The configuration of the MSDF error correction pass.

+ 121 - 55
main.cpp

@@ -16,13 +16,23 @@
 #include <string>
 
 #include "msdfgen.h"
+#ifdef MSDFGEN_EXTENSIONS
 #include "msdfgen-ext.h"
+#endif
 
 #include "core/ShapeDistanceFinder.h"
 
 #define SDF_ERROR_ESTIMATE_PRECISION 19
 #define DEFAULT_ANGLE_THRESHOLD 3.
 
+#ifdef MSDFGEN_EXTENSIONS
+#define DEFAULT_IMAGE_EXTENSION "png"
+#define SAVE_DEFAULT_IMAGE_FORMAT savePng
+#else
+#define DEFAULT_IMAGE_EXTENSION "tif"
+#define SAVE_DEFAULT_IMAGE_FORMAT saveTiff
+#endif
+
 using namespace msdfgen;
 
 enum Format {
@@ -68,19 +78,6 @@ static bool parseDouble(double &value, const char *arg) {
     return sscanf(arg, "%lf%c", &value, &c) == 1;
 }
 
-static bool parseUnicode(unicode_t &unicode, const char *arg) {
-    unsigned uuc;
-    if (parseUnsignedDecOrHex(uuc, arg)) {
-        unicode = uuc;
-        return true;
-    }
-    if (arg[0] == '\'' && arg[1] && arg[2] == '\'' && !arg[3]) {
-        unicode = (unicode_t) (unsigned char) arg[1];
-        return true;
-    }
-    return false;
-}
-
 static bool parseAngle(double &value, const char *arg) {
     char c1, c2;
     int result = sscanf(arg, "%lf%c%c", &value, &c1, &c2);
@@ -136,6 +133,20 @@ static void parseColoring(Shape &shape, const char *edgeAssignment) {
     }
 }
 
+#ifdef MSDFGEN_EXTENSIONS
+static bool parseUnicode(unicode_t &unicode, const char *arg) {
+    unsigned uuc;
+    if (parseUnsignedDecOrHex(uuc, arg)) {
+        unicode = uuc;
+        return true;
+    }
+    if (arg[0] == '\'' && arg[1] && arg[2] == '\'' && !arg[3]) {
+        unicode = (unicode_t) (unsigned char) arg[1];
+        return true;
+    }
+    return false;
+}
+
 static FontHandle * loadVarFont(FreetypeHandle *library, const char *filename) {
     std::string buffer;
     while (*filename && *filename != '?')
@@ -158,6 +169,7 @@ static FontHandle * loadVarFont(FreetypeHandle *library, const char *filename) {
     }
     return font;
 }
+#endif
 
 template <int N>
 static void invertColor(const BitmapRef<float, N> &bitmap) {
@@ -229,7 +241,12 @@ template <int N>
 static const char * writeOutput(const BitmapConstRef<float, N> &bitmap, const char *filename, Format &format) {
     if (filename) {
         if (format == AUTO) {
+        #ifdef MSDFGEN_EXTENSIONS
             if (cmpExtension(filename, ".png")) format = PNG;
+        #else
+            if (cmpExtension(filename, ".png"))
+                return "PNG format is not available in core-only version.";
+        #endif
             else if (cmpExtension(filename, ".bmp")) format = BMP;
             else if (cmpExtension(filename, ".tif") || cmpExtension(filename, ".tiff")) format = TIFF;
             else if (cmpExtension(filename, ".txt")) format = TEXT;
@@ -238,7 +255,9 @@ static const char * writeOutput(const BitmapConstRef<float, N> &bitmap, const ch
                 return "Could not deduce format from output file name.";
         }
         switch (format) {
+        #ifdef MSDFGEN_EXTENSIONS
             case PNG: return savePng(bitmap, filename) ? NULL : "Failed to write output PNG image.";
+        #endif
             case BMP: return saveBmp(bitmap, filename) ? NULL : "Failed to write output BMP image.";
             case TIFF: return saveTiff(bitmap, filename) ? NULL : "Failed to write output TIFF image.";
             case TEXT: case TEXT_FLOAT: {
@@ -285,7 +304,13 @@ static const char * writeOutput(const BitmapConstRef<float, N> &bitmap, const ch
     #define VERSION_UNDERLINE "--------"
 #endif
 
-#if defined(MSDFGEN_USE_SKIA) && defined(MSDFGEN_USE_OPENMP)
+#if !defined(MSDFGEN_EXTENSIONS) && defined(MSDFGEN_USE_OPENMP)
+    #define TITLE_SUFFIX     " - core with OpenMP"
+    #define SUFFIX_UNDERLINE "-------------------"
+#elif !defined(MSDFGEN_EXTENSIONS)
+    #define TITLE_SUFFIX     " - core only"
+    #define SUFFIX_UNDERLINE "------------"
+#elif defined(MSDFGEN_USE_SKIA) && defined(MSDFGEN_USE_OPENMP)
     #define TITLE_SUFFIX     " with Skia & OpenMP"
     #define SUFFIX_UNDERLINE "-------------------"
 #elif defined(MSDFGEN_USE_SKIA)
@@ -323,17 +348,21 @@ static const char * const helpText =
     "INPUT SPECIFICATION\n"
     "  -defineshape <definition>\n"
         "\tDefines input shape using the ad-hoc text definition.\n"
+#ifdef MSDFGEN_EXTENSIONS
     "  -font <filename.ttf> <character code>\n"
         "\tLoads a single glyph from the specified font file.\n"
         "\tFormat of character code is '?', 63, 0x3F (Unicode value), or g34 (glyph index).\n"
+#endif
     "  -shapedesc <filename.txt>\n"
         "\tLoads text shape description from a file.\n"
     "  -stdin\n"
         "\tReads text shape description from the standard input.\n"
+#ifdef MSDFGEN_EXTENSIONS
     "  -svg <filename.svg>\n"
         "\tLoads the last vector path found in the specified SVG file.\n"
     "  -varfont <filename and variables> <character code>\n"
         "\tLoads a single glyph from a variable font. Specify variable values as x.ttf?var1=0.5&var2=1\n"
+#endif
     "\n"
     // Keep alphabetical order!
     "OPTIONS\n"
@@ -361,7 +390,11 @@ static const char * const helpText =
         "\tSaves the shape description into a text file that can be edited and loaded using -shapedesc.\n"
     "  -fillrule <nonzero / evenodd / positive / negative>\n"
         "\tSets the fill rule for the scanline pass. Default is nonzero.\n"
+#ifdef MSDFGEN_EXTENSIONS
     "  -format <png / bmp / tiff / text / textfloat / bin / binfloat / binfloatbe>\n"
+#else
+    "  -format <bmp / tiff / text / textfloat / bin / binfloat / binfloatbe>\n"
+#endif
         "\tSpecifies the output format of the distance field. Otherwise it is chosen based on output file extension.\n"
     "  -guessorder\n"
         "\tAttempts to detect if shape contours have the wrong winding and generates the SDF with the right one.\n"
@@ -379,7 +412,7 @@ static const char * const helpText =
         "\tDisables the scanline pass, which corrects the distance field's signs according to the selected fill rule.\n"
 #endif
     "  -o <filename>\n"
-        "\tSets the output file name. The default value is \"output.png\".\n"
+        "\tSets the output file name. The default value is \"output." DEFAULT_IMAGE_EXTENSION "\".\n"
 #ifdef MSDFGEN_USE_SKIA
     "  -overlap\n"
         "\tSwitches to distance field generator with support for overlapping contours.\n"
@@ -404,9 +437,13 @@ static const char * const helpText =
         "\tSets the dimensions of the output image.\n"
     "  -stdout\n"
         "\tPrints the output instead of storing it in a file. Only text formats are supported.\n"
-    "  -testrender <filename.png> <width> <height>\n"
+    "  -testrender <filename." DEFAULT_IMAGE_EXTENSION "> <width> <height>\n"
+#ifdef MSDFGEN_EXTENSIONS
         "\tRenders an image preview using the generated distance field and saves it as a PNG file.\n"
-    "  -testrendermulti <filename.png> <width> <height>\n"
+#else
+        "\tRenders an image preview using the generated distance field and saves it as a TIFF file.\n"
+#endif
+    "  -testrendermulti <filename." DEFAULT_IMAGE_EXTENSION "> <width> <height>\n"
         "\tRenders an image preview without flattening the color channels.\n"
     "  -translate <x> <y>\n"
         "\tSets the translation of the shape in shape units.\n"
@@ -442,7 +479,7 @@ static const char *errorCorrectionHelpText =
     "\n";
 
 int main(int argc, const char * const *argv) {
-    #define ABORT(msg) { puts(msg); return 1; }
+    #define ABORT(msg) do { fputs(msg "\n", stderr); return 1; } while (false)
 
     // Parse command line arguments
     enum {
@@ -479,15 +516,17 @@ int main(int argc, const char * const *argv) {
     FillRule fillRule = FILL_NONZERO;
     Format format = AUTO;
     const char *input = NULL;
-    const char *output = "output.png";
+    const char *output = "output." DEFAULT_IMAGE_EXTENSION;
     const char *shapeExport = NULL;
     const char *testRender = NULL;
     const char *testRenderMulti = NULL;
     bool outputSpecified = false;
+#ifdef MSDFGEN_EXTENSIONS
     bool glyphIndexSpecified = false;
     GlyphIndex glyphIndex;
     unicode_t unicode = 0;
     int svgPathIndex = 0;
+#endif
 
     int width = 64, height = 64;
     int testWidth = 0, testHeight = 0;
@@ -536,6 +575,7 @@ int main(int argc, const char * const *argv) {
         ARG_MODE("mtsdf", MULTI_AND_TRUE)
         ARG_MODE("metrics", METRICS)
 
+    #ifdef MSDFGEN_EXTENSIONS
         ARG_CASE("-svg", 1) {
             inputType = SVG;
             input = argv[argPos+1];
@@ -562,6 +602,17 @@ int main(int argc, const char * const *argv) {
             argPos += 3;
             continue;
         }
+    #else
+        ARG_CASE("-svg", 1) {
+            ABORT("SVG input is not available in core-only version.");
+        }
+        ARG_CASE("-font", 2) {
+            ABORT("Font input is not available in core-only version.");
+        }
+        ARG_CASE("-varfont", 2) {
+            ABORT("Variable font input is not available in core-only version.");
+        }
+    #endif
         ARG_CASE("-defineshape", 1) {
             inputType = DESCRIPTION_ARG;
             input = argv[argPos+1];
@@ -638,22 +689,27 @@ int main(int argc, const char * const *argv) {
             else if (!strcmp(argv[argPos+1], "positive")) fillRule = FILL_POSITIVE;
             else if (!strcmp(argv[argPos+1], "negative")) fillRule = FILL_NEGATIVE;
             else
-                puts("Unknown fill rule specified.");
+                fputs("Unknown fill rule specified.\n", stderr);
             argPos += 2;
             continue;
         }
         ARG_CASE("-format", 1) {
             if (!strcmp(argv[argPos+1], "auto")) format = AUTO;
+        #ifdef MSDFGEN_EXTENSIONS
             else if (!strcmp(argv[argPos+1], "png")) SET_FORMAT(PNG, "png");
+        #else
+            else if (!strcmp(argv[argPos+1], "png"))
+                fputs("PNG format is not available in core-only version.\n", stderr);
+        #endif
             else if (!strcmp(argv[argPos+1], "bmp")) SET_FORMAT(BMP, "bmp");
-            else if (!strcmp(argv[argPos+1], "tiff")) SET_FORMAT(TIFF, "tif");
+            else if (!strcmp(argv[argPos+1], "tiff") || !strcmp(argv[argPos+1], "tif")) SET_FORMAT(TIFF, "tif");
             else if (!strcmp(argv[argPos+1], "text") || !strcmp(argv[argPos+1], "txt")) SET_FORMAT(TEXT, "txt");
             else if (!strcmp(argv[argPos+1], "textfloat") || !strcmp(argv[argPos+1], "txtfloat")) SET_FORMAT(TEXT_FLOAT, "txt");
             else if (!strcmp(argv[argPos+1], "bin") || !strcmp(argv[argPos+1], "binary")) SET_FORMAT(BINARY, "bin");
             else if (!strcmp(argv[argPos+1], "binfloat") || !strcmp(argv[argPos+1], "binfloatle")) SET_FORMAT(BINARY_FLOAT, "bin");
             else if (!strcmp(argv[argPos+1], "binfloatbe")) SET_FORMAT(BINARY_FLOAT_BE, "bin");
             else
-                puts("Unknown format specified.");
+                fputs("Unknown format specified.\n", stderr);
             argPos += 2;
             continue;
         }
@@ -751,7 +807,7 @@ int main(int argc, const char * const *argv) {
                 puts(errorCorrectionHelpText);
                 return 0;
             } else
-                puts("Unknown error correction mode. Use -errorcorrection help for more information.");
+                fputs("Unknown error correction mode. Use -errorcorrection help for more information.\n", stderr);
             explicitErrorCorrectionMode = true;
             argPos += 2;
             continue;
@@ -777,7 +833,7 @@ int main(int argc, const char * const *argv) {
             else if (!strcmp(argv[argPos+1], "inktrap")) edgeColoring = edgeColoringInkTrap;
             else if (!strcmp(argv[argPos+1], "distance")) edgeColoring = edgeColoringByDistance;
             else
-                puts("Unknown coloring strategy specified.");
+                fputs("Unknown coloring strategy specified.\n", stderr);
             argPos += 2;
             continue;
         }
@@ -810,7 +866,7 @@ int main(int argc, const char * const *argv) {
         ARG_CASE("-testrender", 3) {
             unsigned w, h;
             if (!parseUnsigned(w, argv[argPos+2]) || !parseUnsigned(h, argv[argPos+3]) || !w || !h)
-                ABORT("Invalid arguments for test render. Use -testrender <output.png> <width> <height>.");
+                ABORT("Invalid arguments for test render. Use -testrender <output." DEFAULT_IMAGE_EXTENSION "> <width> <height>.");
             testRender = argv[argPos+1];
             testWidth = w, testHeight = h;
             argPos += 4;
@@ -819,7 +875,7 @@ int main(int argc, const char * const *argv) {
         ARG_CASE("-testrendermulti", 3) {
             unsigned w, h;
             if (!parseUnsigned(w, argv[argPos+2]) || !parseUnsigned(h, argv[argPos+3]) || !w || !h)
-                ABORT("Invalid arguments for test render. Use -testrendermulti <output.png> <width> <height>.");
+                ABORT("Invalid arguments for test render. Use -testrendermulti <output." DEFAULT_IMAGE_EXTENSION "> <width> <height>.");
             testRenderMulti = argv[argPos+1];
             testWidthM = w, testHeightM = h;
             argPos += 4;
@@ -869,22 +925,28 @@ int main(int argc, const char * const *argv) {
             puts(helpText);
             return 0;
         }
-        printf("Unknown setting or insufficient parameters: %s\n", argv[argPos]);
+        fprintf(stderr, "Unknown setting or insufficient parameters: %s\n", argv[argPos]);
         suggestHelp = true;
         ++argPos;
     }
     if (suggestHelp)
-        printf("Use -help for more information.\n");
+        fprintf(stderr, "Use -help for more information.\n");
 
     // Load input
     Vector2 svgDims;
     double glyphAdvance = 0;
-    if (!inputType || !input)
-        ABORT("No input specified! Use either -svg <file.svg> or -font <file.ttf/otf> <character code>, or see -help.");
+    if (!inputType || !input) {
+        #ifdef MSDFGEN_EXTENSIONS
+            ABORT("No input specified! Use either -svg <file.svg> or -font <file.ttf/otf> <character code>, or see -help.");
+        #else
+            ABORT("No input specified! See -help.");
+        #endif
+    }
     if (mode == MULTI_AND_TRUE && (format == BMP || (format == AUTO && output && cmpExtension(output, ".bmp"))))
         ABORT("Incompatible image format. A BMP file cannot contain alpha channel, which is required in mtsdf mode.");
     Shape shape;
     switch (inputType) {
+    #ifdef MSDFGEN_EXTENSIONS
         case SVG: {
             if (!loadSvgShape(shape, input, svgPathIndex, &svgDims))
                 ABORT("Failed to load shape from SVG file.");
@@ -912,6 +974,7 @@ int main(int argc, const char * const *argv) {
             deinitializeFreetype(ft);
             break;
         }
+    #endif
         case DESCRIPTION_ARG: {
             if (!readShapeDescription(input, shape, &skipColoring))
                 ABORT("Parse error in shape description.");
@@ -946,10 +1009,10 @@ int main(int argc, const char * const *argv) {
         case FULL_PREPROCESS:
             #ifdef MSDFGEN_USE_SKIA
                 if (!resolveShapeGeometry(shape))
-                    puts("Shape geometry preprocessing failed, skipping.");
+                    fputs("Shape geometry preprocessing failed, skipping.\n", stderr);
                 else if (skipColoring) {
                     skipColoring = false;
-                    puts("Note: Input shape coloring won't be preserved due to geometry preprocessing");
+                    fputs("Note: Input shape coloring won't be preserved due to geometry preprocessing.\n", stderr);
                 }
             #else
                 ABORT("Shape geometry preprocessing (-preprocess) is not available in this version because the Skia library is not present.");
@@ -1040,7 +1103,7 @@ int main(int argc, const char * const *argv) {
                 case ErrorCorrectionConfig::EDGE_PRIORITY: fallbackModeName = "auto-fast"; break;
                 case ErrorCorrectionConfig::EDGE_ONLY: fallbackModeName = "edge-fast"; break;
             }
-            printf("Selected error correction mode not compatible with scanline pass, falling back to %s.\n", fallbackModeName);
+            fprintf(stderr, "Selected error correction mode not compatible with scanline pass, falling back to %s.\n", fallbackModeName);
         }
         generatorConfig.errorCorrection.mode = ErrorCorrectionConfig::DISABLED;
         postErrorCorrectionConfig.errorCorrection.distanceCheckMode = ErrorCorrectionConfig::DO_NOT_CHECK_DISTANCE;
@@ -1156,15 +1219,16 @@ int main(int argc, const char * const *argv) {
             writeShapeDescription(file, shape);
             fclose(file);
         } else
-            puts("Failed to write shape export file.");
+            fputs("Failed to write shape export file.\n", stderr);
     }
     const char *error = NULL;
     switch (mode) {
         case SINGLE:
         case PSEUDO:
-            error = writeOutput<1>(sdf, output, format);
-            if (error)
-                ABORT(error);
+            if ((error = writeOutput<1>(sdf, output, format))) {
+                fprintf(stderr, "%s\n", error);
+                return 1;
+            }
             if (is8bitFormat(format) && (testRenderMulti || testRender || estimateError))
                 simulate8bit(sdf);
             if (estimateError) {
@@ -1174,20 +1238,21 @@ int main(int argc, const char * const *argv) {
             if (testRenderMulti) {
                 Bitmap<float, 3> render(testWidthM, testHeightM);
                 renderSDF(render, sdf, avgScale*range, .5f+outputDistanceShift);
-                if (!savePng(render, testRenderMulti))
-                    puts("Failed to write test render file.");
+                if (!SAVE_DEFAULT_IMAGE_FORMAT(render, testRenderMulti))
+                    fputs("Failed to write test render file.\n", stderr);
             }
             if (testRender) {
                 Bitmap<float, 1> render(testWidth, testHeight);
                 renderSDF(render, sdf, avgScale*range, .5f+outputDistanceShift);
-                if (!savePng(render, testRender))
-                    puts("Failed to write test render file.");
+                if (!SAVE_DEFAULT_IMAGE_FORMAT(render, testRender))
+                    fputs("Failed to write test render file.\n", stderr);
             }
             break;
         case MULTI:
-            error = writeOutput<3>(msdf, output, format);
-            if (error)
-                ABORT(error);
+            if ((error = writeOutput<3>(msdf, output, format))) {
+                fprintf(stderr, "%s\n", error);
+                return 1;
+            }
             if (is8bitFormat(format) && (testRenderMulti || testRender || estimateError))
                 simulate8bit(msdf);
             if (estimateError) {
@@ -1197,20 +1262,21 @@ int main(int argc, const char * const *argv) {
             if (testRenderMulti) {
                 Bitmap<float, 3> render(testWidthM, testHeightM);
                 renderSDF(render, msdf, avgScale*range, .5f+outputDistanceShift);
-                if (!savePng(render, testRenderMulti))
-                    puts("Failed to write test render file.");
+                if (!SAVE_DEFAULT_IMAGE_FORMAT(render, testRenderMulti))
+                    fputs("Failed to write test render file.\n", stderr);
             }
             if (testRender) {
                 Bitmap<float, 1> render(testWidth, testHeight);
                 renderSDF(render, msdf, avgScale*range, .5f+outputDistanceShift);
-                if (!savePng(render, testRender))
-                    ABORT("Failed to write test render file.");
+                if (!SAVE_DEFAULT_IMAGE_FORMAT(render, testRender))
+                    fputs("Failed to write test render file.\n", stderr);
             }
             break;
         case MULTI_AND_TRUE:
-            error = writeOutput<4>(mtsdf, output, format);
-            if (error)
-                ABORT(error);
+            if ((error = writeOutput<4>(mtsdf, output, format))) {
+                fprintf(stderr, "%s\n", error);
+                return 1;
+            }
             if (is8bitFormat(format) && (testRenderMulti || testRender || estimateError))
                 simulate8bit(mtsdf);
             if (estimateError) {
@@ -1220,14 +1286,14 @@ int main(int argc, const char * const *argv) {
             if (testRenderMulti) {
                 Bitmap<float, 4> render(testWidthM, testHeightM);
                 renderSDF(render, mtsdf, avgScale*range, .5f+outputDistanceShift);
-                if (!savePng(render, testRenderMulti))
-                    puts("Failed to write test render file.");
+                if (!SAVE_DEFAULT_IMAGE_FORMAT(render, testRenderMulti))
+                    fputs("Failed to write test render file.\n", stderr);
             }
             if (testRender) {
                 Bitmap<float, 1> render(testWidth, testHeight);
                 renderSDF(render, mtsdf, avgScale*range, .5f+outputDistanceShift);
-                if (!savePng(render, testRender))
-                    ABORT("Failed to write test render file.");
+                if (!SAVE_DEFAULT_IMAGE_FORMAT(render, testRender))
+                    fputs("Failed to write test render file.\n", stderr);
             }
             break;
         default:;

+ 1 - 1
vcpkg.json

@@ -1,5 +1,5 @@
 {
-    "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg/master/scripts/vcpkg.schema.json",
+    "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/master/docs/vcpkg.schema.json",
     "name": "msdfgen",
     "version": "1.10.0",
     "default-features": [