فهرست منبع

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

Chlumsky 2 سال پیش
والد
کامیت
34baf1706e
6فایلهای تغییر یافته به همراه542 افزوده شده و 60 حذف شده
  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(MSDFGEN_DYNAMIC_RUNTIME "Link dynamic runtime library instead of static" OFF)
 option(BUILD_SHARED_LIBS "Generate dynamic library files 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)
 if(MSDFGEN_CORE_ONLY AND MSDFGEN_USE_VCPKG)
     message(STATUS "Option MSDFGEN_USE_VCPKG ignored due to MSDFGEN_CORE_ONLY - core has no dependencies")
     message(STATUS "Option MSDFGEN_USE_VCPKG ignored due to MSDFGEN_CORE_ONLY - core has no dependencies")
     set(MSDFGEN_USE_VCPKG OFF)
     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_target_properties(msdfgen-ext PROPERTIES PUBLIC_HEADER "${MSDFGEN_EXT_HEADERS}")
     set_property(TARGET msdfgen-ext PROPERTY MSVC_RUNTIME_LIBRARY "${MSDFGEN_MSVC_RUNTIME}")
     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 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_link_libraries(msdfgen-ext PRIVATE msdfgen::msdfgen-core Freetype::Freetype tinyxml2::tinyxml2 PNG::PNG)
     target_include_directories(msdfgen-ext
     target_include_directories(msdfgen-ext
         PUBLIC
         PUBLIC
@@ -171,6 +168,8 @@ if(NOT MSDFGEN_CORE_ONLY)
     add_library(msdfgen-full INTERFACE)
     add_library(msdfgen-full INTERFACE)
     add_library(msdfgen::msdfgen ALIAS msdfgen-full)
     add_library(msdfgen::msdfgen ALIAS msdfgen-full)
     target_link_libraries(msdfgen-full INTERFACE msdfgen::msdfgen-core msdfgen::msdfgen-ext)
     target_link_libraries(msdfgen-full INTERFACE msdfgen::msdfgen-core msdfgen::msdfgen-ext)
+else()
+    add_library(msdfgen::msdfgen ALIAS msdfgen-core)
 endif()
 endif()
 
 
 # Standalone executable
 # Standalone executable
@@ -187,6 +186,10 @@ if(MSDFGEN_BUILD_STANDALONE)
     set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT msdfgen)
     set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT msdfgen)
 endif()
 endif()
 
 
+# Hide ZERO_CHECK and ALL_BUILD targets
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER meta)
+
 # Installation
 # Installation
 if(MSDFGEN_INSTALL)
 if(MSDFGEN_INSTALL)
     include(GNUInstallDirs)
     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 <cstdlib>
 #include "BitmapRef.hpp"
 #include "BitmapRef.hpp"
 
 
+#ifndef MSDFGEN_PUBLIC
+#define MSDFGEN_PUBLIC // for DLL import/export
+#endif
+
 namespace msdfgen {
 namespace msdfgen {
 
 
 /// The configuration of the MSDF error correction pass.
 /// The configuration of the MSDF error correction pass.

+ 121 - 55
main.cpp

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