summaryrefslogtreecommitdiff
path: root/Build/source/libs/potrace/potrace-src/src
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/potrace/potrace-src/src')
-rw-r--r--Build/source/libs/potrace/potrace-src/src/Makefile.am61
-rw-r--r--Build/source/libs/potrace/potrace-src/src/Makefile.in901
-rw-r--r--Build/source/libs/potrace/potrace-src/src/auxiliary.h80
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_dxf.c278
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_dxf.h15
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_eps.c855
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_eps.h19
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_geojson.c223
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_geojson.h15
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_pdf.c441
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_pdf.h20
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_pgm.c106
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_pgm.h16
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_svg.c342
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_svg.h16
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_xfig.c252
-rw-r--r--Build/source/libs/potrace/potrace-src/src/backend_xfig.h15
-rw-r--r--Build/source/libs/potrace/potrace-src/src/bbox.c154
-rw-r--r--Build/source/libs/potrace/potrace-src/src/bbox.h18
-rw-r--r--Build/source/libs/potrace/potrace-src/src/bitmap.h228
-rw-r--r--Build/source/libs/potrace/potrace-src/src/bitmap_io.c886
-rw-r--r--Build/source/libs/potrace/potrace-src/src/bitmap_io.h23
-rw-r--r--Build/source/libs/potrace/potrace-src/src/bitops.h83
-rw-r--r--Build/source/libs/potrace/potrace-src/src/curve.c112
-rw-r--r--Build/source/libs/potrace/potrace-src/src/curve.h77
-rw-r--r--Build/source/libs/potrace/potrace-src/src/decompose.c521
-rw-r--r--Build/source/libs/potrace/potrace-src/src/decompose.h16
-rw-r--r--Build/source/libs/potrace/potrace-src/src/flate.c380
-rw-r--r--Build/source/libs/potrace/potrace-src/src/flate.h15
-rw-r--r--Build/source/libs/potrace/potrace-src/src/getopt.c1041
-rw-r--r--Build/source/libs/potrace/potrace-src/src/getopt1.c168
-rw-r--r--Build/source/libs/potrace/potrace-src/src/greymap.c1090
-rw-r--r--Build/source/libs/potrace/potrace-src/src/greymap.h67
-rw-r--r--Build/source/libs/potrace/potrace-src/src/include/getopt/getopt.h180
-rw-r--r--Build/source/libs/potrace/potrace-src/src/libpotrace-export.sym5
-rw-r--r--Build/source/libs/potrace/potrace-src/src/lists.h285
-rw-r--r--Build/source/libs/potrace/potrace-src/src/lzw.c415
-rw-r--r--Build/source/libs/potrace/potrace-src/src/lzw.h50
-rw-r--r--Build/source/libs/potrace/potrace-src/src/main.c1269
-rw-r--r--Build/source/libs/potrace/potrace-src/src/main.h109
-rw-r--r--Build/source/libs/potrace/potrace-src/src/mkbitmap.c794
-rw-r--r--Build/source/libs/potrace/potrace-src/src/platform.h48
-rw-r--r--Build/source/libs/potrace/potrace-src/src/potracelib.c114
-rw-r--r--Build/source/libs/potrace/potrace-src/src/potracelib.h139
-rw-r--r--Build/source/libs/potrace/potrace-src/src/potracelib_demo.c148
-rw-r--r--Build/source/libs/potrace/potrace-src/src/progress.h79
-rw-r--r--Build/source/libs/potrace/potrace-src/src/progress_bar.c207
-rw-r--r--Build/source/libs/potrace/potrace-src/src/progress_bar.h26
-rw-r--r--Build/source/libs/potrace/potrace-src/src/render.c245
-rw-r--r--Build/source/libs/potrace/potrace-src/src/render.h27
-rw-r--r--Build/source/libs/potrace/potrace-src/src/trace.c1249
-rw-r--r--Build/source/libs/potrace/potrace-src/src/trace.h15
-rw-r--r--Build/source/libs/potrace/potrace-src/src/trans.c127
-rw-r--r--Build/source/libs/potrace/potrace-src/src/trans.h36
54 files changed, 14101 insertions, 0 deletions
diff --git a/Build/source/libs/potrace/potrace-src/src/Makefile.am b/Build/source/libs/potrace/potrace-src/src/Makefile.am
new file mode 100644
index 00000000000..1a925725860
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/Makefile.am
@@ -0,0 +1,61 @@
+## Copyright (C) 2001-2019 Peter Selinger.
+## This file is part of Potrace. It is free software and it is covered
+## by the GNU General Public License. See the file COPYING for details.
+
+## Process this file with automake to produce Makefile.in
+
+AM_CFLAGS = $(CADD)
+
+#----------------------------------------------------------------------
+# programs:
+
+bin_PROGRAMS = potrace mkbitmap
+EXTRA_PROGRAMS = potracelib_demo
+
+potrace_SOURCES = main.c main.h bitmap_io.c bitmap_io.h backend_eps.c \
+ backend_eps.h flate.c flate.h lists.h greymap.c greymap.h render.c \
+ render.h backend_pgm.c backend_pgm.h backend_svg.c backend_svg.h \
+ backend_xfig.c backend_xfig.h backend_dxf.c backend_dxf.h \
+ backend_pdf.c backend_pdf.h backend_geojson.c backend_geojson.h \
+ lzw.c lzw.h bitops.h auxiliary.h potracelib.h bitmap.h curve.h \
+ platform.h progress.h progress_bar.c progress_bar.h bbox.c bbox.h \
+ trans.c trans.h
+EXTRA_potrace_SOURCES = getopt.c getopt1.c include/getopt/getopt.h
+potrace_LDADD = libpotrace.la @EXTRA_OBJS@ -lm @EXTRA_LIBS@
+potrace_DEPENDENCIES = libpotrace.la @EXTRA_OBJS@
+
+mkbitmap_SOURCES = mkbitmap.c bitmap_io.c bitmap_io.h greymap.c \
+ greymap.h platform.h bitmap.h potracelib.h bitops.h
+EXTRA_mkbitmap_SOURCES = getopt.c getopt1.c include/getopt/getopt.h
+mkbitmap_LDADD = @EXTRA_OBJS@ -lm
+mkbitmap_DEPENDENCIES = @EXTRA_OBJS@
+
+potracelib_demo_SOURCES = potracelib_demo.c
+potracelib_demo_LDADD = libpotrace.la -lm
+potracelib_demo_DEPENDENCIES = libpotrace.la
+
+AM_CPPFLAGS = @EXTRA_INCLUDES@
+
+#----------------------------------------------------------------------
+# Potrace library:
+
+libsources = curve.c curve.h trace.c trace.h decompose.c \
+ decompose.h potracelib.c potracelib.h lists.h auxiliary.h bitmap.h \
+ progress.h
+
+lib_LTLIBRARIES = $(INSTLIBS)
+EXTRA_LTLIBRARIES = libpotrace.la
+libpotrace_la_SOURCES = $(libsources)
+libpotrace_la_LDFLAGS = -version-info 0:6:0 -rpath '$(libdir)' \
+ -export-symbols $(srcdir)/libpotrace-export.sym -no-undefined
+libpotrace_la_LIBADD = -lm
+MOSTLYCLEANFILES = libpotrace.la
+
+# header files to install
+include_HEADERS = $(INSTHEADERS)
+EXTRA_HEADERS = potracelib.h
+
+#----------------------------------------------------------------------
+# other stuff to distribute
+
+EXTRA_DIST = libpotrace-export.sym
diff --git a/Build/source/libs/potrace/potrace-src/src/Makefile.in b/Build/source/libs/potrace/potrace-src/src/Makefile.in
new file mode 100644
index 00000000000..51932fa1a2c
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/Makefile.in
@@ -0,0 +1,901 @@
+# Makefile.in generated by automake 1.16.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+
+VPATH = @srcdir@
+am__is_gnu_make = { \
+ if test -z '$(MAKELEVEL)'; then \
+ false; \
+ elif test -n '$(MAKE_HOST)'; then \
+ true; \
+ elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
+ true; \
+ else \
+ false; \
+ fi; \
+}
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+bin_PROGRAMS = potrace$(EXEEXT) mkbitmap$(EXEEXT)
+EXTRA_PROGRAMS = potracelib_demo$(EXEEXT)
+subdir = src
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/libtool.m4 \
+ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
+ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+DIST_COMMON = $(srcdir)/Makefile.am $(include_HEADERS) \
+ $(am__DIST_COMMON)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" \
+ "$(DESTDIR)$(includedir)"
+PROGRAMS = $(bin_PROGRAMS)
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libpotrace_la_DEPENDENCIES =
+am__objects_1 = curve.lo trace.lo decompose.lo potracelib.lo
+am_libpotrace_la_OBJECTS = $(am__objects_1)
+libpotrace_la_OBJECTS = $(am_libpotrace_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+libpotrace_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(libpotrace_la_LDFLAGS) $(LDFLAGS) -o $@
+am_mkbitmap_OBJECTS = mkbitmap.$(OBJEXT) bitmap_io.$(OBJEXT) \
+ greymap.$(OBJEXT)
+mkbitmap_OBJECTS = $(am_mkbitmap_OBJECTS)
+am_potrace_OBJECTS = main.$(OBJEXT) bitmap_io.$(OBJEXT) \
+ backend_eps.$(OBJEXT) flate.$(OBJEXT) greymap.$(OBJEXT) \
+ render.$(OBJEXT) backend_pgm.$(OBJEXT) backend_svg.$(OBJEXT) \
+ backend_xfig.$(OBJEXT) backend_dxf.$(OBJEXT) \
+ backend_pdf.$(OBJEXT) backend_geojson.$(OBJEXT) lzw.$(OBJEXT) \
+ progress_bar.$(OBJEXT) bbox.$(OBJEXT) trans.$(OBJEXT)
+potrace_OBJECTS = $(am_potrace_OBJECTS)
+am_potracelib_demo_OBJECTS = potracelib_demo.$(OBJEXT)
+potracelib_demo_OBJECTS = $(am_potracelib_demo_OBJECTS)
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__maybe_remake_depfiles = depfiles
+am__depfiles_remade = ./$(DEPDIR)/backend_dxf.Po \
+ ./$(DEPDIR)/backend_eps.Po ./$(DEPDIR)/backend_geojson.Po \
+ ./$(DEPDIR)/backend_pdf.Po ./$(DEPDIR)/backend_pgm.Po \
+ ./$(DEPDIR)/backend_svg.Po ./$(DEPDIR)/backend_xfig.Po \
+ ./$(DEPDIR)/bbox.Po ./$(DEPDIR)/bitmap_io.Po \
+ ./$(DEPDIR)/curve.Plo ./$(DEPDIR)/decompose.Plo \
+ ./$(DEPDIR)/flate.Po ./$(DEPDIR)/getopt.Po \
+ ./$(DEPDIR)/getopt1.Po ./$(DEPDIR)/greymap.Po \
+ ./$(DEPDIR)/lzw.Po ./$(DEPDIR)/main.Po ./$(DEPDIR)/mkbitmap.Po \
+ ./$(DEPDIR)/potracelib.Plo ./$(DEPDIR)/potracelib_demo.Po \
+ ./$(DEPDIR)/progress_bar.Po ./$(DEPDIR)/render.Po \
+ ./$(DEPDIR)/trace.Plo ./$(DEPDIR)/trans.Po
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(libpotrace_la_SOURCES) $(mkbitmap_SOURCES) \
+ $(EXTRA_mkbitmap_SOURCES) $(potrace_SOURCES) \
+ $(EXTRA_potrace_SOURCES) $(potracelib_demo_SOURCES)
+DIST_SOURCES = $(libpotrace_la_SOURCES) $(mkbitmap_SOURCES) \
+ $(EXTRA_mkbitmap_SOURCES) $(potrace_SOURCES) \
+ $(EXTRA_potrace_SOURCES) $(potracelib_demo_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+HEADERS = $(include_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \
+ $(top_srcdir)/mkinstalldirs
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CPPFLAGS = @EXTRA_INCLUDES@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CADD = @CADD@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATE = @DATE@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+EXTRA_INCLUDES = @EXTRA_INCLUDES@
+EXTRA_LIBS = @EXTRA_LIBS@
+EXTRA_OBJS = @EXTRA_OBJS@
+FGREP = @FGREP@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTHEADERS = @INSTHEADERS@
+INSTLIBS = @INSTLIBS@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKBITMAP = @MKBITMAP@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+POTRACE = @POTRACE@
+POTRACELIB_VERSION = @POTRACELIB_VERSION@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+runstatedir = @runstatedir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+AM_CFLAGS = $(CADD)
+potrace_SOURCES = main.c main.h bitmap_io.c bitmap_io.h backend_eps.c \
+ backend_eps.h flate.c flate.h lists.h greymap.c greymap.h render.c \
+ render.h backend_pgm.c backend_pgm.h backend_svg.c backend_svg.h \
+ backend_xfig.c backend_xfig.h backend_dxf.c backend_dxf.h \
+ backend_pdf.c backend_pdf.h backend_geojson.c backend_geojson.h \
+ lzw.c lzw.h bitops.h auxiliary.h potracelib.h bitmap.h curve.h \
+ platform.h progress.h progress_bar.c progress_bar.h bbox.c bbox.h \
+ trans.c trans.h
+
+EXTRA_potrace_SOURCES = getopt.c getopt1.c include/getopt/getopt.h
+potrace_LDADD = libpotrace.la @EXTRA_OBJS@ -lm @EXTRA_LIBS@
+potrace_DEPENDENCIES = libpotrace.la @EXTRA_OBJS@
+mkbitmap_SOURCES = mkbitmap.c bitmap_io.c bitmap_io.h greymap.c \
+ greymap.h platform.h bitmap.h potracelib.h bitops.h
+
+EXTRA_mkbitmap_SOURCES = getopt.c getopt1.c include/getopt/getopt.h
+mkbitmap_LDADD = @EXTRA_OBJS@ -lm
+mkbitmap_DEPENDENCIES = @EXTRA_OBJS@
+potracelib_demo_SOURCES = potracelib_demo.c
+potracelib_demo_LDADD = libpotrace.la -lm
+potracelib_demo_DEPENDENCIES = libpotrace.la
+
+#----------------------------------------------------------------------
+# Potrace library:
+libsources = curve.c curve.h trace.c trace.h decompose.c \
+ decompose.h potracelib.c potracelib.h lists.h auxiliary.h bitmap.h \
+ progress.h
+
+lib_LTLIBRARIES = $(INSTLIBS)
+EXTRA_LTLIBRARIES = libpotrace.la
+libpotrace_la_SOURCES = $(libsources)
+libpotrace_la_LDFLAGS = -version-info 0:6:0 -rpath '$(libdir)' \
+ -export-symbols $(srcdir)/libpotrace-export.sym -no-undefined
+
+libpotrace_la_LIBADD = -lm
+MOSTLYCLEANFILES = libpotrace.la
+
+# header files to install
+include_HEADERS = $(INSTHEADERS)
+EXTRA_HEADERS = potracelib.h
+
+#----------------------------------------------------------------------
+# other stuff to distribute
+EXTRA_DIST = libpotrace-export.sym
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+install-binPROGRAMS: $(bin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p \
+ || test -f $$p1 \
+ ; then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' \
+ -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-binPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' \
+ `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(bindir)" && rm -f $$files
+
+clean-binPROGRAMS:
+ @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libpotrace.la: $(libpotrace_la_OBJECTS) $(libpotrace_la_DEPENDENCIES) $(EXTRA_libpotrace_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libpotrace_la_LINK) $(libpotrace_la_OBJECTS) $(libpotrace_la_LIBADD) $(LIBS)
+
+mkbitmap$(EXEEXT): $(mkbitmap_OBJECTS) $(mkbitmap_DEPENDENCIES) $(EXTRA_mkbitmap_DEPENDENCIES)
+ @rm -f mkbitmap$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(mkbitmap_OBJECTS) $(mkbitmap_LDADD) $(LIBS)
+
+potrace$(EXEEXT): $(potrace_OBJECTS) $(potrace_DEPENDENCIES) $(EXTRA_potrace_DEPENDENCIES)
+ @rm -f potrace$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(potrace_OBJECTS) $(potrace_LDADD) $(LIBS)
+
+potracelib_demo$(EXEEXT): $(potracelib_demo_OBJECTS) $(potracelib_demo_DEPENDENCIES) $(EXTRA_potracelib_demo_DEPENDENCIES)
+ @rm -f potracelib_demo$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(potracelib_demo_OBJECTS) $(potracelib_demo_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_dxf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_eps.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_geojson.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_pdf.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_pgm.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_svg.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backend_xfig.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bbox.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bitmap_io.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/curve.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decompose.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flate.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/greymap.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lzw.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mkbitmap.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/potracelib.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/potracelib_demo.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/progress_bar.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/render.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trans.Po@am__quote@ # am--include-marker
+
+$(am__depfiles_remade):
+ @$(MKDIR_P) $(@D)
+ @echo '# dummy' >$@-t && $(am__mv) $@-t $@
+
+am--depfiles: $(am__depfiles_remade)
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-includeHEADERS: $(include_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
+ done
+
+uninstall-includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(include_HEADERS)'; test -n "$(includedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) distdir-am
+
+distdir-am: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(HEADERS)
+install-binPROGRAMS: install-libLTLIBRARIES
+
+installdirs:
+ for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(includedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+ -test -z "$(MOSTLYCLEANFILES)" || rm -f $(MOSTLYCLEANFILES)
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
+ clean-libtool mostlyclean-am
+
+distclean: distclean-am
+ -rm -f ./$(DEPDIR)/backend_dxf.Po
+ -rm -f ./$(DEPDIR)/backend_eps.Po
+ -rm -f ./$(DEPDIR)/backend_geojson.Po
+ -rm -f ./$(DEPDIR)/backend_pdf.Po
+ -rm -f ./$(DEPDIR)/backend_pgm.Po
+ -rm -f ./$(DEPDIR)/backend_svg.Po
+ -rm -f ./$(DEPDIR)/backend_xfig.Po
+ -rm -f ./$(DEPDIR)/bbox.Po
+ -rm -f ./$(DEPDIR)/bitmap_io.Po
+ -rm -f ./$(DEPDIR)/curve.Plo
+ -rm -f ./$(DEPDIR)/decompose.Plo
+ -rm -f ./$(DEPDIR)/flate.Po
+ -rm -f ./$(DEPDIR)/getopt.Po
+ -rm -f ./$(DEPDIR)/getopt1.Po
+ -rm -f ./$(DEPDIR)/greymap.Po
+ -rm -f ./$(DEPDIR)/lzw.Po
+ -rm -f ./$(DEPDIR)/main.Po
+ -rm -f ./$(DEPDIR)/mkbitmap.Po
+ -rm -f ./$(DEPDIR)/potracelib.Plo
+ -rm -f ./$(DEPDIR)/potracelib_demo.Po
+ -rm -f ./$(DEPDIR)/progress_bar.Po
+ -rm -f ./$(DEPDIR)/render.Po
+ -rm -f ./$(DEPDIR)/trace.Plo
+ -rm -f ./$(DEPDIR)/trans.Po
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-includeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-binPROGRAMS install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f ./$(DEPDIR)/backend_dxf.Po
+ -rm -f ./$(DEPDIR)/backend_eps.Po
+ -rm -f ./$(DEPDIR)/backend_geojson.Po
+ -rm -f ./$(DEPDIR)/backend_pdf.Po
+ -rm -f ./$(DEPDIR)/backend_pgm.Po
+ -rm -f ./$(DEPDIR)/backend_svg.Po
+ -rm -f ./$(DEPDIR)/backend_xfig.Po
+ -rm -f ./$(DEPDIR)/bbox.Po
+ -rm -f ./$(DEPDIR)/bitmap_io.Po
+ -rm -f ./$(DEPDIR)/curve.Plo
+ -rm -f ./$(DEPDIR)/decompose.Plo
+ -rm -f ./$(DEPDIR)/flate.Po
+ -rm -f ./$(DEPDIR)/getopt.Po
+ -rm -f ./$(DEPDIR)/getopt1.Po
+ -rm -f ./$(DEPDIR)/greymap.Po
+ -rm -f ./$(DEPDIR)/lzw.Po
+ -rm -f ./$(DEPDIR)/main.Po
+ -rm -f ./$(DEPDIR)/mkbitmap.Po
+ -rm -f ./$(DEPDIR)/potracelib.Plo
+ -rm -f ./$(DEPDIR)/potracelib_demo.Po
+ -rm -f ./$(DEPDIR)/progress_bar.Po
+ -rm -f ./$(DEPDIR)/render.Po
+ -rm -f ./$(DEPDIR)/trace.Plo
+ -rm -f ./$(DEPDIR)/trans.Po
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-binPROGRAMS uninstall-includeHEADERS \
+ uninstall-libLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
+ clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \
+ clean-libtool cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-binPROGRAMS install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am \
+ install-includeHEADERS install-info install-info-am \
+ install-libLTLIBRARIES install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am uninstall-binPROGRAMS \
+ uninstall-includeHEADERS uninstall-libLTLIBRARIES
+
+.PRECIOUS: Makefile
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/Build/source/libs/potrace/potrace-src/src/auxiliary.h b/Build/source/libs/potrace/potrace-src/src/auxiliary.h
new file mode 100644
index 00000000000..6ac2713a63e
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/auxiliary.h
@@ -0,0 +1,80 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* This header file collects some general-purpose macros (and static
+ inline functions) that are used in various places. */
+
+#ifndef AUXILIARY_H
+#define AUXILIARY_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+/* ---------------------------------------------------------------------- */
+/* point arithmetic */
+
+#include "potracelib.h"
+
+struct point_s {
+ long x;
+ long y;
+};
+typedef struct point_s point_t;
+
+typedef potrace_dpoint_t dpoint_t;
+
+/* convert point_t to dpoint_t */
+static inline dpoint_t dpoint(point_t p) {
+ dpoint_t res;
+ res.x = p.x;
+ res.y = p.y;
+ return res;
+}
+
+/* range over the straight line segment [a,b] when lambda ranges over [0,1] */
+static inline dpoint_t interval(double lambda, dpoint_t a, dpoint_t b) {
+ dpoint_t res;
+
+ res.x = a.x + lambda * (b.x - a.x);
+ res.y = a.y + lambda * (b.y - a.y);
+ return res;
+}
+
+/* ---------------------------------------------------------------------- */
+/* some useful macros. Note: the "mod" macro works correctly for
+ negative a. Also note that the test for a>=n, while redundant,
+ speeds up the mod function by 70% in the average case (significant
+ since the program spends about 16% of its time here - or 40%
+ without the test). The "floordiv" macro returns the largest integer
+ <= a/n, and again this works correctly for negative a, as long as
+ a,n are integers and n>0. */
+
+/* integer arithmetic */
+
+static inline int mod(int a, int n) {
+ return a>=n ? a%n : a>=0 ? a : n-1-(-1-a)%n;
+}
+
+static inline int floordiv(int a, int n) {
+ return a>=0 ? a/n : -1-(-1-a)/n;
+}
+
+/* Note: the following work for integers and other numeric types. */
+#undef sign
+#undef abs
+#undef min
+#undef max
+#undef sq
+#undef cu
+#define sign(x) ((x)>0 ? 1 : (x)<0 ? -1 : 0)
+#define abs(a) ((a)>0 ? (a) : -(a))
+#define min(a,b) ((a)<(b) ? (a) : (b))
+#define max(a,b) ((a)>(b) ? (a) : (b))
+#define sq(a) ((a)*(a))
+#define cu(a) ((a)*(a)*(a))
+
+#endif /* AUXILIARY_H */
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_dxf.c b/Build/source/libs/potrace/potrace-src/src/backend_dxf.c
new file mode 100644
index 00000000000..3e42b95f533
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_dxf.c
@@ -0,0 +1,278 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* The DXF backend of Potrace. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+
+#include "main.h"
+#include "backend_dxf.h"
+#include "potracelib.h"
+#include "lists.h"
+#include "auxiliary.h"
+#include "trans.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary linear algebra functions */
+
+/* subtract two vectors */
+static dpoint_t sub(dpoint_t v, dpoint_t w) {
+ dpoint_t r;
+
+ r.x = v.x - w.x;
+ r.y = v.y - w.y;
+ return r;
+}
+
+/* inner product */
+static double iprod(dpoint_t v, dpoint_t w) {
+ return v.x * w.x + v.y * w.y;
+}
+
+/* cross product */
+static double xprod(dpoint_t v, dpoint_t w) {
+ return v.x * w.y - v.y * w.x;
+}
+
+/* calculate the DXF polyline "bulge" value corresponding to the angle
+ between two vectors. In case of "infinity" return 0.0. */
+static double bulge(dpoint_t v, dpoint_t w) {
+ double v2, w2, vw, vxw, nvw;
+
+ v2 = iprod(v, v);
+ w2 = iprod(w, w);
+ vw = iprod(v, w);
+ vxw = xprod(v, w);
+ nvw = sqrt(v2 * w2);
+
+ if (vxw == 0.0) {
+ return 0.0;
+ }
+
+ return (nvw - vw) / vxw;
+}
+
+/* ---------------------------------------------------------------------- */
+/* DXF output synthesis */
+
+/* print with group code: the low-level DXF file format */
+static int ship(FILE *fout, int gc, const char *fmt, ...) {
+ va_list args;
+ int r;
+ int c;
+
+ r = fprintf(fout, "%3d\n", gc);
+ if (r < 0) {
+ return r;
+ }
+ c = r;
+ va_start(args, fmt);
+ r = vfprintf(fout, fmt, args);
+ va_end(args);
+ if (r < 0) {
+ return r;
+ }
+ c += r;
+ r = fprintf(fout, "\n");
+ if (r < 0) {
+ return r;
+ }
+ c += r;
+ return c;
+}
+
+/* output the start of a polyline */
+static void ship_polyline(FILE *fout, const char *layer, int closed) {
+ ship(fout, 0, "POLYLINE");
+ ship(fout, 8, "%s", layer);
+ ship(fout, 66, "%d", 1);
+ ship(fout, 70, "%d", closed ? 1 : 0);
+}
+
+/* output a vertex */
+static void ship_vertex(FILE *fout, const char *layer, dpoint_t v, double bulge) {
+ ship(fout, 0, "VERTEX");
+ ship(fout, 8, "%s", layer);
+ ship(fout, 10, "%f", v.x);
+ ship(fout, 20, "%f", v.y);
+ ship(fout, 42, "%f", bulge);
+}
+
+/* output the end of a polyline */
+static void ship_seqend(FILE *fout) {
+ ship(fout, 0, "SEQEND");
+}
+
+/* output a comment */
+static void ship_comment(FILE *fout, const char *comment) {
+ ship(fout, 999, "%s", comment);
+}
+
+/* output the start of a section */
+static void ship_section(FILE *fout, const char *name) {
+ ship(fout, 0, "SECTION");
+ ship(fout, 2, "%s", name);
+}
+
+static void ship_endsec(FILE *fout) {
+ ship(fout, 0, "ENDSEC");
+}
+
+static void ship_eof(FILE *fout) {
+ ship(fout, 0, "EOF");
+}
+
+/* ---------------------------------------------------------------------- */
+/* Simulated quadratic and bezier curves */
+
+/* Output vertices (with bulges) corresponding to a smooth pair of
+ circular arcs from A to B, tangent to AC at A and to CB at
+ B. Segments are meant to be concatenated, so don't output the final
+ vertex. */
+static void pseudo_quad(FILE *fout, const char *layer, dpoint_t A, dpoint_t C, dpoint_t B) {
+ dpoint_t v, w;
+ double v2, w2, vw, vxw, nvw;
+ double a, b, c, y;
+ dpoint_t G;
+ double bulge1, bulge2;
+
+ v = sub(A, C);
+ w = sub(B, C);
+
+ v2 = iprod(v, v);
+ w2 = iprod(w, w);
+ vw = iprod(v, w);
+ vxw = xprod(v, w);
+ nvw = sqrt(v2 * w2);
+
+ a = v2 + 2*vw + w2;
+ b = v2 + 2*nvw + w2;
+ c = 4*nvw;
+ if (vxw == 0 || a == 0) {
+ goto degenerate;
+ }
+ /* assert: a,b,c >= 0, b*b - a*c >= 0, and 0 <= b - sqrt(b*b - a*c) <= a */
+ y = (b - sqrt(b*b - a*c)) / a;
+ G = interval(y, C, interval(0.5, A, B));
+
+ bulge1 = bulge(sub(A,G), v);
+ bulge2 = bulge(w, sub(B,G));
+
+ ship_vertex(fout, layer, A, -bulge1);
+ ship_vertex(fout, layer, G, -bulge2);
+ return;
+
+ degenerate:
+ ship_vertex(fout, layer, A, 0);
+
+ return;
+}
+
+/* produce a smooth from A to D, tangent to AB at A and to CD at D.
+ This is similar to a Bezier curve, except that our curve will be
+ made up of up to 4 circular arcs. This is particularly intended for
+ the case when AD and BC are parallel. Like arcs(), don't output the
+ final vertex. */
+static void pseudo_bezier(FILE *fout, const char *layer, dpoint_t A, dpoint_t B, dpoint_t C, dpoint_t D) {
+ dpoint_t E = interval(0.75, A, B);
+ dpoint_t G = interval(0.75, D, C);
+ dpoint_t F = interval(0.5, E, G);
+
+ pseudo_quad(fout, layer, A, E, F);
+ pseudo_quad(fout, layer, F, G, D);
+ return;
+}
+
+/* ---------------------------------------------------------------------- */
+/* functions for converting a path to a DXF polyline */
+
+/* do one path. */
+static int dxf_path(FILE *fout, const char *layer, potrace_curve_t *curve, trans_t t) {
+ int i;
+ dpoint_t *c, *c1;
+ int n = curve->n;
+
+ ship_polyline(fout, layer, 1);
+
+ for (i=0; i<n; i++) {
+ c = curve->c[i];
+ c1 = curve->c[mod(i-1,n)];
+ switch (curve->tag[i]) {
+ case POTRACE_CORNER:
+ ship_vertex(fout, layer, trans(c1[2], t), 0);
+ ship_vertex(fout, layer, trans(c[1], t), 0);
+ break;
+ case POTRACE_CURVETO:
+ pseudo_bezier(fout, layer, trans(c1[2], t), trans(c[0], t), trans(c[1], t), trans(c[2], t));
+ break;
+ }
+ }
+ ship_seqend(fout);
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Backend. */
+
+/* public interface for DXF */
+int page_dxf(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
+ potrace_path_t *p;
+ trans_t t;
+ const char *layer = "0";
+
+ /* set up the coordinate transform (rotation) */
+ t.bb[0] = imginfo->trans.bb[0]+imginfo->lmar+imginfo->rmar;
+ t.bb[1] = imginfo->trans.bb[1]+imginfo->tmar+imginfo->bmar;
+ t.orig[0] = imginfo->trans.orig[0]+imginfo->lmar;
+ t.orig[1] = imginfo->trans.orig[1]+imginfo->bmar;
+ t.x[0] = imginfo->trans.x[0];
+ t.x[1] = imginfo->trans.x[1];
+ t.y[0] = imginfo->trans.y[0];
+ t.y[1] = imginfo->trans.y[1];
+
+ ship_comment(fout, "DXF data, created by " POTRACE " " VERSION ", written by Peter Selinger 2001-2019");
+
+ /* header section */
+ ship_section(fout, "HEADER");
+
+ /* variables */
+ ship(fout, 9, "$ACADVER");
+ ship(fout, 1, "AC1006");
+ ship(fout, 9, "$EXTMIN");
+ ship(fout, 10, "%f", 0.0);
+ ship(fout, 20, "%f", 0.0);
+ ship(fout, 30, "%f", 0.0);
+ ship(fout, 9, "$EXTMAX");
+ ship(fout, 10, "%f", t.bb[0]);
+ ship(fout, 20, "%f", t.bb[1]);
+ ship(fout, 30, "%f", 0.0);
+
+ ship_endsec(fout);
+
+ /* entities section */
+ ship_section(fout, "ENTITIES");
+
+ /* write paths */
+ list_forall (p, plist) {
+ dxf_path(fout, layer, &p->curve, t);
+ }
+
+ ship_endsec(fout);
+ ship_eof(fout);
+
+ fflush(fout);
+ return 0;
+}
+
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_dxf.h b/Build/source/libs/potrace/potrace-src/src/backend_dxf.h
new file mode 100644
index 00000000000..be7424f7f51
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_dxf.h
@@ -0,0 +1,15 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef BACKEND_DXF_H
+#define BACKEND_DXF_H
+
+#include "potracelib.h"
+#include "main.h"
+
+int page_dxf(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
+
+#endif /* BACKEND_DXF_H */
+
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_eps.c b/Build/source/libs/potrace/potrace-src/src/backend_eps.c
new file mode 100644
index 00000000000..fe2878132e1
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_eps.c
@@ -0,0 +1,855 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+/* The Postscript backend of Potrace. This can produce "ps" or "eps"
+ output, and different kinds of graphical debugging
+ output. Postscript compression is optionally supplied via the
+ functions in flate.c. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "potracelib.h"
+#include "curve.h"
+#include "main.h"
+#include "backend_eps.h"
+#include "flate.h"
+#include "lists.h"
+#include "auxiliary.h"
+
+#define SAFE_CALLOC(var, n, typ) \
+ if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error
+
+typedef int color_t;
+
+#define black 0x000000
+#define red 0xff0000
+#define green 0x008000
+#define blue 0x0000ff
+
+#define TRY(x) if (x) goto try_error
+
+/* ---------------------------------------------------------------------- */
+/* functions for interfacing with compression backend */
+
+/* xship: callback function that must be initialized before calling
+ any other functions of the "ship" family. xship_file must be
+ initialized too. */
+
+/* print the token to f, but filtered through a compression
+ filter in case filter!=0 */
+static int (*xship)(FILE *f, int filter, const char *s, int len);
+static FILE *xship_file;
+
+/* ship postscript code, filtered */
+static int ship(const char *fmt, ...) {
+ va_list args;
+ static char buf[4096]; /* static string limit is okay here because
+ we only use constant format strings - for
+ the same reason, it is okay to use
+ vsprintf instead of vsnprintf below. */
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ buf[4095] = 0;
+ va_end(args);
+
+ xship(xship_file, 1, buf, strlen(buf));
+ return 0;
+}
+
+/* ship a postscript comment, unfiltered */
+static int shipcom(const char *fmt, ...) {
+ static char buf[4096];
+ va_list args;
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ buf[4095] = 0;
+ va_end(args);
+
+ xship(xship_file, 0, buf, strlen(buf));
+ return 0;
+}
+
+/* set all callback functions */
+static void eps_callbacks(FILE *fout) {
+ if (info.compress && info.pslevel==2) {
+ xship = lzw_xship;
+ } else if (info.compress && info.pslevel==3) {
+ xship = flate_xship;
+ } else {
+ xship = dummy_xship;
+ }
+ xship_file = fout;
+}
+
+/* ---------------------------------------------------------------------- */
+/* postscript path-drawing auxiliary functions */
+
+/* coordinate quantization */
+static inline point_t unit(dpoint_t p) {
+ point_t q;
+
+ q.x = (long)(floor(p.x*info.unit+.5));
+ q.y = (long)(floor(p.y*info.unit+.5));
+ return q;
+}
+
+/* current point */
+static point_t cur;
+
+static void eps_coords(dpoint_t p) {
+ cur = unit(p);
+ ship("%ld %ld ", cur.x, cur.y);
+}
+
+static void eps_rcoords(dpoint_t p) {
+ point_t q;
+
+ q = unit(p);
+ ship("%ld %ld ", q.x-cur.x, q.y-cur.y);
+ cur = q;
+}
+
+static void eps_moveto(dpoint_t p) {
+ eps_coords(p);
+ ship("moveto\n");
+}
+
+/* move to point + offset */
+static void eps_moveto_offs(dpoint_t p, double xoffs, double yoffs) {
+ /* note: structs are passed by value, so the following assignment
+ does not modify the original struct in the caller */
+ p.x += xoffs;
+ p.y += yoffs;
+ eps_coords(p);
+ ship("moveto\n");
+}
+
+static void eps_lineto(dpoint_t p) {
+ eps_rcoords(p);
+ ship("rlineto\n");
+}
+
+static void eps_curveto(dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+ point_t q1, q2, q3;
+
+ q1 = unit(p1);
+ q2 = unit(p2);
+ q3 = unit(p3);
+
+ ship("%ld %ld %ld %ld %ld %ld rcurveto\n", q1.x-cur.x, q1.y-cur.y, q2.x-cur.x, q2.y-cur.y, q3.x-cur.x, q3.y-cur.y);
+
+ cur = q3;
+}
+
+/* this procedure returns a statically allocated string */
+static const char *eps_colorstring(const color_t col) {
+ double r, g, b;
+ static char buf[100];
+
+ r = (col & 0xff0000) >> 16;
+ g = (col & 0x00ff00) >> 8;
+ b = (col & 0x0000ff) >> 0;
+
+ if (r==0 && g==0 && b==0) {
+ return "0 setgray";
+ } else if (r==255 && g==255 && b==255) {
+ return "1 setgray";
+ } else if (r == g && g == b) {
+ sprintf(buf, "%.3f setgray", r/255.0);
+ return buf;
+ } else {
+ sprintf(buf, "%.3f %.3f %.3f setrgbcolor", r/255.0, g/255.0, b/255.0);
+ return buf;
+ }
+}
+
+static color_t eps_color = -1;
+static double eps_width = -1;
+
+static void eps_setcolor(const color_t col) {
+ if (col == eps_color) {
+ return;
+ }
+ eps_color = col;
+
+ ship("%s\n", eps_colorstring(col));
+}
+
+static void eps_linewidth(double w) {
+ if (w == eps_width) {
+ return;
+ }
+ eps_width = w;
+ ship("%f setlinewidth\n", w * info.unit);
+}
+
+/* ---------------------------------------------------------------------- */
+/* functions for converting a path to postscript code */
+
+/* ---------------------------------------------------------------------- */
+/* ASCII encoding */
+
+/* explicit encoding, does not use special macros */
+static int eps_path_long(privcurve_t *curve) {
+ int i;
+ dpoint_t *c;
+ int m = curve->n;
+
+ c = curve->c[m-1];
+ eps_moveto(c[2]);
+
+ for (i=0; i<m; i++) {
+ c = curve->c[i];
+ switch (curve->tag[i]) {
+ case POTRACE_CORNER:
+ eps_lineto(c[1]);
+ eps_lineto(c[2]);
+ break;
+ case POTRACE_CURVETO:
+ eps_curveto(c[0], c[1], c[2]);
+ break;
+ }
+ }
+ return 0;
+}
+
+/* size-optimized encoding relies on special macros */
+static int eps_path_short(privcurve_t *curve) {
+ int i, i1;
+ long int *bq = NULL; /* bq[m] */
+ long int *aq = NULL; /* aq[m] */
+ point_t *v = NULL; /* v[m] */
+ dpoint_t *q = NULL; /* q[m] */
+ double M;
+ int m = curve->n;
+
+ SAFE_CALLOC(bq, m, long int);
+ SAFE_CALLOC(aq, m, long int);
+ SAFE_CALLOC(v, m, point_t);
+ SAFE_CALLOC(q, m, dpoint_t);
+
+ /* quantize vertices */
+ for (i=0; i<m; i++) {
+ v[i] = unit(curve->vertex[i]);
+ }
+
+ /* quantize beta */
+ for (i=0; i<m; i++) {
+ i1 = mod(i+1,m);
+ M = max(10, max(abs(v[i1].x-v[i].x), abs(v[i1].y-v[i].y)));
+ bq[i] = (int)(M * curve->beta[i] + 0.5);
+ if (curve->beta[i] != 0.5) {
+ q[i1] = interval(bq[i]/M, dpoint(v[i]), dpoint(v[i1]));
+ } else {
+ q[i1] = interval(0.5, dpoint(v[i]), dpoint(v[i1]));
+ }
+ }
+
+ /* quantize alpha */
+ for (i=0; i<m; i++) {
+ i1 = mod(i+1,m);
+ M = max(10, max(max(abs(q[i].x-v[i].x), abs(q[i].y-v[i].y)),
+ max(abs(v[i].x-q[i1].x), abs(v[i].y-q[i1].y))));
+ if (curve->tag[i] == POTRACE_CURVETO) {
+ aq[i] = (int)(M * curve->alpha[i] + 0.5);
+ if (aq[i] > M) {
+ aq[i]--;
+ }
+ }
+ }
+
+ /* generate output */
+ ship("%ld %ld ", v[m-1].x, v[m-1].y);
+ ship("%ld %ld ", v[0].x - v[m-1].x, v[0].y - v[m-1].y);
+ if (curve->beta[m-1] == 0.5) {
+ ship("i\n");
+ } else {
+ ship("%ld I\n", bq[m-1]);
+ }
+ for (i=0; i<m; i++) {
+ if (i<m-1) {
+ ship("%ld %ld ", v[i+1].x - v[i].x, v[i+1].y - v[i].y);
+ if (curve->beta[i] != 0.5) {
+ ship("%ld ", bq[i]);
+ }
+ }
+ if (curve->tag[i] == POTRACE_CURVETO) {
+ ship(curve->beta[i] == 0.5 ? "%ld c\n" : "%ld C\n", aq[i]);
+ } else {
+ ship(curve->beta[i] == 0.5 ? "v\n" : "V\n");
+ }
+ }
+
+ free(bq);
+ free(aq);
+ free(v);
+ free(q);
+ return 0;
+
+ calloc_error:
+ free(bq);
+ free(aq);
+ free(v);
+ free(q);
+ return 1;
+}
+
+static int eps_path(privcurve_t *curve) {
+ if (info.longcoding==0 && curve->alphacurve) {
+ return eps_path_short(curve);
+ } else {
+ return eps_path_long(curve);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* functions for rendering various internal data structures, used to
+ generate debugging output */
+
+/* output jaggie curve in grey */
+static void eps_jaggy(potrace_path_t *plist) {
+ potrace_path_t *p;
+ int i;
+
+ ship(".9 setgray\n");
+ list_forall (p, plist) {
+ point_t *pt = p->priv->pt;
+ point_t cur, prev;
+
+ if (p->sign == '+') {
+ cur = prev = pt[p->priv->len-1];
+ eps_moveto(dpoint(cur));
+ for (i=0; i<p->priv->len; i++) {
+ if (pt[i].x != cur.x && pt[i].y != cur.y) {
+ cur = prev;
+ eps_lineto(dpoint(cur));
+ }
+ prev = pt[i];
+ }
+ eps_lineto(dpoint(pt[p->priv->len-1]));
+ } else {
+ cur = prev = pt[0];
+ eps_moveto(dpoint(cur));
+ for (i=p->priv->len-1; i>=0; i--) {
+ if (pt[i].x != cur.x && pt[i].y != cur.y) {
+ cur = prev;
+ eps_lineto(dpoint(cur));
+ }
+ prev = pt[i];
+ }
+ eps_lineto(dpoint(pt[0]));
+ }
+ if (p->next == NULL || p->next->sign == '+') {
+ ship("fill\n");
+ }
+ }
+}
+
+/* output polygon */
+static void eps_polygon(privcurve_t *curve, const color_t col) {
+ int i;
+ int m = curve->n;
+
+ eps_linewidth(.02);
+ eps_setcolor(col);
+ eps_moveto(curve->vertex[m-1]);
+ for (i=0; i<m; i++) {
+ eps_lineto(curve->vertex[i]);
+ }
+ ship("stroke\n");
+}
+
+/* output lines L and parameter alpha */
+static void eps_L(privcurve_t *curve, const color_t col) {
+ int i, i1;
+ double gamma;
+ dpoint_t p1, p4, p1l, p4l;
+ int m = curve->n;
+
+ for (i=0; i<m; i++) {
+ i1 = mod(i+1, m);
+ gamma = curve->alpha0[i1] * 0.75;
+
+ p1 = curve->c[i][2];
+ p4 = curve->c[i1][2];
+ p1l = interval(gamma, p1, curve->vertex[i1]);
+ p4l = interval(gamma, p4, curve->vertex[i1]);
+ eps_linewidth(.02);
+ eps_setcolor(col);
+ eps_moveto(p1l);
+ eps_lineto(p4l);
+ ship("stroke\n");
+ eps_moveto_offs(curve->vertex[i1], -.4, -.4);
+ ship("times (%.2f) show\n", curve->alpha0[i1]);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* postscript macros */
+
+/* special macros for size-optimized rendering of Bezier curves */
+static const char *optimacros =
+ "/D{bind def}def\n"
+ "/R{roll}D\n"
+ "/K{copy}D\n"
+ "/P{pop}D\n"
+ "/p{3 2 R add 3 1 R add exch}D\n"
+ "/t{dup 4 3 R mul 3 1 R mul}D\n"
+ "/a{dup 1 sub neg 4 1 R t 5 2 R t p}D\n"
+ "/m{2 K le{exch}if P}D\n"
+ "/n{abs exch abs m}D\n"
+ "/d{-1 t p n}D\n"
+ "/s{[4 2 R] cvx def}D\n"
+ "/g{7 K P 4 K P P d 5 1 R d 10 m m div 5 K 12 8 R 5 4 R a 9 4 R 3 2 R a 6 4 R curveto}D\n"
+ "/e{4 2 R lineto lineto P P}D\n"
+ "/q{3 K P n 10 m div}D\n"
+ "/f{x y 7 4 R 5 1 R 4 K p /y s 7 2 R 2 K 9 7 R 7 6 R t p 2 K /x s}D\n"
+ "/C{4 1 R q f 7 6 R g}D\n"
+ "/V{q f e}D\n"
+ "/c{3 1 R .5 f 7 6 R g}D\n"
+ "/v{.5 f e}D\n"
+ "/j{5 K P p /y s 3 K t 7 5 R p /x s x moveto P}D\n"
+ "/i{.5 j}D\n"
+ "/I{dup 6 1 R q j 3 2 R}D\n"
+ "/z{closepath}D\n"
+ "/b{%s z fill}D\n"
+ "/w{%s z fill}D\n";
+
+/* special macros for debug output */
+static const char *debugmacros =
+ "/unit { %f } def\n"
+ "/box { newpath 0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath } def\n"
+ "/circ { newpath 0 0 1 0 360 arc closepath } def\n"
+ "/dot { gsave .15 mul dup scale circ fill grestore } def\n"
+ "/sq { gsave unit unit scale -.5 -.5 translate box .02 setlinewidth stroke grestore } def\n"
+ "/sq1 { gsave translate sq unit .6 mul dot grestore } def\n"
+ "/dot2 { gsave translate unit dot grestore } def\n"
+ "/usq { gsave unit unit scale -.5 -.5 rmoveto 0 1 rlineto 1 0 rlineto 0 -1 rlineto closepath .02 setlinewidth stroke grestore } def\n"
+ "/dot1 { gsave translate unit .3 mul dup scale circ fill grestore } def\n"
+ "/times { /Times-Roman findfont unit .3 mul scalefont setfont } def\n"
+ "/times1 { /Times-Roman findfont unit 10 mul scalefont setfont 0 0 0 setrgbcolor } def\n"
+ "/times2 { /Times-Roman findfont unit 2 mul scalefont setfont 0 0 0 setrgbcolor } def\n";
+
+/* ---------------------------------------------------------------------- */
+/* Backends for various types of output. */
+
+/* Normal output: black on transparent */
+static int render0(potrace_path_t *plist) {
+ potrace_path_t *p;
+
+ if (info.longcoding) {
+ eps_setcolor(info.color);
+ list_forall (p, plist) {
+ TRY(eps_path(p->priv->fcurve));
+ ship("closepath\n");
+ if (p->next == NULL || p->next->sign == '+') {
+ ship("fill\n");
+ }
+ }
+ } else {
+ list_forall (p, plist) {
+ TRY(eps_path(p->priv->fcurve));
+ if (p->next == NULL || p->next->sign == '+') {
+ ship("b\n");
+ } else {
+ ship("z\n");
+ }
+ }
+ }
+ return 0;
+
+ try_error:
+ return 1;
+}
+
+/* Opaque output: alternating black and white */
+static int render0_opaque(potrace_path_t *plist) {
+ potrace_path_t *p;
+
+ if (info.longcoding) {
+ list_forall (p, plist) {
+ TRY(eps_path(p->priv->fcurve));
+ ship("closepath\n");
+ eps_setcolor(p->sign=='+' ? info.color : info.fillcolor);
+ ship("fill\n");
+ }
+ } else {
+ list_forall (p, plist) {
+ TRY(eps_path(p->priv->fcurve));
+ ship(p->sign=='+' ? "b\n" : "w\n");
+ }
+ }
+ return 0;
+
+ try_error:
+ return 1;
+}
+
+/* Debug output type 1 (show optimal polygon) */
+static int render1(potrace_path_t *plist) {
+ potrace_path_t *p;
+ int i;
+
+ eps_jaggy(plist);
+
+ list_forall (p, plist) {
+
+ point_t *pt = p->priv->pt;
+ int n = p->priv->len;
+ int m = p->priv->m;
+ int *po = p->priv->po;
+
+ eps_linewidth(.02);
+ eps_setcolor(black);
+ /* output jaggie curve in boxed style */
+ for (i=1; i<n; i++) {
+ eps_moveto(dpoint(pt[i-1]));
+ eps_lineto(dpoint(pt[i]));
+ ship("stroke\n");
+ eps_coords(dpoint(pt[i]));
+ ship("sq1\n");
+ }
+ eps_moveto(dpoint(pt[n-1]));
+ eps_lineto(dpoint(pt[0]));
+ ship("stroke\n");
+ eps_coords(dpoint(pt[0]));
+ ship("sq1\n");
+
+ /* output the uncorrected polygon */
+ eps_linewidth(.1);
+ eps_setcolor(blue);
+ eps_moveto(dpoint(pt[po[0]]));
+ for (i=1; i<m; i++) {
+ eps_lineto(dpoint(pt[po[i]]));
+ }
+ eps_lineto(dpoint(pt[po[0]]));
+ ship("stroke\n");
+ for (i=0; i<m; i++) {
+ eps_coords(dpoint(pt[po[i]]));
+ ship("dot2\n");
+ }
+ }
+ return 0;
+}
+
+/* Debug output type 2 (show corrected polygon and edge detection) */
+static int render2(potrace_path_t *plist) {
+ potrace_path_t *p;
+ int i;
+
+ /* output original bitmap in grey */
+ eps_jaggy(plist);
+
+ list_forall (p, plist) {
+ /* output polygon with corrected edges, lines L, and parameter alpha */
+ eps_polygon(&p->priv->curve, black);
+ eps_L(&p->priv->curve, black);
+
+ /* output the vertex unit squares */
+ for (i=0; i<p->priv->curve.n; i++) {
+ eps_moveto(p->priv->curve.vertex[i]);
+ ship("usq\n");
+ }
+
+ /* output the path */
+ eps_linewidth(.1);
+ eps_setcolor(blue);
+ TRY(eps_path(&p->priv->curve));
+ ship("closepath\n");
+ ship("stroke\n");
+
+ if (info.param->opticurve && info.debug == 3) {
+
+ /* output opticurve */
+ eps_linewidth(.05);
+ eps_setcolor(red);
+ TRY(eps_path(&p->priv->ocurve));
+ ship("closepath\n");
+ ship("stroke\n");
+
+ /* output dots */
+ for (i=0; i<p->priv->ocurve.n; i++) {
+ eps_coords(p->priv->ocurve.c[i][2]);
+ ship("dot1\n");
+ }
+ }
+ }
+ return 0;
+
+ try_error:
+ return 1;
+}
+
+/* Free-style debug output */
+static int render_debug(potrace_path_t *plist) {
+ potrace_path_t *p;
+ int count;
+ int i;
+
+ /* output original bitmap in grey */
+ eps_jaggy(plist);
+
+ count = -1;
+ list_forall (p, plist) {
+ count++;
+
+ /* output path numbers */
+ eps_moveto_offs(p->priv->curve.vertex[0], 0, 5);
+ ship("times1 (%d) show\n", count);
+
+ /* output polygon with corrected edges, lines L, and parameter alpha */
+ eps_polygon(&p->priv->curve, black);
+ eps_L(&p->priv->curve, black);
+
+ /* output the vertex unit squares */
+ for (i=0; i<p->priv->curve.n; i++) {
+ eps_moveto(p->priv->curve.vertex[i]);
+ ship("usq\n");
+ }
+
+ /* output the vertex numbers */
+ for (i=0; i<p->priv->curve.n; i++) {
+ eps_moveto_offs(p->priv->curve.vertex[i], +1, +1);
+ ship("times2 (%d) show\n", i);
+ }
+
+ /* output the path */
+ eps_linewidth(.1);
+ eps_setcolor(blue);
+ TRY(eps_path(&p->priv->curve));
+ ship("closepath\n");
+ ship("stroke\n");
+
+ if (info.param->opticurve) {
+
+ /* output the opti-verteces polygon */
+ eps_polygon(&p->priv->ocurve, green);
+
+ /* output opticurve */
+ eps_linewidth(.05);
+ eps_setcolor(red);
+ TRY(eps_path(&p->priv->ocurve));
+ ship("closepath\n");
+ ship("stroke\n");
+
+ /* output dots */
+ for (i=0; i<p->priv->ocurve.n; i++) {
+ eps_coords(p->priv->ocurve.c[i][2]);
+ ship("dot1\n");
+ }
+
+ /* output beta parameters */
+ for (i=0; i<p->priv->ocurve.n; i++) {
+ eps_moveto_offs(p->priv->ocurve.c[i][2], +.4, -.4);
+ ship("times (%.2f) show\n", p->priv->ocurve.beta[i]);
+ }
+ }
+ }
+ return 0;
+
+ try_error:
+ return 1;
+}
+
+/* select the appropriate rendering function from above */
+static int eps_render(potrace_path_t *plist) {
+ int r;
+
+ switch (info.debug) {
+ case 0:
+ if (info.opaque) {
+ r = render0_opaque(plist);
+ } else {
+ r = render0(plist);
+ }
+ break;
+ case 1:
+ r = render1(plist);
+ break;
+ case 2: case 3:
+ r = render2(plist);
+ break;
+ default:
+ r = render_debug(plist);
+ break;
+ }
+ return r;
+}
+
+/* ---------------------------------------------------------------------- */
+/* EPS header and footer */
+
+static int eps_init(imginfo_t *imginfo) {
+ double origx = imginfo->trans.orig[0] + imginfo->lmar;
+ double origy = imginfo->trans.orig[1] + imginfo->bmar;
+ double scalex = imginfo->trans.scalex / info.unit;
+ double scaley = imginfo->trans.scaley / info.unit;
+ char *c0, *c1;
+
+ shipcom("%%!PS-Adobe-3.0 EPSF-3.0\n");
+ shipcom("%%%%Creator: " POTRACE " " VERSION ", written by Peter Selinger 2001-2019\n");
+ shipcom("%%%%LanguageLevel: %d\n", info.pslevel);
+ shipcom("%%%%BoundingBox: 0 0 %.0f %.0f\n",
+ ceil(imginfo->trans.bb[0]+imginfo->lmar+imginfo->rmar),
+ ceil(imginfo->trans.bb[1]+imginfo->tmar+imginfo->bmar));
+ shipcom("%%%%HiResBoundingBox: 0 0 %f %f\n",
+ imginfo->trans.bb[0]+imginfo->lmar+imginfo->rmar,
+ imginfo->trans.bb[1]+imginfo->tmar+imginfo->bmar);
+ shipcom("%%%%Pages: 1\n");
+ shipcom("%%%%EndComments\n");
+
+ shipcom("%%%%Page: 1 1\n");
+ ship("save\n");
+ if (!info.longcoding) {
+ c0 = strdup(eps_colorstring(info.color));
+ c1 = strdup(eps_colorstring(info.fillcolor));
+ if (!c0 || !c1) {
+ free(c0);
+ free(c1);
+ return 1;
+ }
+ ship(optimacros, c0, c1);
+ free(c0);
+ free(c1);
+ }
+ if (info.debug) {
+ ship(debugmacros, info.unit);
+ }
+ if (origx != 0 || origy != 0) {
+ ship("%f %f translate\n", origx, origy);
+ }
+ if (info.angle != 0) {
+ ship("%.2f rotate\n", info.angle);
+ }
+ ship("%f %f scale\n", scalex, scaley);
+
+ return 0;
+}
+
+static void eps_term(void) {
+ ship("restore\n");
+ shipcom("%%%%EOF\n");
+}
+
+/* public interface for EPS */
+int page_eps(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
+ eps_callbacks(fout);
+
+ TRY(eps_init(imginfo));
+ TRY(eps_render(plist));
+ eps_term();
+ return 0;
+
+ try_error:
+ return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* PostScript header and footer */
+
+static int eps_pagenumber;
+
+int init_ps(FILE *fout) {
+ char *c0, *c1;
+
+ /* set callback functions for shipping routines */
+ eps_callbacks(fout);
+
+ shipcom("%%!PS-Adobe-3.0\n");
+ shipcom("%%%%Creator: " POTRACE " " VERSION ", written by Peter Selinger 2001-2019\n");
+ shipcom("%%%%LanguageLevel: %d\n", info.pslevel);
+ shipcom("%%%%BoundingBox: 0 0 %d %d\n", info.paperwidth, info.paperheight);
+ shipcom("%%%%Pages: (atend)\n");
+ shipcom("%%%%EndComments\n");
+ if (!info.longcoding || info.debug) {
+ shipcom("%%%%BeginSetup\n");
+ if (!info.longcoding) {
+ c0 = strdup(eps_colorstring(info.color));
+ c1 = strdup(eps_colorstring(info.fillcolor));
+ if (!c0 || !c1) {
+ free(c0);
+ free(c1);
+ return 1;
+ }
+ ship(optimacros, c0, c1);
+ free(c0);
+ free(c1);
+ }
+ if (info.debug) {
+ ship(debugmacros, info.unit);
+ }
+ shipcom("%%%%EndSetup\n");
+ }
+ eps_pagenumber = 0;
+ fflush(fout);
+ return 0;
+}
+
+int term_ps(FILE *fout) {
+ eps_callbacks(fout);
+
+ shipcom("%%%%Trailer\n");
+ shipcom("%%%%Pages: %d\n", eps_pagenumber);
+ shipcom("%%%%EOF\n");
+ fflush(fout);
+
+ return 0;
+}
+
+static void eps_pageinit_ps(imginfo_t *imginfo) {
+ double origx = imginfo->trans.orig[0] + imginfo->lmar;
+ double origy = imginfo->trans.orig[1] + imginfo->bmar;
+ double scalex = imginfo->trans.scalex / info.unit;
+ double scaley = imginfo->trans.scaley / info.unit;
+
+ eps_pagenumber++;
+ eps_color = -1;
+ eps_width = -1;
+
+ shipcom("%%%%Page: %d %d\n", eps_pagenumber, eps_pagenumber);
+ ship("save\n");
+ if (origx != 0 || origy != 0) {
+ ship("%f %f translate\n", origx, origy);
+ }
+ if (info.angle != 0) {
+ ship("%.2f rotate\n", info.angle);
+ }
+ ship("%f %f scale\n", scalex, scaley);
+}
+
+static void eps_pageterm_ps(void) {
+ ship("restore\n");
+ ship("showpage\n");
+}
+
+int page_ps(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
+ int r;
+
+ eps_callbacks(fout);
+
+ eps_pageinit_ps(imginfo);
+
+ r = eps_render(plist);
+ if (r) {
+ return r;
+ }
+
+ eps_pageterm_ps();
+
+ shipcom("");
+
+ fflush(fout);
+
+ return 0;
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_eps.h b/Build/source/libs/potrace/potrace-src/src/backend_eps.h
new file mode 100644
index 00000000000..254a6c54818
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_eps.h
@@ -0,0 +1,19 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef BACKEND_EPS_H
+#define BACKEND_EPS_H
+
+#include "potracelib.h"
+#include "main.h"
+
+int init_ps(FILE *fout);
+int page_ps(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
+int term_ps(FILE *fout);
+
+int page_eps(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
+
+#endif /* BACKEND_EPS_H */
+
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_geojson.c b/Build/source/libs/potrace/potrace-src/src/backend_geojson.c
new file mode 100644
index 00000000000..8ac226b8969
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_geojson.c
@@ -0,0 +1,223 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* The GeoJSON backend of Potrace. */
+/* Written 2012 by Christoph Hormann <chris_hormann@gmx.de> */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+
+#include "potracelib.h"
+#include "curve.h"
+#include "main.h"
+#include "backend_geojson.h"
+#include "lists.h"
+#include "auxiliary.h"
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary */
+
+/* return a point on a 1-dimensional Bezier segment */
+static inline double bezier(double t, double x0, double x1, double x2, double x3) {
+ double s = 1-t;
+ return s*s*s*x0 + 3*(s*s*t)*x1 + 3*(t*t*s)*x2 + t*t*t*x3;
+}
+
+static const char *format = "%f";
+
+/* Convert a floating-point number to a string, using a pre-determined
+ format. The format must be previously set with set_format().
+ Returns one of a small number of statically allocated strings. */
+static char *round_to_unit(double x) {
+ static int n = 0;
+ static char buf[4][100];
+
+ n++;
+ if (n >= 4) {
+ n = 0;
+ }
+ sprintf(buf[n], format, x);
+ return buf[n];
+}
+
+/* Select a print format for floating point numbers, appropriate for
+ the given scaling and info.unit. Note: the format must be so that
+ the resulting number fits into a buffer of size 100. */
+static void set_format(trans_t tr) {
+ double s;
+ int d;
+ static char buf[10];
+
+ s = min(fabs(tr.scalex), fabs(tr.scaley));
+ if (info.unit != 0.0 && s != 0.0) {
+ d = (int)ceil(log(info.unit/s) / log(10));
+ } else {
+ d = 0;
+ }
+ if (d <= 0) {
+ format = "%.0f";
+ } else if (d <= 20) {
+ sprintf(buf, "%%.%df", d);
+ format = buf;
+ } else {
+ format = "%e";
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* path-drawing auxiliary functions */
+
+static dpoint_t cur;
+
+static void geojson_moveto(FILE *fout, dpoint_t p, trans_t tr) {
+ dpoint_t q;
+
+ q = trans(p, tr);
+
+ fprintf(fout, "[%s, %s]", round_to_unit(q.x), round_to_unit(q.y));
+
+ cur = q;
+}
+
+static void geojson_lineto(FILE *fout, dpoint_t p, trans_t tr) {
+ dpoint_t q;
+
+ q = trans(p, tr);
+
+ fprintf(fout, ", [%s, %s]", round_to_unit(q.x), round_to_unit(q.y));
+
+ cur = q;
+}
+
+static void geojson_curveto(FILE *fout, dpoint_t p1, dpoint_t p2, dpoint_t p3, trans_t tr) {
+ dpoint_t q1;
+ dpoint_t q2;
+ dpoint_t q3;
+ double step, t;
+ int i;
+ double x, y;
+
+ q1 = trans(p1, tr);
+ q2 = trans(p2, tr);
+ q3 = trans(p3, tr);
+
+ step = 1.0 / 8.0;
+
+ for (i=0, t=step; i<8; i++, t+=step) {
+ x = bezier(t, cur.x, q1.x, q2.x, q3.x);
+ y = bezier(t, cur.y, q1.y, q2.y, q3.y);
+
+ fprintf(fout, ", [%s, %s]", round_to_unit(x), round_to_unit(y));
+ }
+
+ cur = q3;
+}
+
+/* ---------------------------------------------------------------------- */
+/* functions for converting a path to an SVG path element */
+
+static int geojson_path(FILE *fout, potrace_curve_t *curve, trans_t tr) {
+ int i;
+ dpoint_t *c;
+ int m = curve->n;
+
+ fprintf(fout, " [");
+
+ c = curve->c[m-1];
+ geojson_moveto(fout, c[2], tr);
+
+ for (i=0; i<m; i++) {
+ c = curve->c[i];
+ switch (curve->tag[i]) {
+ case POTRACE_CORNER:
+ geojson_lineto(fout, c[1], tr);
+ geojson_lineto(fout, c[2], tr);
+ break;
+ case POTRACE_CURVETO:
+ geojson_curveto(fout, c[0], c[1], c[2], tr);
+ break;
+ }
+ }
+
+ fprintf(fout, " ]");
+
+ return 0;
+}
+
+
+static void write_polygons(FILE *fout, potrace_path_t *tree, trans_t tr, int first) {
+ potrace_path_t *p, *q;
+
+ for (p=tree; p; p=p->sibling) {
+
+ if (!first) fprintf(fout, ",\n");
+
+ fprintf(fout, "{ \"type\": \"Feature\",\n");
+ fprintf(fout, " \"properties\": { },\n");
+ fprintf(fout, " \"geometry\": {\n");
+ fprintf(fout, " \"type\": \"Polygon\",\n");
+ fprintf(fout, " \"coordinates\": [\n");
+
+ geojson_path(fout, &p->curve, tr);
+
+ for (q=p->childlist; q; q=q->sibling) {
+ fprintf(fout, ",\n");
+ geojson_path(fout, &q->curve, tr);
+ }
+
+ fprintf(fout, " ]\n");
+ fprintf(fout, " }\n");
+ fprintf(fout, "}");
+
+ for (q=p->childlist; q; q=q->sibling) {
+ write_polygons(fout, q->childlist, tr, 0);
+ }
+
+ first = 0;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* Backend. */
+
+/* public interface for GeoJSON */
+int page_geojson(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
+
+ trans_t tr;
+
+ /* set up the coordinate transform (rotation) */
+ tr.bb[0] = imginfo->trans.bb[0]+imginfo->lmar+imginfo->rmar;
+ tr.bb[1] = imginfo->trans.bb[1]+imginfo->tmar+imginfo->bmar;
+ tr.orig[0] = imginfo->trans.orig[0]+imginfo->lmar;
+ tr.orig[1] = imginfo->trans.orig[1]+imginfo->bmar;
+ tr.x[0] = imginfo->trans.x[0];
+ tr.x[1] = imginfo->trans.x[1];
+ tr.y[0] = imginfo->trans.y[0];
+ tr.y[1] = imginfo->trans.y[1];
+
+ /* set the print format for floating point numbers */
+ set_format(imginfo->trans);
+
+ /* header */
+ fprintf(fout, "{\n");
+ fprintf(fout, "\"type\": \"FeatureCollection\",\n");
+ fprintf(fout, "\"features\": [\n");
+
+ write_polygons(fout, plist, tr, 1);
+
+ /* write footer */
+ fprintf(fout, "\n]\n");
+ fprintf(fout, "}\n");
+
+ fflush(fout);
+
+ return 0;
+}
+
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_geojson.h b/Build/source/libs/potrace/potrace-src/src/backend_geojson.h
new file mode 100644
index 00000000000..1290bef0708
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_geojson.h
@@ -0,0 +1,15 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef BACKEND_GEO_H
+#define BACKEND_GEO_H
+
+#include "potracelib.h"
+#include "main.h"
+
+int page_geojson(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
+
+#endif /* BACKEND_GEO_H */
+
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_pdf.c b/Build/source/libs/potrace/potrace-src/src/backend_pdf.c
new file mode 100644
index 00000000000..c623426586e
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_pdf.c
@@ -0,0 +1,441 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+/* The PDF backend of Potrace. Stream compression is optionally
+ supplied via the functions in flate.c. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include "main.h"
+#include "backend_pdf.h"
+#include "flate.h"
+#include "lists.h"
+#include "potracelib.h"
+#include "auxiliary.h"
+
+typedef int color_t;
+
+#define TRY(x) if (x) goto try_error
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary: growing arrays */
+
+struct intarray_s {
+ int size;
+ int *data;
+};
+typedef struct intarray_s intarray_t;
+
+static inline void intarray_init(intarray_t *ar) {
+ ar->size = 0;
+ ar->data = NULL;
+}
+
+static inline void intarray_term(intarray_t *ar) {
+ free(ar->data);
+ ar->size = 0;
+ ar->data = NULL;
+}
+
+/* Set ar[n]=val. Expects n>=0. Grows array if necessary. Return 0 on
+ success and -1 on error with errno set. */
+static inline int intarray_set(intarray_t *ar, int n, int val) {
+ int *p;
+ int s;
+
+ if (n >= ar->size) {
+ s = n+1024;
+ p = (int *)realloc(ar->data, s * sizeof(int));
+ if (!p) {
+ return -1;
+ }
+ ar->data = p;
+ ar->size = s;
+ }
+ ar->data[n] = val;
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* some global variables */
+
+static intarray_t xref;
+static int nxref = 0;
+static intarray_t pages;
+static int npages;
+static int streamofs;
+static size_t outcount; /* output file position */
+
+/* ---------------------------------------------------------------------- */
+/* functions for interfacing with compression backend */
+
+/* xship: callback function that must be initialized before calling
+ any other functions of the "ship" family. xship_file must be
+ initialized too. */
+
+/* print the token to f, but filtered through a compression
+ filter in case filter!=0 */
+static int (*xship)(FILE *f, int filter, const char *s, int len);
+static FILE *xship_file;
+
+/* ship PDF code, filtered */
+static int ship(const char *fmt, ...) {
+ va_list args;
+ static char buf[4096]; /* static string limit is okay here because
+ we only use constant format strings - for
+ the same reason, it is okay to use
+ vsprintf instead of vsnprintf below. */
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ buf[4095] = 0;
+ va_end(args);
+
+ outcount += xship(xship_file, 1, buf, strlen(buf));
+ return 0;
+}
+
+/* ship PDF code, unfiltered */
+static int shipclear(const char *fmt, ...) {
+ static char buf[4096];
+ va_list args;
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ buf[4095] = 0;
+ va_end(args);
+
+ outcount += xship(xship_file, 0, buf, strlen(buf));
+ return 0;
+}
+
+/* set all callback functions */
+static void pdf_callbacks(FILE *fout) {
+
+ if (info.compress) {
+ xship = pdf_xship;
+ } else {
+ xship = dummy_xship;
+ }
+ xship_file = fout;
+}
+
+/* ---------------------------------------------------------------------- */
+/* PDF path-drawing auxiliary functions */
+
+/* coordinate quantization */
+static inline point_t unit(dpoint_t p) {
+ point_t q;
+
+ q.x = (long)(floor(p.x*info.unit+.5));
+ q.y = (long)(floor(p.y*info.unit+.5));
+ return q;
+}
+
+static void pdf_coords(dpoint_t p) {
+ point_t cur = unit(p);
+ ship("%ld %ld ", cur.x, cur.y);
+}
+
+static void pdf_moveto(dpoint_t p) {
+ pdf_coords(p);
+ ship("m\n");
+}
+
+static void pdf_lineto(dpoint_t p) {
+ pdf_coords(p);
+ ship("l\n");
+}
+
+static void pdf_curveto(dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+ point_t q1, q2, q3;
+
+ q1 = unit(p1);
+ q2 = unit(p2);
+ q3 = unit(p3);
+
+ ship("%ld %ld %ld %ld %ld %ld c\n", q1.x, q1.y, q2.x, q2.y, q3.x, q3.y);
+}
+
+/* this procedure returns a statically allocated string */
+static const char *pdf_colorstring(const color_t col) {
+ double r, g, b;
+ static char buf[100];
+
+ r = (col & 0xff0000) >> 16;
+ g = (col & 0x00ff00) >> 8;
+ b = (col & 0x0000ff) >> 0;
+
+ if (r==0 && g==0 && b==0) {
+ return "0 g";
+ } else if (r==255 && g==255 && b==255) {
+ return "1 g";
+ } else if (r == g && g == b) {
+ sprintf(buf, "%.3f g", r/255.0);
+ return buf;
+ } else {
+ sprintf(buf, "%.3f %.3f %.3f rg", r/255.0, g/255.0, b/255.0);
+ return buf;
+ }
+}
+
+static color_t pdf_color = -1;
+
+static void pdf_setcolor(const color_t col) {
+ if (col == pdf_color) {
+ return;
+ }
+ pdf_color = col;
+
+ ship("%s\n", pdf_colorstring(col));
+}
+
+/* explicit encoding, does not use special macros */
+static int pdf_path(potrace_curve_t *curve) {
+ int i;
+ dpoint_t *c;
+ int m = curve->n;
+
+ c = curve->c[m-1];
+ pdf_moveto(c[2]);
+
+ for (i=0; i<m; i++) {
+ c = curve->c[i];
+ switch (curve->tag[i]) {
+ case POTRACE_CORNER:
+ pdf_lineto(c[1]);
+ pdf_lineto(c[2]);
+ break;
+ case POTRACE_CURVETO:
+ pdf_curveto(c[0], c[1], c[2]);
+ break;
+ }
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Backends for various types of output. */
+
+/* Normal output: black on transparent */
+static int render0(potrace_path_t *plist) {
+ potrace_path_t *p;
+
+ pdf_setcolor(info.color);
+ list_forall (p, plist) {
+ pdf_path(&p->curve);
+ ship("h\n");
+ if (p->next == NULL || p->next->sign == '+') {
+ ship("f\n");
+ }
+ }
+ return 0;
+}
+
+/* Opaque output: alternating black and white */
+static int render0_opaque(potrace_path_t *plist) {
+ potrace_path_t *p;
+
+ list_forall (p, plist) {
+ pdf_path(&p->curve);
+ ship("h\n");
+ pdf_setcolor(p->sign=='+' ? info.color : info.fillcolor);
+ ship("f\n");
+ }
+ return 0;
+}
+
+/* select the appropriate rendering function from above */
+static int pdf_render(potrace_path_t *plist)
+{
+ if (info.opaque) {
+ return render0_opaque(plist);
+ }
+ return render0(plist);
+}
+
+/* ---------------------------------------------------------------------- */
+/* PDF header and footer */
+
+int init_pdf(FILE *fout)
+{
+ intarray_init(&xref);
+ intarray_init(&pages);
+ nxref = 0;
+ npages = 0;
+
+ /* set callback functions for shipping routines */
+ pdf_callbacks(fout);
+ outcount = 0;
+
+ shipclear("%%PDF-1.3\n");
+
+ TRY(intarray_set(&xref, nxref++, outcount));
+ shipclear("1 0 obj\n<</Type/Catalog/Pages 3 0 R>>\nendobj\n");
+
+ TRY(intarray_set(&xref, nxref++, outcount));
+ shipclear("2 0 obj\n"
+ "<</Creator"
+ "(" POTRACE " " VERSION ", written by Peter Selinger 2001-2019)>>\n"
+ "endobj\n");
+
+ /* delay obj #3 (pages) until end */
+ nxref++;
+
+ fflush(fout);
+ return 0;
+
+ try_error:
+ return 1;
+}
+
+int term_pdf(FILE *fout)
+{
+ int startxref;
+ int i;
+
+ pdf_callbacks(fout);
+
+ TRY(intarray_set(&xref, 2, outcount));
+ shipclear("3 0 obj\n"
+ "<</Type/Pages/Count %d/Kids[\n", npages);
+ for (i = 0; i < npages; i++)
+ shipclear("%d 0 R\n", pages.data[i]);
+ shipclear("]>>\nendobj\n");
+
+ startxref = outcount;
+
+ shipclear("xref\n0 %d\n", nxref + 1);
+ shipclear("0000000000 65535 f \n");
+ for (i = 0; i < nxref; i++)
+ shipclear("%0.10d 00000 n \n", xref.data[i]);
+
+ shipclear("trailer\n<</Size %d/Root 1 0 R/Info 2 0 R>>\n", nxref + 1);
+ shipclear("startxref\n%d\n%%%%EOF\n", startxref);
+
+ fflush(fout);
+ intarray_term(&xref);
+ intarray_term(&pages);
+ return 0;
+
+ try_error:
+ return 1;
+}
+
+/* if largebbox is set, set bounding box to pagesize. Return 0 on
+ success or 1 on error with errno set. */
+static int pdf_pageinit(imginfo_t *imginfo, int largebbox)
+{
+ double origx = imginfo->trans.orig[0] + imginfo->lmar;
+ double origy = imginfo->trans.orig[1] + imginfo->bmar;
+ double dxx = imginfo->trans.x[0] / info.unit;
+ double dxy = imginfo->trans.x[1] / info.unit;
+ double dyx = imginfo->trans.y[0] / info.unit;
+ double dyy = imginfo->trans.y[1] / info.unit;
+
+ double pagew = imginfo->trans.bb[0]+imginfo->lmar+imginfo->rmar;
+ double pageh = imginfo->trans.bb[1]+imginfo->tmar+imginfo->bmar;
+
+ pdf_color = -1;
+
+ TRY(intarray_set(&xref, nxref++, outcount));
+ shipclear("%d 0 obj\n", nxref);
+ shipclear("<</Type/Page/Parent 3 0 R/Resources<</ProcSet[/PDF]>>");
+ if (largebbox) {
+ shipclear("/MediaBox[0 0 %d %d]", info.paperwidth, info.paperheight);
+ } else {
+ shipclear("/MediaBox[0 0 %f %f]", pagew, pageh);
+ }
+ shipclear("/Contents %d 0 R>>\n", nxref + 1);
+ shipclear("endobj\n");
+
+ TRY(intarray_set(&pages, npages++, nxref));
+
+ TRY(intarray_set(&xref, nxref++, outcount));
+ shipclear("%d 0 obj\n", nxref);
+ if (info.compress)
+ shipclear("<</Filter/FlateDecode/Length %d 0 R>>\n", nxref + 1);
+ else
+ shipclear("<</Length %d 0 R>>\n", nxref + 1);
+ shipclear("stream\n");
+
+ streamofs = outcount;
+
+ ship("%f %f %f %f %f %f cm\n", dxx, dxy, dyx, dyy, origx, origy);
+ return 0;
+
+ try_error:
+ return 1;
+}
+
+/* Return 0 on success or 1 on error with errno set. */
+static int pdf_pageterm(void)
+{
+ int streamlen;
+
+ shipclear("");
+
+ streamlen = outcount - streamofs;
+ shipclear("endstream\nendobj\n");
+
+ TRY(intarray_set(&xref, nxref++, outcount));
+ shipclear("%d 0 obj\n%d\nendobj\n", nxref, streamlen);
+ return 0;
+
+ try_error:
+ return 1;
+}
+
+int page_pdf(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo)
+{
+ int r;
+
+ pdf_callbacks(fout);
+
+ TRY(pdf_pageinit(imginfo, 0));
+
+ r = pdf_render(plist);
+ if (r) {
+ return r;
+ }
+
+ TRY(pdf_pageterm());
+
+ fflush(fout);
+ return 0;
+
+ try_error:
+ return 1;
+}
+
+int page_pdfpage(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo)
+{
+ int r;
+
+ pdf_callbacks(fout);
+
+ TRY(pdf_pageinit(imginfo, 1));
+
+ r = pdf_render(plist);
+ if (r) {
+ return r;
+ }
+
+ TRY(pdf_pageterm());
+
+ fflush(fout);
+ return 0;
+
+ try_error:
+ return 1;
+}
+
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_pdf.h b/Build/source/libs/potrace/potrace-src/src/backend_pdf.h
new file mode 100644
index 00000000000..0886318991b
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_pdf.h
@@ -0,0 +1,20 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef BACKEND_PDF_H
+#define BACKEND_PDF_H
+
+#include "potracelib.h"
+#include "main.h"
+
+int init_pdf(FILE *fout);
+int page_pdf(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
+int term_pdf(FILE *fout);
+
+int page_pdf(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
+int page_pdfpage(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
+
+#endif /* BACKEND_PDF_H */
+
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_pgm.c b/Build/source/libs/potrace/potrace-src/src/backend_pgm.c
new file mode 100644
index 00000000000..3f7632b1505
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_pgm.c
@@ -0,0 +1,106 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+/* The PGM backend of Potrace. Here we custom-render a set of Bezier
+ curves and output the result as a greymap. This is merely a
+ convenience, as the same could be achieved by piping the EPS output
+ through ghostscript. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+
+#include "backend_pgm.h"
+#include "potracelib.h"
+#include "lists.h"
+#include "greymap.h"
+#include "render.h"
+#include "main.h"
+#include "auxiliary.h"
+#include "trans.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+static void pgm_path(potrace_curve_t *curve, trans_t t, render_t *rm) {
+ dpoint_t *c, c1[3];
+ int i;
+ int m = curve->n;
+
+ c = curve->c[m-1];
+ c1[2] = trans(c[2], t);
+ render_moveto(rm, c1[2].x, c1[2].y);
+
+ for (i=0; i<m; i++) {
+ c = curve->c[i];
+ switch (curve->tag[i]) {
+ case POTRACE_CORNER:
+ c1[1] = trans(c[1], t);
+ c1[2] = trans(c[2], t);
+ render_lineto(rm, c1[1].x, c1[1].y);
+ render_lineto(rm, c1[2].x, c1[2].y);
+ break;
+ case POTRACE_CURVETO:
+ c1[0] = trans(c[0], t);
+ c1[1] = trans(c[1], t);
+ c1[2] = trans(c[2], t);
+ render_curveto(rm, c1[0].x, c1[0].y, c1[1].x, c1[1].y, c1[2].x, c1[2].y);
+ break;
+ }
+ }
+}
+
+int page_pgm(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
+ potrace_path_t *p;
+ greymap_t *gm;
+ render_t *rm;
+ int w, h;
+ trans_t t;
+ int mode;
+ const char *comment = "created by " POTRACE " " VERSION ", written by Peter Selinger 2001-2019";
+
+ t.bb[0] = imginfo->trans.bb[0]+imginfo->lmar+imginfo->rmar;
+ t.bb[1] = imginfo->trans.bb[1]+imginfo->tmar+imginfo->bmar;
+ t.orig[0] = imginfo->trans.orig[0]+imginfo->lmar;
+ t.orig[1] = imginfo->trans.orig[1]+imginfo->bmar;
+ t.x[0] = imginfo->trans.x[0];
+ t.x[1] = imginfo->trans.x[1];
+ t.y[0] = imginfo->trans.y[0];
+ t.y[1] = imginfo->trans.y[1];
+
+ w = (int)ceil(t.bb[0]);
+ h = (int)ceil(t.bb[1]);
+
+ gm = gm_new(w, h);
+ if (!gm) {
+ return 1;
+ }
+ rm = render_new(gm);
+ if (!rm) {
+ return 1;
+ }
+
+ gm_clear(gm, 255); /* white */
+
+ list_forall(p, plist) {
+ pgm_path(&p->curve, t, rm);
+ }
+
+ render_close(rm);
+
+ /* if negative orientation, make sure to invert effect of rendering */
+ mode = imginfo->width * imginfo->height < 0 ? GM_MODE_NEGATIVE : GM_MODE_POSITIVE;
+
+ gm_writepgm(fout, rm->gm, comment, 1, mode, info.gamma);
+
+ render_free(rm);
+ gm_free(gm);
+
+ return 0;
+}
+
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_pgm.h b/Build/source/libs/potrace/potrace-src/src/backend_pgm.h
new file mode 100644
index 00000000000..55d77771929
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_pgm.h
@@ -0,0 +1,16 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef BACKEND_PGM_H
+#define BACKEND_PGM_H
+
+#include <stdio.h>
+
+#include "potracelib.h"
+#include "main.h"
+
+int page_pgm(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
+
+#endif /* BACKEND_PGM_H */
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_svg.c b/Build/source/libs/potrace/potrace-src/src/backend_svg.c
new file mode 100644
index 00000000000..7b1d3a3b010
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_svg.c
@@ -0,0 +1,342 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+/* The SVG backend of Potrace. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+
+#include "potracelib.h"
+#include "curve.h"
+#include "main.h"
+#include "backend_svg.h"
+#include "lists.h"
+#include "auxiliary.h"
+
+/* ---------------------------------------------------------------------- */
+/* path-drawing auxiliary functions */
+
+/* coordinate quantization */
+static inline point_t unit(dpoint_t p) {
+ point_t q;
+
+ q.x = (long)(floor(p.x*info.unit+.5));
+ q.y = (long)(floor(p.y*info.unit+.5));
+ return q;
+}
+
+static point_t cur;
+static char lastop = 0;
+static int column = 0;
+static int newline = 1;
+
+static void shiptoken(FILE *fout, const char *token) {
+ int c = strlen(token);
+ if (!newline && column+c+1 > 75) {
+ fprintf(fout, "\n");
+ column = 0;
+ newline = 1;
+ } else if (!newline) {
+ fprintf(fout, " ");
+ column++;
+ }
+ fprintf(fout, "%s", token);
+ column += c;
+ newline = 0;
+}
+
+static void ship(FILE *fout, const char *fmt, ...) {
+ va_list args;
+ static char buf[4096]; /* static string limit is okay here because
+ we only use constant format strings - for
+ the same reason, it is okay to use
+ vsprintf instead of vsnprintf below. */
+ char *p, *q;
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ buf[4095] = 0;
+ va_end(args);
+
+ p = buf;
+ while ((q = strchr(p, ' ')) != NULL) {
+ *q = 0;
+ shiptoken(fout, p);
+ p = q+1;
+ }
+ shiptoken(fout, p);
+}
+
+static void svg_moveto(FILE *fout, dpoint_t p) {
+ cur = unit(p);
+
+ ship(fout, "M%ld %ld", cur.x, cur.y);
+ lastop = 'M';
+}
+
+static void svg_rmoveto(FILE *fout, dpoint_t p) {
+ point_t q;
+
+ q = unit(p);
+ ship(fout, "m%ld %ld", q.x-cur.x, q.y-cur.y);
+ cur = q;
+ lastop = 'm';
+}
+
+static void svg_lineto(FILE *fout, dpoint_t p) {
+ point_t q;
+
+ q = unit(p);
+
+ if (lastop != 'l') {
+ ship(fout, "l%ld %ld", q.x-cur.x, q.y-cur.y);
+ } else {
+ ship(fout, "%ld %ld", q.x-cur.x, q.y-cur.y);
+ }
+ cur = q;
+ lastop = 'l';
+}
+
+static void svg_curveto(FILE *fout, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+ point_t q1, q2, q3;
+
+ q1 = unit(p1);
+ q2 = unit(p2);
+ q3 = unit(p3);
+
+ if (lastop != 'c') {
+ ship(fout, "c%ld %ld %ld %ld %ld %ld", q1.x-cur.x, q1.y-cur.y, q2.x-cur.x, q2.y-cur.y, q3.x-cur.x, q3.y-cur.y);
+ } else {
+ ship(fout, "%ld %ld %ld %ld %ld %ld", q1.x-cur.x, q1.y-cur.y, q2.x-cur.x, q2.y-cur.y, q3.x-cur.x, q3.y-cur.y);
+ }
+ cur = q3;
+ lastop = 'c';
+}
+
+/* ---------------------------------------------------------------------- */
+/* functions for converting a path to an SVG path element */
+
+/* Explicit encoding. If abs is set, move to first coordinate
+ absolutely. */
+static int svg_path(FILE *fout, potrace_curve_t *curve, int abs) {
+ int i;
+ dpoint_t *c;
+ int m = curve->n;
+
+ c = curve->c[m-1];
+ if (abs) {
+ svg_moveto(fout, c[2]);
+ } else {
+ svg_rmoveto(fout, c[2]);
+ }
+
+ for (i=0; i<m; i++) {
+ c = curve->c[i];
+ switch (curve->tag[i]) {
+ case POTRACE_CORNER:
+ svg_lineto(fout, c[1]);
+ svg_lineto(fout, c[2]);
+ break;
+ case POTRACE_CURVETO:
+ svg_curveto(fout, c[0], c[1], c[2]);
+ break;
+ }
+ }
+ newline = 1;
+ shiptoken(fout, "z");
+ return 0;
+}
+
+/* produce a jaggy path - for debugging. If abs is set, move to first
+ coordinate absolutely. If abs is not set, move to first coordinate
+ relatively, and traverse path in the opposite direction. */
+static int svg_jaggy_path(FILE *fout, point_t *pt, int n, int abs) {
+ int i;
+ point_t cur, prev;
+
+ if (abs) {
+ cur = prev = pt[n-1];
+ svg_moveto(fout, dpoint(cur));
+ for (i=0; i<n; i++) {
+ if (pt[i].x != cur.x && pt[i].y != cur.y) {
+ cur = prev;
+ svg_lineto(fout, dpoint(cur));
+ }
+ prev = pt[i];
+ }
+ svg_lineto(fout, dpoint(pt[n-1]));
+ } else {
+ cur = prev = pt[0];
+ svg_rmoveto(fout, dpoint(cur));
+ for (i=n-1; i>=0; i--) {
+ if (pt[i].x != cur.x && pt[i].y != cur.y) {
+ cur = prev;
+ svg_lineto(fout, dpoint(cur));
+ }
+ prev = pt[i];
+ }
+ svg_lineto(fout, dpoint(pt[0]));
+ }
+ newline = 1;
+ shiptoken(fout, "z");
+ return 0;
+}
+
+static void write_paths_opaque(FILE *fout, potrace_path_t *tree) {
+ potrace_path_t *p, *q;
+
+ for (p=tree; p; p=p->sibling) {
+ if (info.grouping == 2) {
+ fprintf(fout, "<g>\n");
+ fprintf(fout, "<g>\n");
+ }
+ column = fprintf(fout, "<path fill=\"#%06x\" stroke=\"none\" d=\"", info.color);
+ newline = 1;
+ lastop = 0;
+ if (info.debug == 1) {
+ svg_jaggy_path(fout, p->priv->pt, p->priv->len, 1);
+ } else {
+ svg_path(fout, &p->curve, 1);
+ }
+ fprintf(fout, "\"/>\n");
+ for (q=p->childlist; q; q=q->sibling) {
+ column = fprintf(fout, "<path fill=\"#%06x\" stroke=\"none\" d=\"", info.fillcolor);
+ newline = 1;
+ lastop = 0;
+ if (info.debug == 1) {
+ svg_jaggy_path(fout, q->priv->pt, q->priv->len, 1);
+ } else {
+ svg_path(fout, &q->curve, 1);
+ }
+ fprintf(fout, "\"/>\n");
+ }
+ if (info.grouping == 2) {
+ fprintf(fout, "</g>\n");
+ }
+ for (q=p->childlist; q; q=q->sibling) {
+ write_paths_opaque(fout, q->childlist);
+ }
+ if (info.grouping == 2) {
+ fprintf(fout, "</g>\n");
+ }
+ }
+}
+
+static void write_paths_transparent_rec(FILE *fout, potrace_path_t *tree) {
+ potrace_path_t *p, *q;
+
+ for (p=tree; p; p=p->sibling) {
+ if (info.grouping == 2) {
+ fprintf(fout, "<g>\n");
+ }
+ if (info.grouping != 0) {
+ column = fprintf(fout, "<path d=\"");
+ newline = 1;
+ lastop = 0;
+ }
+ if (info.debug == 1) {
+ svg_jaggy_path(fout, p->priv->pt, p->priv->len, 1);
+ } else {
+ svg_path(fout, &p->curve, 1);
+ }
+ for (q=p->childlist; q; q=q->sibling) {
+ if (info.debug == 1) {
+ svg_jaggy_path(fout, q->priv->pt, q->priv->len, 0);
+ } else {
+ svg_path(fout, &q->curve, 0);
+ }
+ }
+ if (info.grouping != 0) {
+ fprintf(fout, "\"/>\n");
+ }
+ for (q=p->childlist; q; q=q->sibling) {
+ write_paths_transparent_rec(fout, q->childlist);
+ }
+ if (info.grouping == 2) {
+ fprintf(fout, "</g>\n");
+ }
+ }
+}
+
+static void write_paths_transparent(FILE *fout, potrace_path_t *tree) {
+ if (info.grouping == 0) {
+ column = fprintf(fout, "<path d=\"");
+ newline = 1;
+ lastop = 0;
+ }
+ write_paths_transparent_rec(fout, tree);
+ if (info.grouping == 0) {
+ fprintf(fout, "\"/>\n");
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* Backend. */
+
+/* public interface for SVG */
+int page_svg(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
+
+ double bboxx = imginfo->trans.bb[0]+imginfo->lmar+imginfo->rmar;
+ double bboxy = imginfo->trans.bb[1]+imginfo->tmar+imginfo->bmar;
+ double origx = imginfo->trans.orig[0] + imginfo->lmar;
+ double origy = bboxy - imginfo->trans.orig[1] - imginfo->bmar;
+ double scalex = imginfo->trans.scalex / info.unit;
+ double scaley = -imginfo->trans.scaley / info.unit;
+
+ /* header */
+ fprintf(fout, "<?xml version=\"1.0\" standalone=\"no\"?>\n");
+ fprintf(fout, "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\"\n");
+ fprintf(fout, " \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n");
+
+ /* set bounding box and namespace */
+ fprintf(fout, "<svg version=\"1.0\" xmlns=\"http://www.w3.org/2000/svg\"\n");
+ fprintf(fout, " width=\"%fpt\" height=\"%fpt\" viewBox=\"0 0 %f %f\"\n",
+ bboxx, bboxy, bboxx, bboxy);
+ fprintf(fout, " preserveAspectRatio=\"xMidYMid meet\">\n");
+
+ /* metadata: creator */
+ fprintf(fout, "<metadata>\n");
+ fprintf(fout, "Created by " POTRACE " " VERSION ", written by Peter Selinger 2001-2019\n");
+ fprintf(fout, "</metadata>\n");
+
+ /* use a "group" tag to establish coordinate system and style */
+ fprintf(fout, "<g transform=\"");
+ if (origx != 0 || origy != 0) {
+ fprintf(fout, "translate(%f,%f) ", origx, origy);
+ }
+ if (info.angle != 0) {
+ fprintf(fout, "rotate(%.2f) ", -info.angle);
+ }
+ fprintf(fout, "scale(%f,%f)", scalex, scaley);
+ fprintf(fout, "\"\n");
+ fprintf(fout, "fill=\"#%06x\" stroke=\"none\">\n", info.color);
+
+ if (info.opaque) {
+ write_paths_opaque(fout, plist);
+ } else {
+ write_paths_transparent(fout, plist);
+ }
+
+ /* write footer */
+ fprintf(fout, "</g>\n");
+ fprintf(fout, "</svg>\n");
+ fflush(fout);
+
+ return 0;
+}
+
+/* the Gimppath backend is identical, except that it disables
+ --opaque, enables --flat, and the dimensions are pixel-based */
+int page_gimp(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
+ info.opaque = 0;
+ info.grouping = 0;
+ return page_svg(fout, plist, imginfo);
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_svg.h b/Build/source/libs/potrace/potrace-src/src/backend_svg.h
new file mode 100644
index 00000000000..29ae6f0abb5
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_svg.h
@@ -0,0 +1,16 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef BACKEND_SVG_H
+#define BACKEND_SVG_H
+
+#include "potracelib.h"
+#include "main.h"
+
+int page_svg(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
+int page_gimp(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
+
+#endif /* BACKEND_SVG_H */
+
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_xfig.c b/Build/source/libs/potrace/potrace-src/src/backend_xfig.c
new file mode 100644
index 00000000000..e0a5f2eb8b8
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_xfig.c
@@ -0,0 +1,252 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+/* The xfig backend of Potrace. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <math.h>
+
+#include "main.h"
+#include "backend_xfig.h"
+#include "potracelib.h"
+#include "lists.h"
+#include "auxiliary.h"
+#include "trans.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+struct pageformat_s {
+ const char *name;
+ int w, h;
+};
+typedef struct pageformat_s pageformat_t;
+
+/* page formats known by xfig, and their dimensions in postscript points */
+static pageformat_t pageformat[] = {
+ { "A9", 105, 149 },
+ { "A8", 149, 211 },
+ { "A7", 211, 298 },
+ { "A6", 298, 421 },
+ { "A5", 421, 595 },
+ { "A4", 595, 842 },
+ { "A3", 842, 1191 },
+ { "A2", 1191, 1685 },
+ { "A1", 1685, 2383 },
+ { "A0", 2383, 3370 },
+
+ { "B10", 91, 129 },
+ { "B9", 129, 182 },
+ { "B8", 182, 258 },
+ { "B7", 258, 365 },
+ { "B6", 365, 516 },
+ { "B5", 516, 730 },
+ { "B4", 730, 1032 },
+ { "B3", 1032, 1460 },
+ { "B2", 1460, 2064 },
+ { "B1", 2064, 2920 },
+ { "B0", 2920, 4127 },
+
+ { "Letter", 612, 792 },
+ { "Legal", 612, 1008 },
+ { "Tabloid", 792, 1224 },
+ { "A", 612, 792 },
+ { "B", 792, 1224 },
+ { "C", 1224, 1584 },
+ { "D", 1584, 2448 },
+ { "E", 2448, 3168 },
+
+ { NULL, 0, 0 },
+};
+
+/* ---------------------------------------------------------------------- */
+/* path-drawing auxiliary functions */
+
+/* coordinate quantization */
+static inline point_t unit(dpoint_t p) {
+ point_t q;
+
+ q.x = (long)(floor(p.x+.5));
+ q.y = (long)(floor(p.y+.5));
+ return q;
+}
+
+static void xfig_point(FILE *fout, dpoint_t p, trans_t t) {
+ point_t q;
+
+ q = unit(trans(p, t));
+
+ fprintf(fout, "%ld %ld\n", q.x, q.y);
+}
+
+/* ---------------------------------------------------------------------- */
+/* functions for converting a path to a xfig */
+
+/* calculate number of xfig control points in this path */
+static int npoints(potrace_curve_t *curve, int m) {
+ int i;
+ int n=0;
+
+ for (i=0; i<m; i++) {
+ switch (curve->tag[i]) {
+ case POTRACE_CORNER:
+ n += 1;
+ break;
+ case POTRACE_CURVETO:
+ n += 2;
+ break;
+ }
+ }
+ return n;
+}
+
+/* do one path. */
+static void xfig_path(FILE *fout, potrace_curve_t *curve, trans_t t, int sign, int depth) {
+ int i;
+ dpoint_t *c;
+ int m = curve->n;
+
+ fprintf(fout, "3 1 0 0 0 %d %d 0 20 0.000 0 0 0 %d\n", sign=='+' ? 32 : 33, depth, npoints(curve, m));
+
+ for (i=0; i<m; i++) {
+ c = curve->c[i];
+ switch (curve->tag[i]) {
+ case POTRACE_CORNER:
+ xfig_point(fout, c[1], t);
+ break;
+ case POTRACE_CURVETO:
+ xfig_point(fout, c[0], t);
+ xfig_point(fout, c[1], t);
+ break;
+ }
+ }
+ for (i=0; i<m; i++) {
+ switch (curve->tag[i]) {
+ case POTRACE_CORNER:
+ fprintf(fout, "0\n");
+ break;
+ case POTRACE_CURVETO:
+ fprintf(fout, "1 1\n");
+ break;
+ }
+ }
+}
+
+/* render a whole tree */
+static void xfig_write_paths(FILE *fout, potrace_path_t *plist, trans_t t, int depth) {
+ potrace_path_t *p, *q;
+
+ for (p=plist; p; p=p->sibling) {
+ xfig_path(fout, &p->curve, t, p->sign, depth);
+ for (q=p->childlist; q; q=q->sibling) {
+ xfig_path(fout, &q->curve, t, q->sign, depth >= 1 ? depth-1 : 0);
+ }
+ for (q=p->childlist; q; q=q->sibling) {
+ xfig_write_paths(fout, q->childlist, t, depth >= 2 ? depth-2 : 0);
+ }
+ }
+}
+
+/* calculate the depth of a tree. Call with d=0. */
+static int xfig_get_depth(potrace_path_t *plist) {
+ potrace_path_t *p;
+ int max =0;
+ int d;
+
+ for (p=plist; p; p=p->sibling) {
+ d = xfig_get_depth(p->childlist);
+ if (d > max) {
+ max = d;
+ }
+ }
+ return max + 1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Backend. */
+
+/* public interface for XFIG */
+int page_xfig(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
+ trans_t t;
+ double origx = imginfo->trans.orig[0] + imginfo->lmar;
+ double origy = - imginfo->trans.orig[1] - imginfo->bmar + info.paperheight;
+ const char *formatname;
+ int best, penalty;
+ pageformat_t *f;
+ int i;
+ int x0, y0, x1, y1; /* in xfig's coordinates */
+ int depth;
+
+ t.orig[0] = 1200/72.0 * origx;
+ t.orig[1] = 1200/72.0 * origy;
+ t.x[0] = 1200/72.0 * imginfo->trans.x[0];
+ t.x[1] = -1200/72.0 * imginfo->trans.x[1];
+ t.y[0] = 1200/72.0 * imginfo->trans.y[0];
+ t.y[1] = -1200/72.0 * imginfo->trans.y[1];
+
+ x0 = (int)(1200/72.0 * (origx - imginfo->trans.orig[0]));
+ y0 = (int)(1200/72.0 * (origy + imginfo->trans.orig[1]));
+ x1 = x0 + (int)(1200/72.0 * imginfo->trans.bb[0]);
+ y1 = y0 - (int)(1200/72.0 * imginfo->trans.bb[1]);
+
+ best = -1;
+ formatname = "Letter";
+
+ /* find closest page format */
+ for (i=0; pageformat[i].name; i++) {
+ f = &pageformat[i];
+ if (f->w >= info.paperwidth-1 && f->h >= info.paperheight-1) {
+ penalty = f->w + f->h;
+ if (best == -1 || penalty < best) {
+ best = penalty;
+ formatname = f->name;
+ }
+ }
+ }
+
+ /* header */
+ fprintf(fout, "#FIG 3.2\n");
+ fprintf(fout, "#created by " POTRACE " " VERSION ", written by Peter Selinger 2001-2019\n");
+ fprintf(fout, "Portrait\n");
+ fprintf(fout, "Center\n");
+ fprintf(fout, "Inches\n");
+ fprintf(fout, "%s\n", formatname);
+ fprintf(fout, "100.0\n");
+ fprintf(fout, "Single\n");
+ fprintf(fout, "-2\n");
+ fprintf(fout, "1200 2\n"); /* 1200 pixels per inch */
+ fprintf(fout, "0 32 #%06x\n", info.color);
+ fprintf(fout, "0 33 #%06x\n", info.fillcolor);
+ fprintf(fout, "6 %d %d %d %d\n", x0-75, y1-35, x1+75, y0+35); /* bounding box */
+
+ /* determine depth of the tree */
+ depth = xfig_get_depth(plist);
+
+ /* figure out appropriate xfig starting depth. Note: xfig only has 1000 depths available */
+ if (depth <= 40) {
+ depth = 50;
+ } else if (depth < 990) {
+ depth += 10;
+ } else {
+ depth = 999;
+ }
+
+ /* write paths. Note: can never use "opticurve" with this backend -
+ it just does not approximate Bezier curves closely enough. */
+ xfig_write_paths(fout, plist, t, depth);
+
+ fprintf(fout, "-6\n"); /* end bounding box */
+
+ fflush(fout);
+
+ return 0;
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/backend_xfig.h b/Build/source/libs/potrace/potrace-src/src/backend_xfig.h
new file mode 100644
index 00000000000..c29de281481
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/backend_xfig.h
@@ -0,0 +1,15 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef BACKEND_XFIG_H
+#define BACKEND_XFIG_H
+
+#include "potracelib.h"
+#include "main.h"
+
+int page_xfig(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
+
+#endif /* BACKEND_XFIG_H */
+
diff --git a/Build/source/libs/potrace/potrace-src/src/bbox.c b/Build/source/libs/potrace/potrace-src/src/bbox.c
new file mode 100644
index 00000000000..5cc889192e4
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/bbox.c
@@ -0,0 +1,154 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* figure out the true bounding box of a vector image */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "bbox.h"
+#include "potracelib.h"
+#include "lists.h"
+
+/* ---------------------------------------------------------------------- */
+/* intervals */
+
+/* initialize the interval to [min, max] */
+static void interval(interval_t *i, double min, double max) {
+ i->min = min;
+ i->max = max;
+}
+
+/* initialize the interval to [x, x] */
+static inline void singleton(interval_t *i, double x) {
+ interval(i, x, x);
+}
+
+/* extend the interval to include the number x */
+static inline void extend(interval_t *i, double x) {
+ if (x < i->min) {
+ i->min = x;
+ } else if (x > i->max) {
+ i->max = x;
+ }
+}
+
+static inline int in_interval(interval_t *i, double x) {
+ return i->min <= x && x <= i->max;
+}
+
+/* ---------------------------------------------------------------------- */
+/* inner product */
+
+typedef potrace_dpoint_t dpoint_t;
+
+static double iprod(dpoint_t a, dpoint_t b) {
+ return a.x * b.x + a.y * b.y;
+}
+
+/* ---------------------------------------------------------------------- */
+/* linear Bezier segments */
+
+/* return a point on a 1-dimensional Bezier segment */
+static inline double bezier(double t, double x0, double x1, double x2, double x3) {
+ double s = 1-t;
+ return s*s*s*x0 + 3*(s*s*t)*x1 + 3*(t*t*s)*x2 + t*t*t*x3;
+}
+
+/* Extend the interval i to include the minimum and maximum of a
+ 1-dimensional Bezier segment given by control points x0..x3. For
+ efficiency, x0 in i is assumed as a precondition. */
+static void bezier_limits(double x0, double x1, double x2, double x3, interval_t *i) {
+ double a, b, c, d, r;
+ double t, x;
+
+ /* the min and max of a cubic curve segment are attained at one of
+ at most 4 critical points: the 2 endpoints and at most 2 local
+ extrema. We don't check the first endpoint, because all our
+ curves are cyclic so it's more efficient not to check endpoints
+ twice. */
+
+ /* endpoint */
+ extend(i, x3);
+
+ /* optimization: don't bother calculating extrema if all control
+ points are already in i */
+ if (in_interval(i, x1) && in_interval(i, x2)) {
+ return;
+ }
+
+ /* solve for extrema. at^2 + bt + c = 0 */
+ a = -3*x0 + 9*x1 - 9*x2 + 3*x3;
+ b = 6*x0 - 12*x1 + 6*x2;
+ c = -3*x0 + 3*x1;
+ d = b*b - 4*a*c;
+ if (d > 0) {
+ r = sqrt(d);
+ t = (-b-r)/(2*a);
+ if (t > 0 && t < 1) {
+ x = bezier(t, x0, x1, x2, x3);
+ extend(i, x);
+ }
+ t = (-b+r)/(2*a);
+ if (t > 0 && t < 1) {
+ x = bezier(t, x0, x1, x2, x3);
+ extend(i, x);
+ }
+ }
+ return;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Potrace segments, curves, and pathlists */
+
+/* extend the interval i to include the inner product <v | dir> for
+ all points v on the segment. Assume precondition a in i. */
+static inline void segment_limits(int tag, dpoint_t a, dpoint_t c[3], dpoint_t dir, interval_t *i) {
+ switch (tag) {
+ case POTRACE_CORNER:
+ extend(i, iprod(c[1], dir));
+ extend(i, iprod(c[2], dir));
+ break;
+ case POTRACE_CURVETO:
+ bezier_limits(iprod(a, dir), iprod(c[0], dir), iprod(c[1], dir), iprod(c[2], dir), i);
+ break;
+ }
+}
+
+/* extend the interval i to include <v | dir> for all points v on the
+ curve. */
+static void curve_limits(potrace_curve_t *curve, dpoint_t dir, interval_t *i) {
+ int k;
+ int n = curve->n;
+
+ segment_limits(curve->tag[0], curve->c[n-1][2], curve->c[0], dir, i);
+ for (k=1; k<n; k++) {
+ segment_limits(curve->tag[k], curve->c[k-1][2], curve->c[k], dir, i);
+ }
+}
+
+/* compute the interval i to be the smallest interval including all <v
+ | dir> for points in the pathlist. If the pathlist is empty, return
+ the singleton interval [0,0]. */
+void path_limits(potrace_path_t *path, dpoint_t dir, interval_t *i) {
+ potrace_path_t *p;
+
+ /* empty image? */
+ if (path == NULL) {
+ interval(i, 0, 0);
+ return;
+ }
+
+ /* initialize interval to a point on the first curve */
+ singleton(i, iprod(path->curve.c[0][2], dir));
+
+ /* iterate */
+ list_forall(p, path) {
+ curve_limits(&p->curve, dir, i);
+ }
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/bbox.h b/Build/source/libs/potrace/potrace-src/src/bbox.h
new file mode 100644
index 00000000000..739a5775010
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/bbox.h
@@ -0,0 +1,18 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+#ifndef BBOX_H
+#define BBOX_H
+
+#include "potracelib.h"
+
+/* an interval [min, max] */
+struct interval_s {
+ double min, max;
+};
+typedef struct interval_s interval_t;
+
+void path_limits(potrace_path_t *path, potrace_dpoint_t dir, interval_t *i);
+
+#endif /* BBOX_H */
diff --git a/Build/source/libs/potrace/potrace-src/src/bitmap.h b/Build/source/libs/potrace/potrace-src/src/bitmap.h
new file mode 100644
index 00000000000..c5685746896
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/bitmap.h
@@ -0,0 +1,228 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+#ifndef BITMAP_H
+#define BITMAP_H
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stddef.h>
+
+/* The bitmap type is defined in potracelib.h */
+#include "potracelib.h"
+
+/* The present file defines some convenient macros and static inline
+ functions for accessing bitmaps. Since they only produce inline
+ code, they can be conveniently shared by the library and frontends,
+ if desired */
+
+/* ---------------------------------------------------------------------- */
+/* some measurements */
+
+#define BM_WORDSIZE ((int)sizeof(potrace_word))
+#define BM_WORDBITS (8*BM_WORDSIZE)
+#define BM_HIBIT (((potrace_word)1)<<(BM_WORDBITS-1))
+#define BM_ALLBITS (~(potrace_word)0)
+
+/* macros for accessing pixel at index (x,y). U* macros omit the
+ bounds check. */
+
+#define bm_scanline(bm, y) ((bm)->map + (ptrdiff_t)(y)*(ptrdiff_t)(bm)->dy)
+#define bm_index(bm, x, y) (&bm_scanline(bm, y)[(x)/BM_WORDBITS])
+#define bm_mask(x) (BM_HIBIT >> ((x) & (BM_WORDBITS-1)))
+#define bm_range(x, a) ((int)(x) >= 0 && (int)(x) < (a))
+#define bm_safe(bm, x, y) (bm_range(x, (bm)->w) && bm_range(y, (bm)->h))
+#define BM_UGET(bm, x, y) ((*bm_index(bm, x, y) & bm_mask(x)) != 0)
+#define BM_USET(bm, x, y) (*bm_index(bm, x, y) |= bm_mask(x))
+#define BM_UCLR(bm, x, y) (*bm_index(bm, x, y) &= ~bm_mask(x))
+#define BM_UINV(bm, x, y) (*bm_index(bm, x, y) ^= bm_mask(x))
+#define BM_UPUT(bm, x, y, b) ((b) ? BM_USET(bm, x, y) : BM_UCLR(bm, x, y))
+#define BM_GET(bm, x, y) (bm_safe(bm, x, y) ? BM_UGET(bm, x, y) : 0)
+#define BM_SET(bm, x, y) (bm_safe(bm, x, y) ? BM_USET(bm, x, y) : 0)
+#define BM_CLR(bm, x, y) (bm_safe(bm, x, y) ? BM_UCLR(bm, x, y) : 0)
+#define BM_INV(bm, x, y) (bm_safe(bm, x, y) ? BM_UINV(bm, x, y) : 0)
+#define BM_PUT(bm, x, y, b) (bm_safe(bm, x, y) ? BM_UPUT(bm, x, y, b) : 0)
+
+/* calculate the size, in bytes, required for the data area of a
+ bitmap of the given dy and h. Assume h >= 0. Return -1 if the size
+ does not fit into the ptrdiff_t type. */
+static inline ptrdiff_t getsize(int dy, int h) {
+ ptrdiff_t size;
+
+ if (dy < 0) {
+ dy = -dy;
+ }
+
+ size = (ptrdiff_t)dy * (ptrdiff_t)h * (ptrdiff_t)BM_WORDSIZE;
+
+ /* check for overflow error */
+ if (size < 0 || (h != 0 && dy != 0 && size / h / dy != BM_WORDSIZE)) {
+ return -1;
+ }
+
+ return size;
+}
+
+/* return the size, in bytes, of the data area of the bitmap. Return
+ -1 if the size does not fit into the ptrdiff_t type; however, this
+ cannot happen if the bitmap is well-formed, i.e., if created with
+ bm_new or bm_dup. */
+static inline ptrdiff_t bm_size(const potrace_bitmap_t *bm) {
+ return getsize(bm->dy, bm->h);
+}
+
+/* calculate the base address of the bitmap data. Assume that the
+ bitmap is well-formed, i.e., its size fits into the ptrdiff_t type.
+ This is the case if created with bm_new or bm_dup. The base address
+ may differ from bm->map if dy is negative */
+static inline potrace_word *bm_base(const potrace_bitmap_t *bm) {
+ int dy = bm->dy;
+
+ if (dy >= 0 || bm->h == 0) {
+ return bm->map;
+ } else {
+ return bm_scanline(bm, bm->h - 1);
+ }
+}
+
+/* free the given bitmap. Leaves errno untouched. */
+static inline void bm_free(potrace_bitmap_t *bm) {
+ if (bm && bm->map) {
+ free(bm_base(bm));
+ }
+ free(bm);
+}
+
+/* return new bitmap initialized to 0. NULL with errno on error.
+ Assumes w, h >= 0. */
+static inline potrace_bitmap_t *bm_new(int w, int h) {
+ potrace_bitmap_t *bm;
+ int dy = w == 0 ? 0 : (w - 1) / BM_WORDBITS + 1;
+ ptrdiff_t size;
+
+ size = getsize(dy, h);
+ if (size < 0) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ if (size == 0) {
+ size = BM_WORDSIZE; /* make sure calloc() doesn't return NULL */
+ }
+
+ bm = (potrace_bitmap_t *) malloc(sizeof(potrace_bitmap_t));
+ if (!bm) {
+ return NULL;
+ }
+ bm->w = w;
+ bm->h = h;
+ bm->dy = dy;
+ bm->map = (potrace_word *) calloc(1, size);
+ if (!bm->map) {
+ free(bm);
+ return NULL;
+ }
+ return bm;
+}
+
+/* clear the given bitmap. Set all bits to c. Assumes a well-formed
+ bitmap. */
+static inline void bm_clear(potrace_bitmap_t *bm, int c) {
+ /* Note: if the bitmap was created with bm_new, then it is
+ guaranteed that size will fit into the ptrdiff_t type. */
+ ptrdiff_t size = bm_size(bm);
+ memset(bm_base(bm), c ? -1 : 0, size);
+}
+
+/* duplicate the given bitmap. Return NULL on error with errno
+ set. Assumes a well-formed bitmap. */
+static inline potrace_bitmap_t *bm_dup(const potrace_bitmap_t *bm) {
+ potrace_bitmap_t *bm1 = bm_new(bm->w, bm->h);
+ int y;
+
+ if (!bm1) {
+ return NULL;
+ }
+ for (y=0; y < bm->h; y++) {
+ memcpy(bm_scanline(bm1, y), bm_scanline(bm, y), (size_t)bm1->dy * (size_t)BM_WORDSIZE);
+ }
+ return bm1;
+}
+
+/* invert the given bitmap. */
+static inline void bm_invert(potrace_bitmap_t *bm) {
+ int dy = bm->dy;
+ int y;
+ int i;
+ potrace_word *p;
+
+ if (dy < 0) {
+ dy = -dy;
+ }
+
+ for (y=0; y < bm->h; y++) {
+ p = bm_scanline(bm, y);
+ for (i=0; i < dy; i++) {
+ p[i] ^= BM_ALLBITS;
+ }
+ }
+}
+
+/* turn the given bitmap upside down. This does not move the bitmap
+ data or change the bm_base() address. */
+static inline void bm_flip(potrace_bitmap_t *bm) {
+ int dy = bm->dy;
+
+ if (bm->h == 0 || bm->h == 1) {
+ return;
+ }
+
+ bm->map = bm_scanline(bm, bm->h - 1);
+ bm->dy = -dy;
+}
+
+/* resize the bitmap to the given new height. The bitmap data remains
+ bottom-aligned (truncated at the top) when dy >= 0 and top-aligned
+ (truncated at the bottom) when dy < 0. Return 0 on success, or 1 on
+ error with errno set. If the new height is <= the old one, no error
+ should occur. If the new height is larger, the additional bitmap
+ data is *not* initialized. */
+static inline int bm_resize(potrace_bitmap_t *bm, int h) {
+ int dy = bm->dy;
+ ptrdiff_t newsize;
+ potrace_word *newmap;
+
+ if (dy < 0) {
+ bm_flip(bm);
+ }
+
+ newsize = getsize(dy, h);
+ if (newsize < 0) {
+ errno = ENOMEM;
+ goto error;
+ }
+ if (newsize == 0) {
+ newsize = BM_WORDSIZE; /* make sure realloc() doesn't return NULL */
+ }
+
+ newmap = (potrace_word *)realloc(bm->map, newsize);
+ if (newmap == NULL) {
+ goto error;
+ }
+ bm->map = newmap;
+ bm->h = h;
+
+ if (dy < 0) {
+ bm_flip(bm);
+ }
+ return 0;
+
+ error:
+ if (dy < 0) {
+ bm_flip(bm);
+ }
+ return 1;
+}
+
+#endif /* BITMAP_H */
diff --git a/Build/source/libs/potrace/potrace-src/src/bitmap_io.c b/Build/source/libs/potrace/potrace-src/src/bitmap_io.c
new file mode 100644
index 00000000000..3e04c2b5e79
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/bitmap_io.c
@@ -0,0 +1,886 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+/* Routines for manipulating bitmaps, including reading pbm files. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include "bitmap.h"
+#include "bitops.h"
+#include "bitmap_io.h"
+
+#define INTBITS (8*sizeof(int))
+
+static int bm_readbody_bmp(FILE *f, double threshold, potrace_bitmap_t **bmp);
+static int bm_readbody_pnm(FILE *f, double threshold, potrace_bitmap_t **bmp, int magic);
+
+#define TRY(x) if (x) goto try_error
+#define TRY_EOF(x) if (x) goto eof
+#define TRY_STD(x) if (x) goto std_error
+
+/* ---------------------------------------------------------------------- */
+/* routines for reading pnm streams */
+
+/* read next character after whitespace and comments. Return EOF on
+ end of file or error. */
+static int fgetc_ws(FILE *f) {
+ int c;
+
+ while (1) {
+ c = fgetc(f);
+ if (c=='#') {
+ while (1) {
+ c = fgetc(f);
+ if (c=='\n' || c==EOF) {
+ break;
+ }
+ }
+ }
+ /* space, tab, line feed, carriage return, form-feed */
+ if (c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=12) {
+ return c;
+ }
+ }
+}
+
+/* skip whitespace and comments, then read a non-negative decimal
+ number from a stream. Return -1 on EOF. Tolerate other errors (skip
+ bad characters). Do not the read any characters following the
+ number (put next character back into the stream) */
+
+static int readnum(FILE *f) {
+ int c;
+ uint64_t acc;
+
+ /* skip whitespace and comments */
+ while (1) {
+ c = fgetc_ws(f);
+ if (c==EOF) {
+ return -1;
+ }
+ if (c>='0' && c<='9') {
+ break;
+ }
+ }
+
+ /* first digit is already in c */
+ acc = c-'0';
+ while (1) {
+ c = fgetc(f);
+ if (c==EOF) {
+ break;
+ }
+ if (c<'0' || c>'9') {
+ ungetc(c, f);
+ break;
+ }
+ acc *= 10;
+ acc += c-'0';
+ if (acc > 0x7fffffff) {
+ return -1;
+ }
+ }
+ return acc;
+}
+
+/* similar to readnum, but read only a single 0 or 1, and do not read
+ any characters after it. */
+
+static int readbit(FILE *f) {
+ int c;
+
+ /* skip whitespace and comments */
+ while (1) {
+ c = fgetc_ws(f);
+ if (c==EOF) {
+ return -1;
+ }
+ if (c>='0' && c<='1') {
+ break;
+ }
+ }
+
+ return c-'0';
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* read a PNM stream: P1-P6 format (see pnm(5)), or a BMP stream, and
+ convert the output to a bitmap. Return bitmap in *bmp. Return 0 on
+ success, -1 on error with errno set, -2 on bad file format (with
+ error message in bm_read_error), and 1 on premature end of file, -3
+ on empty file (including files which contain only whitespace and
+ comments), -4 if wrong magic number. If the return value is >=0,
+ *bmp is valid. */
+
+const char *bm_read_error = NULL;
+
+int bm_read(FILE *f, double threshold, potrace_bitmap_t **bmp) {
+ int magic[2];
+
+ /* read magic number. We ignore whitespace and comments before the
+ magic, for the benefit of concatenated files in P1-P3 format.
+ Multiple P1-P3 images in a single file are not formally allowed
+ by the PNM standard, but there is no harm in being lenient. */
+
+ magic[0] = fgetc_ws(f);
+ if (magic[0] == EOF) {
+ return -3;
+ }
+ magic[1] = fgetc(f);
+ if (magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6') {
+ return bm_readbody_pnm(f, threshold, bmp, magic[1]);
+ }
+ if (magic[0] == 'B' && magic[1] == 'M') {
+ return bm_readbody_bmp(f, threshold, bmp);
+ }
+ return -4;
+}
+
+/* ---------------------------------------------------------------------- */
+/* read PNM format */
+
+/* read PNM stream after magic number. Return values as for bm_read */
+static int bm_readbody_pnm(FILE *f, double threshold, potrace_bitmap_t **bmp, int magic) {
+ potrace_bitmap_t *bm;
+ int x, y, i, b, b1, sum;
+ int bpr; /* bytes per row (as opposed to 4*bm->c) */
+ int w, h, max;
+ int realheight; /* in case of incomplete file, keeps track of how
+ many scan lines actually contain data */
+
+ bm = NULL;
+
+ w = readnum(f);
+ if (w<0) {
+ goto format_error;
+ }
+
+ h = readnum(f);
+ if (h<0) {
+ goto format_error;
+ }
+
+ /* allocate bitmap */
+ bm = bm_new(w, h);
+ if (!bm) {
+ goto std_error;
+ }
+
+ realheight = 0;
+
+ switch (magic) {
+ default:
+ /* not reached */
+ goto format_error;
+
+ case '1':
+ /* read P1 format: PBM ascii */
+
+ for (y=0; y<h; y++) {
+ realheight = y+1;
+ for (x=0; x<w; x++) {
+ b = readbit(f);
+ if (b<0) {
+ goto eof;
+ }
+ BM_UPUT(bm, x, y, b);
+ }
+ }
+ break;
+
+ case '2':
+ /* read P2 format: PGM ascii */
+
+ max = readnum(f);
+ if (max<1) {
+ goto format_error;
+ }
+
+ for (y=0; y<h; y++) {
+ realheight = y+1;
+ for (x=0; x<w; x++) {
+ b = readnum(f);
+ if (b<0) {
+ goto eof;
+ }
+ BM_UPUT(bm, x, y, b > threshold * max ? 0 : 1);
+ }
+ }
+ break;
+
+ case '3':
+ /* read P3 format: PPM ascii */
+
+ max = readnum(f);
+ if (max<1) {
+ goto format_error;
+ }
+
+ for (y=0; y<h; y++) {
+ realheight = y+1;
+ for (x=0; x<w; x++) {
+ sum = 0;
+ for (i=0; i<3; i++) {
+ b = readnum(f);
+ if (b<0) {
+ goto eof;
+ }
+ sum += b;
+ }
+ BM_UPUT(bm, x, y, sum > 3 * threshold * max ? 0 : 1);
+ }
+ }
+ break;
+
+ case '4':
+ /* read P4 format: PBM raw */
+
+ b = fgetc(f); /* read single white-space character after height */
+ if (b==EOF) {
+ goto format_error;
+ }
+
+ bpr = (w+7)/8;
+
+ for (y=0; y<h; y++) {
+ realheight = y+1;
+ for (i=0; i<bpr; i++) {
+ b = fgetc(f);
+ if (b==EOF) {
+ goto eof;
+ }
+ *bm_index(bm, i*8, y) |= ((potrace_word)b) << (8*(BM_WORDSIZE-1-(i % BM_WORDSIZE)));
+ }
+ }
+ break;
+
+ case '5':
+ /* read P5 format: PGM raw */
+
+ max = readnum(f);
+ if (max<1) {
+ goto format_error;
+ }
+
+ b = fgetc(f); /* read single white-space character after max */
+ if (b==EOF) {
+ goto format_error;
+ }
+
+ for (y=0; y<h; y++) {
+ realheight = y+1;
+ for (x=0; x<w; x++) {
+ b = fgetc(f);
+ if (b==EOF)
+ goto eof;
+ if (max>=256) {
+ b <<= 8;
+ b1 = fgetc(f);
+ if (b1==EOF)
+ goto eof;
+ b |= b1;
+ }
+ BM_UPUT(bm, x, y, b > threshold * max ? 0 : 1);
+ }
+ }
+ break;
+
+ case '6':
+ /* read P6 format: PPM raw */
+
+ max = readnum(f);
+ if (max<1) {
+ goto format_error;
+ }
+
+ b = fgetc(f); /* read single white-space character after max */
+ if (b==EOF) {
+ goto format_error;
+ }
+
+ for (y=0; y<h; y++) {
+ realheight = y+1;
+ for (x=0; x<w; x++) {
+ sum = 0;
+ for (i=0; i<3; i++) {
+ b = fgetc(f);
+ if (b==EOF) {
+ goto eof;
+ }
+ if (max>=256) {
+ b <<= 8;
+ b1 = fgetc(f);
+ if (b1==EOF)
+ goto eof;
+ b |= b1;
+ }
+ sum += b;
+ }
+ BM_UPUT(bm, x, y, sum > 3 * threshold * max ? 0 : 1);
+ }
+ }
+ break;
+ }
+
+ bm_flip(bm);
+ *bmp = bm;
+ return 0;
+
+ eof:
+ TRY_STD(bm_resize(bm, realheight));
+ bm_flip(bm);
+ *bmp = bm;
+ return 1;
+
+ format_error:
+ bm_free(bm);
+ if (magic == '1' || magic == '4') {
+ bm_read_error = "invalid pbm file";
+ } else if (magic == '2' || magic == '5') {
+ bm_read_error = "invalid pgm file";
+ } else {
+ bm_read_error = "invalid ppm file";
+ }
+ return -2;
+
+ std_error:
+ bm_free(bm);
+ return -1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* read BMP format */
+
+struct bmp_info_s {
+ unsigned int FileSize;
+ unsigned int reserved;
+ unsigned int DataOffset;
+ unsigned int InfoSize;
+ unsigned int w; /* width */
+ unsigned int h; /* height */
+ unsigned int Planes;
+ unsigned int bits; /* bits per sample */
+ unsigned int comp; /* compression mode */
+ unsigned int ImageSize;
+ unsigned int XpixelsPerM;
+ unsigned int YpixelsPerM;
+ unsigned int ncolors; /* number of colors in palette */
+ unsigned int ColorsImportant;
+ unsigned int RedMask;
+ unsigned int GreenMask;
+ unsigned int BlueMask;
+ unsigned int AlphaMask;
+ unsigned int ctbits; /* sample size for color table */
+ int topdown; /* top-down mode? */
+};
+typedef struct bmp_info_s bmp_info_t;
+
+/* auxiliary */
+
+static int bmp_count = 0; /* counter for byte padding */
+static int bmp_pos = 0; /* counter from start of BMP data */
+
+/* read n-byte little-endian integer. Return 1 on EOF or error, else
+ 0. Assume n<=4. */
+static int bmp_readint(FILE *f, int n, unsigned int *p) {
+ int i;
+ unsigned int sum = 0;
+ int b;
+
+ for (i=0; i<n; i++) {
+ b = fgetc(f);
+ if (b==EOF) {
+ return 1;
+ }
+ sum += (unsigned)b << (8*i);
+ }
+ bmp_count += n;
+ bmp_pos += n;
+ *p = sum;
+ return 0;
+}
+
+/* reset padding boundary */
+static void bmp_pad_reset(void) {
+ bmp_count = 0;
+}
+
+/* read padding bytes to 4-byte boundary. Return 1 on EOF or error,
+ else 0. */
+static int bmp_pad(FILE *f) {
+ int c, i, b;
+
+ c = (-bmp_count) & 3;
+ for (i=0; i<c; i++) {
+ b = fgetc(f);
+ if (b==EOF) {
+ return 1;
+ }
+ }
+ bmp_pos += c;
+ bmp_count = 0;
+ return 0;
+}
+
+/* forward to the new file position. Return 1 on EOF or error, else 0 */
+static int bmp_forward(FILE *f, int pos) {
+ int b;
+
+ while (bmp_pos < pos) {
+ b = fgetc(f);
+ if (b==EOF) {
+ return 1;
+ }
+ bmp_pos++;
+ bmp_count++;
+ }
+ return 0;
+}
+
+/* safe colortable access */
+#define COLTABLE(c) ((c) < bmpinfo.ncolors ? coltable[(c)] : 0)
+
+/* read BMP stream after magic number. Return values as for bm_read.
+ We choose to be as permissive as possible, since there are many
+ programs out there which produce BMP. For instance, ppmtobmp can
+ produce codings with anywhere from 1-8 or 24 bits per sample,
+ although most specifications only allow 1,4,8,24,32. We can also
+ read both the old and new OS/2 BMP formats in addition to the
+ Windows BMP format. */
+static int bm_readbody_bmp(FILE *f, double threshold, potrace_bitmap_t **bmp) {
+ bmp_info_t bmpinfo;
+ int *coltable;
+ unsigned int b, c;
+ unsigned int i;
+ potrace_bitmap_t *bm;
+ int mask;
+ unsigned int x, y;
+ int col[2];
+ unsigned int bitbuf;
+ unsigned int n;
+ unsigned int redshift, greenshift, blueshift;
+ int col1[2];
+ int realheight; /* in case of incomplete file, keeps track of how
+ many scan lines actually contain data */
+
+ bm_read_error = NULL;
+ bm = NULL;
+ coltable = NULL;
+
+ bmp_pos = 2; /* set file position */
+
+ /* file header (minus magic number) */
+ TRY(bmp_readint(f, 4, &bmpinfo.FileSize));
+ TRY(bmp_readint(f, 4, &bmpinfo.reserved));
+ TRY(bmp_readint(f, 4, &bmpinfo.DataOffset));
+
+ /* info header */
+ TRY(bmp_readint(f, 4, &bmpinfo.InfoSize));
+ if (bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64
+ || bmpinfo.InfoSize == 108 || bmpinfo.InfoSize == 124) {
+ /* Windows or new OS/2 format */
+ bmpinfo.ctbits = 32; /* sample size in color table */
+ TRY(bmp_readint(f, 4, &bmpinfo.w));
+ TRY(bmp_readint(f, 4, &bmpinfo.h));
+ TRY(bmp_readint(f, 2, &bmpinfo.Planes));
+ TRY(bmp_readint(f, 2, &bmpinfo.bits));
+ TRY(bmp_readint(f, 4, &bmpinfo.comp));
+ TRY(bmp_readint(f, 4, &bmpinfo.ImageSize));
+ TRY(bmp_readint(f, 4, &bmpinfo.XpixelsPerM));
+ TRY(bmp_readint(f, 4, &bmpinfo.YpixelsPerM));
+ TRY(bmp_readint(f, 4, &bmpinfo.ncolors));
+ TRY(bmp_readint(f, 4, &bmpinfo.ColorsImportant));
+ if (bmpinfo.InfoSize >= 108) { /* V4 and V5 bitmaps */
+ TRY(bmp_readint(f, 4, &bmpinfo.RedMask));
+ TRY(bmp_readint(f, 4, &bmpinfo.GreenMask));
+ TRY(bmp_readint(f, 4, &bmpinfo.BlueMask));
+ TRY(bmp_readint(f, 4, &bmpinfo.AlphaMask));
+ }
+ if (bmpinfo.w > 0x7fffffff) {
+ goto format_error;
+ }
+ if (bmpinfo.h > 0x7fffffff) {
+ bmpinfo.h = (-bmpinfo.h) & 0xffffffff;
+ bmpinfo.topdown = 1;
+ } else {
+ bmpinfo.topdown = 0;
+ }
+ if (bmpinfo.h > 0x7fffffff) {
+ goto format_error;
+ }
+ } else if (bmpinfo.InfoSize == 12) {
+ /* old OS/2 format */
+ bmpinfo.ctbits = 24; /* sample size in color table */
+ TRY(bmp_readint(f, 2, &bmpinfo.w));
+ TRY(bmp_readint(f, 2, &bmpinfo.h));
+ TRY(bmp_readint(f, 2, &bmpinfo.Planes));
+ TRY(bmp_readint(f, 2, &bmpinfo.bits));
+ bmpinfo.comp = 0;
+ bmpinfo.ncolors = 0;
+ bmpinfo.topdown = 0;
+ } else {
+ goto format_error;
+ }
+
+ if (bmpinfo.comp == 3 && bmpinfo.InfoSize < 108) {
+ /* bitfield feature is only understood with V4 and V5 format */
+ goto format_error;
+ }
+
+ if (bmpinfo.comp > 3 || bmpinfo.bits > 32) {
+ goto format_error;
+ }
+
+ /* forward to color table (e.g., if bmpinfo.InfoSize == 64) */
+ TRY(bmp_forward(f, 14+bmpinfo.InfoSize));
+
+ if (bmpinfo.Planes != 1) {
+ bm_read_error = "cannot handle bmp planes";
+ goto format_error; /* can't handle planes */
+ }
+
+ if (bmpinfo.ncolors == 0 && bmpinfo.bits <= 8) {
+ bmpinfo.ncolors = 1 << bmpinfo.bits;
+ }
+
+ /* color table, present only if bmpinfo.bits <= 8. */
+ if (bmpinfo.bits <= 8) {
+ coltable = (int *) calloc(bmpinfo.ncolors, sizeof(int));
+ if (!coltable) {
+ goto std_error;
+ }
+ /* NOTE: since we are reading a bitmap, we can immediately convert
+ the color table entries to bits. */
+ for (i=0; i<bmpinfo.ncolors; i++) {
+ TRY(bmp_readint(f, bmpinfo.ctbits/8, &c));
+ c = ((c>>16) & 0xff) + ((c>>8) & 0xff) + (c & 0xff);
+ coltable[i] = (c > 3 * threshold * 255 ? 0 : 1);
+ if (i<2) {
+ col1[i] = c;
+ }
+ }
+ }
+
+ /* forward to data */
+ if (bmpinfo.InfoSize != 12) { /* not old OS/2 format */
+ TRY(bmp_forward(f, bmpinfo.DataOffset));
+ }
+
+ /* allocate bitmap */
+ bm = bm_new(bmpinfo.w, bmpinfo.h);
+ if (!bm) {
+ goto std_error;
+ }
+
+ realheight = 0;
+
+ switch (bmpinfo.bits + 0x100*bmpinfo.comp) {
+
+ default:
+ goto format_error;
+ break;
+
+ case 0x001: /* monochrome palette */
+ if (col1[0] < col1[1]) { /* make the darker color black */
+ mask = 0xff;
+ } else {
+ mask = 0;
+ }
+
+ /* raster data */
+ for (y=0; y<bmpinfo.h; y++) {
+ realheight = y+1;
+ bmp_pad_reset();
+ for (i=0; 8*i<bmpinfo.w; i++) {
+ TRY_EOF(bmp_readint(f, 1, &b));
+ b ^= mask;
+ *bm_index(bm, i*8, y) |= ((potrace_word)b) << (8*(BM_WORDSIZE-1-(i % BM_WORDSIZE)));
+ }
+ TRY(bmp_pad(f));
+ }
+ break;
+
+ case 0x002: /* 2-bit to 8-bit palettes */
+ case 0x003:
+ case 0x004:
+ case 0x005:
+ case 0x006:
+ case 0x007:
+ case 0x008:
+ for (y=0; y<bmpinfo.h; y++) {
+ realheight = y+1;
+ bmp_pad_reset();
+ bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
+ n = 0; /* number of bits currently in bitbuffer */
+ for (x=0; x<bmpinfo.w; x++) {
+ if (n < bmpinfo.bits) {
+ TRY_EOF(bmp_readint(f, 1, &b));
+ bitbuf |= b << (INTBITS - 8 - n);
+ n += 8;
+ }
+ b = bitbuf >> (INTBITS - bmpinfo.bits);
+ bitbuf <<= bmpinfo.bits;
+ n -= bmpinfo.bits;
+ BM_UPUT(bm, x, y, COLTABLE(b));
+ }
+ TRY(bmp_pad(f));
+ }
+ break;
+
+ case 0x010: /* 16-bit encoding */
+ /* can't do this format because it is not well-documented and I
+ don't have any samples */
+ bm_read_error = "cannot handle bmp 16-bit coding";
+ goto format_error;
+ break;
+
+ case 0x018: /* 24-bit encoding */
+ case 0x020: /* 32-bit encoding */
+ for (y=0; y<bmpinfo.h; y++) {
+ realheight = y+1;
+ bmp_pad_reset();
+ for (x=0; x<bmpinfo.w; x++) {
+ TRY_EOF(bmp_readint(f, bmpinfo.bits/8, &c));
+ c = ((c>>16) & 0xff) + ((c>>8) & 0xff) + (c & 0xff);
+ BM_UPUT(bm, x, y, c > 3 * threshold * 255 ? 0 : 1);
+ }
+ TRY(bmp_pad(f));
+ }
+ break;
+
+ case 0x320: /* 32-bit encoding with bitfields */
+ if (bmpinfo.RedMask == 0 || bmpinfo.GreenMask == 0 || bmpinfo.BlueMask == 0) {
+ goto format_error;
+ }
+
+ redshift = lobit(bmpinfo.RedMask);
+ greenshift = lobit(bmpinfo.GreenMask);
+ blueshift = lobit(bmpinfo.BlueMask);
+
+ for (y=0; y<bmpinfo.h; y++) {
+ realheight = y+1;
+ bmp_pad_reset();
+ for (x=0; x<bmpinfo.w; x++) {
+ TRY_EOF(bmp_readint(f, bmpinfo.bits/8, &c));
+ c = ((c & bmpinfo.RedMask) >> redshift) + ((c & bmpinfo.GreenMask) >> greenshift) + ((c & bmpinfo.BlueMask) >> blueshift);
+ BM_UPUT(bm, x, y, c > 3 * threshold * 255 ? 0 : 1);
+ }
+ TRY(bmp_pad(f));
+ }
+ break;
+
+ case 0x204: /* 4-bit runlength compressed encoding (RLE4) */
+ x = 0;
+ y = 0;
+
+ while (1) {
+ TRY_EOF(bmp_readint(f, 1, &b)); /* opcode */
+ TRY_EOF(bmp_readint(f, 1, &c)); /* argument */
+ if (b>0) {
+ /* repeat count */
+ col[0] = COLTABLE((c>>4) & 0xf);
+ col[1] = COLTABLE(c & 0xf);
+ for (i=0; i<b && x<bmpinfo.w; i++) {
+ if (x>=bmpinfo.w) {
+ x=0;
+ y++;
+ }
+ if (x>=bmpinfo.w || y>=bmpinfo.h) {
+ break;
+ }
+ realheight = y+1;
+ BM_PUT(bm, x, y, col[i&1]);
+ x++;
+ }
+ } else if (c == 0) {
+ /* end of line */
+ y++;
+ x = 0;
+ } else if (c == 1) {
+ /* end of bitmap */
+ break;
+ } else if (c == 2) {
+ /* "delta": skip pixels in x and y directions */
+ TRY_EOF(bmp_readint(f, 1, &b)); /* x offset */
+ TRY_EOF(bmp_readint(f, 1, &c)); /* y offset */
+ x += b;
+ y += c;
+ } else {
+ /* verbatim segment */
+ for (i=0; i<c; i++) {
+ if ((i&1)==0) {
+ TRY_EOF(bmp_readint(f, 1, &b));
+ }
+ if (x>=bmpinfo.w) {
+ x=0;
+ y++;
+ }
+ if (x>=bmpinfo.w || y>=bmpinfo.h) {
+ break;
+ }
+ realheight = y+1;
+ BM_PUT(bm, x, y, COLTABLE((b>>(4-4*(i&1))) & 0xf));
+ x++;
+ }
+ if ((c+1) & 2) {
+ /* pad to 16-bit boundary */
+ TRY_EOF(bmp_readint(f, 1, &b));
+ }
+ }
+ }
+ break;
+
+ case 0x108: /* 8-bit runlength compressed encoding (RLE8) */
+ x = 0;
+ y = 0;
+ while (1) {
+ TRY_EOF(bmp_readint(f, 1, &b)); /* opcode */
+ TRY_EOF(bmp_readint(f, 1, &c)); /* argument */
+ if (b>0) {
+ /* repeat count */
+ for (i=0; i<b; i++) {
+ if (x>=bmpinfo.w) {
+ x=0;
+ y++;
+ }
+ if (x>=bmpinfo.w || y>=bmpinfo.h) {
+ break;
+ }
+ realheight = y+1;
+ BM_PUT(bm, x, y, COLTABLE(c));
+ x++;
+ }
+ } else if (c == 0) {
+ /* end of line */
+ y++;
+ x = 0;
+ } else if (c == 1) {
+ /* end of bitmap */
+ break;
+ } else if (c == 2) {
+ /* "delta": skip pixels in x and y directions */
+ TRY_EOF(bmp_readint(f, 1, &b)); /* x offset */
+ TRY_EOF(bmp_readint(f, 1, &c)); /* y offset */
+ x += b;
+ y += c;
+ } else {
+ /* verbatim segment */
+ for (i=0; i<c; i++) {
+ TRY_EOF(bmp_readint(f, 1, &b));
+ if (x>=bmpinfo.w) {
+ x=0;
+ y++;
+ }
+ if (x>=bmpinfo.w || y>=bmpinfo.h) {
+ break;
+ }
+ realheight = y+1;
+ BM_PUT(bm, x, y, COLTABLE(b));
+ x++;
+ }
+ if (c & 1) {
+ /* pad input to 16-bit boundary */
+ TRY_EOF(bmp_readint(f, 1, &b));
+ }
+ }
+ }
+ break;
+
+ } /* switch */
+
+ /* skip any potential junk after the data section, but don't
+ complain in case EOF is encountered */
+ bmp_forward(f, bmpinfo.FileSize);
+
+ free(coltable);
+ if (bmpinfo.topdown) {
+ bm_flip(bm);
+ }
+ *bmp = bm;
+ return 0;
+
+ eof:
+ TRY_STD(bm_resize(bm, realheight));
+ free(coltable);
+ if (bmpinfo.topdown) {
+ bm_flip(bm);
+ }
+ *bmp = bm;
+ return 1;
+
+ format_error:
+ try_error:
+ free(coltable);
+ bm_free(bm);
+ if (!bm_read_error) {
+ bm_read_error = "invalid bmp file";
+ }
+ return -2;
+
+ std_error:
+ free(coltable);
+ bm_free(bm);
+ return -1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* output pbm format */
+
+void bm_writepbm(FILE *f, potrace_bitmap_t *bm) {
+ int w, h, bpr, y, i, c;
+
+ w = bm->w;
+ h = bm->h;
+
+ bpr = (w+7)/8;
+
+ fprintf(f, "P4\n%d %d\n", w, h);
+ for (y=h-1; y>=0; y--) {
+ for (i=0; i<bpr; i++) {
+ c = (*bm_index(bm, i*8, y) >> (8*(BM_WORDSIZE-1-(i % BM_WORDSIZE)))) & 0xff;
+ fputc(c, f);
+ }
+ }
+ return;
+}
+
+/* ---------------------------------------------------------------------- */
+/* output - for primitive debugging purposes only! */
+
+/* print bitmap to screen */
+int bm_print(FILE *f, potrace_bitmap_t *bm) {
+ int x, y;
+ int xx, yy;
+ int d;
+ int sw, sh;
+
+ sw = bm->w < 79 ? bm->w : 79;
+ sh = bm->w < 79 ? bm->h : bm->h*sw*44/(79*bm->w);
+
+ for (yy=sh-1; yy>=0; yy--) {
+ for (xx=0; xx<sw; xx++) {
+ d=0;
+ for (x=xx*bm->w/sw; x<(xx+1)*bm->w/sw; x++) {
+ for (y=yy*bm->h/sh; y<(yy+1)*bm->h/sh; y++) {
+ if (BM_GET(bm, x, y)) {
+ d++;
+ }
+ }
+ }
+ fputc(d ? '*' : ' ', f);
+ }
+ fputc('\n', f);
+ }
+ return 0;
+}
+
diff --git a/Build/source/libs/potrace/potrace-src/src/bitmap_io.h b/Build/source/libs/potrace/potrace-src/src/bitmap_io.h
new file mode 100644
index 00000000000..603dbff032b
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/bitmap_io.h
@@ -0,0 +1,23 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* bitmap input/output functions */
+
+#ifndef BITMAP_IO_H
+#define BITMAP_IO_H
+
+#include <stdio.h>
+#include "bitmap.h"
+
+/* Note that bitmaps are stored bottom to top, i.e., the first
+ scanline is the bottom-most one */
+
+extern const char *bm_read_error;
+
+int bm_read(FILE *f, double blacklevel, potrace_bitmap_t **bmp);
+void bm_writepbm(FILE *f, potrace_bitmap_t *bm);
+int bm_print(FILE *f, potrace_bitmap_t *bm);
+
+#endif /* BITMAP_IO_H */
+
diff --git a/Build/source/libs/potrace/potrace-src/src/bitops.h b/Build/source/libs/potrace/potrace-src/src/bitops.h
new file mode 100644
index 00000000000..96cf6cc8d47
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/bitops.h
@@ -0,0 +1,83 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+/* bits.h: this file defines some macros for bit manipulations. We
+ provide a generic implementation, as well as machine- and
+ compiler-specific fast implementations */
+
+/* lobit: return the position of the rightmost "1" bit of an int, or
+ 32 if none. hibit: return 1 + the position of the leftmost "1" bit
+ of an int, or 0 if none. Note: these functions work on 32-bit
+ integers. */
+
+#ifndef BITOPS_H
+#define BITOPS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* ---------------------------------------------------------------------- */
+/* machine specific macros */
+
+#if defined(HAVE_I386)
+
+static inline unsigned int lobit(unsigned int x) {
+ unsigned int res;
+ asm ("bsf %1,%0\n\t"
+ "jnz 0f\n\t"
+ "movl $32,%0\n"
+ "0:"
+ : "=r" (res)
+ : "r" (x)
+ : "cc");
+ return res;
+}
+
+static inline unsigned int hibit(unsigned int x) {
+ unsigned int res;
+
+ asm ("bsr %1,%0\n\t"
+ "jnz 0f\n\t"
+ "movl $-1,%0\n"
+ "0:"
+ : "=r" (res)
+ : "r" (x)
+ : "cc");
+ return res+1;
+}
+
+/* ---------------------------------------------------------------------- */
+#else /* generic macros */
+
+static inline unsigned int lobit(unsigned int x) {
+ unsigned int res = 32;
+ while (x & 0xffffff) {
+ x <<= 8;
+ res -= 8;
+ }
+ while (x) {
+ x <<= 1;
+ res -= 1;
+ }
+ return res;
+}
+
+static inline unsigned int hibit(unsigned int x) {
+ unsigned int res = 0;
+ while (x > 0xff) {
+ x >>= 8;
+ res += 8;
+ }
+ while (x) {
+ x >>= 1;
+ res += 1;
+ }
+ return res;
+}
+
+#endif
+
+#endif /* BITOPS_H */
diff --git a/Build/source/libs/potrace/potrace-src/src/curve.c b/Build/source/libs/potrace/potrace-src/src/curve.c
new file mode 100644
index 00000000000..81e02bb7d2a
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/curve.c
@@ -0,0 +1,112 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* private part of the path and curve data structures */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "potracelib.h"
+#include "lists.h"
+#include "curve.h"
+
+#define SAFE_CALLOC(var, n, typ) \
+ if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error
+
+/* ---------------------------------------------------------------------- */
+/* allocate and free path objects */
+
+path_t *path_new(void) {
+ path_t *p = NULL;
+ privpath_t *priv = NULL;
+
+ SAFE_CALLOC(p, 1, path_t);
+ memset(p, 0, sizeof(path_t));
+ SAFE_CALLOC(priv, 1, privpath_t);
+ memset(priv, 0, sizeof(privpath_t));
+ p->priv = priv;
+ return p;
+
+ calloc_error:
+ free(p);
+ free(priv);
+ return NULL;
+}
+
+/* free the members of the given curve structure. Leave errno unchanged. */
+static void privcurve_free_members(privcurve_t *curve) {
+ free(curve->tag);
+ free(curve->c);
+ free(curve->vertex);
+ free(curve->alpha);
+ free(curve->alpha0);
+ free(curve->beta);
+}
+
+/* free a path. Leave errno untouched. */
+void path_free(path_t *p) {
+ if (p) {
+ if (p->priv) {
+ free(p->priv->pt);
+ free(p->priv->lon);
+ free(p->priv->sums);
+ free(p->priv->po);
+ privcurve_free_members(&p->priv->curve);
+ privcurve_free_members(&p->priv->ocurve);
+ }
+ free(p->priv);
+ /* do not free p->fcurve ! */
+ }
+ free(p);
+}
+
+/* free a pathlist, leaving errno untouched. */
+void pathlist_free(path_t *plist) {
+ path_t *p;
+
+ list_forall_unlink(p, plist) {
+ path_free(p);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* initialize and finalize curve structures */
+
+typedef dpoint_t dpoint3_t[3];
+
+/* initialize the members of the given curve structure to size m.
+ Return 0 on success, 1 on error with errno set. */
+int privcurve_init(privcurve_t *curve, int n) {
+ memset(curve, 0, sizeof(privcurve_t));
+ curve->n = n;
+ SAFE_CALLOC(curve->tag, n, int);
+ SAFE_CALLOC(curve->c, n, dpoint3_t);
+ SAFE_CALLOC(curve->vertex, n, dpoint_t);
+ SAFE_CALLOC(curve->alpha, n, double);
+ SAFE_CALLOC(curve->alpha0, n, double);
+ SAFE_CALLOC(curve->beta, n, double);
+ return 0;
+
+ calloc_error:
+ free(curve->tag);
+ free(curve->c);
+ free(curve->vertex);
+ free(curve->alpha);
+ free(curve->alpha0);
+ free(curve->beta);
+ return 1;
+}
+
+/* copy private to public curve structure */
+void privcurve_to_curve(privcurve_t *pc, potrace_curve_t *c) {
+ c->n = pc->n;
+ c->tag = pc->tag;
+ c->c = pc->c;
+}
+
diff --git a/Build/source/libs/potrace/potrace-src/src/curve.h b/Build/source/libs/potrace/potrace-src/src/curve.h
new file mode 100644
index 00000000000..fa18a93d216
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/curve.h
@@ -0,0 +1,77 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+#ifndef CURVE_H
+#define CURVE_H
+
+#include "auxiliary.h"
+
+/* vertex is c[1] for tag=POTRACE_CORNER, and the intersection of
+ .c[-1][2]..c[0] and c[1]..c[2] for tag=POTRACE_CURVETO. alpha is only
+ defined for tag=POTRACE_CURVETO and is the alpha parameter of the curve:
+ .c[-1][2]..c[0] = alpha*(.c[-1][2]..vertex), and
+ c[2]..c[1] = alpha*(c[2]..vertex).
+ Beta is so that (.beta[i])[.vertex[i],.vertex[i+1]] = .c[i][2].
+*/
+
+struct privcurve_s {
+ int n; /* number of segments */
+ int *tag; /* tag[n]: POTRACE_CORNER or POTRACE_CURVETO */
+ dpoint_t (*c)[3]; /* c[n][i]: control points.
+ c[n][0] is unused for tag[n]=POTRACE_CORNER */
+ /* the remainder of this structure is special to privcurve, and is
+ used in EPS debug output and special EPS "short coding". These
+ fields are valid only if "alphacurve" is set. */
+ int alphacurve; /* have the following fields been initialized? */
+ dpoint_t *vertex; /* for POTRACE_CORNER, this equals c[1] */
+ double *alpha; /* only for POTRACE_CURVETO */
+ double *alpha0; /* "uncropped" alpha parameter - for debug output only */
+ double *beta;
+};
+typedef struct privcurve_s privcurve_t;
+
+struct sums_s {
+ double x;
+ double y;
+ double x2;
+ double xy;
+ double y2;
+};
+typedef struct sums_s sums_t;
+
+/* the path structure is filled in with information about a given path
+ as it is accumulated and passed through the different stages of the
+ Potrace algorithm. Backends only need to read the fcurve and fm
+ fields of this data structure, but debugging backends may read
+ other fields. */
+struct potrace_privpath_s {
+ int len;
+ point_t *pt; /* pt[len]: path as extracted from bitmap */
+ int *lon; /* lon[len]: (i,lon[i]) = longest straight line from i */
+
+ int x0, y0; /* origin for sums */
+ sums_t *sums; /* sums[len+1]: cache for fast summing */
+
+ int m; /* length of optimal polygon */
+ int *po; /* po[m]: optimal polygon */
+
+ privcurve_t curve; /* curve[m]: array of curve elements */
+ privcurve_t ocurve; /* ocurve[om]: array of curve elements */
+ privcurve_t *fcurve; /* final curve: this points to either curve or
+ ocurve. Do not free this separately. */
+};
+typedef struct potrace_privpath_s potrace_privpath_t;
+
+/* shorter names */
+typedef potrace_privpath_t privpath_t;
+typedef potrace_path_t path_t;
+
+path_t *path_new(void);
+void path_free(path_t *p);
+void pathlist_free(path_t *plist);
+int privcurve_init(privcurve_t *curve, int n);
+void privcurve_to_curve(privcurve_t *pc, potrace_curve_t *c);
+
+#endif /* CURVE_H */
+
diff --git a/Build/source/libs/potrace/potrace-src/src/decompose.c b/Build/source/libs/potrace/potrace-src/src/decompose.c
new file mode 100644
index 00000000000..ae72850efb2
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/decompose.c
@@ -0,0 +1,521 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include "potracelib.h"
+#include "curve.h"
+#include "lists.h"
+#include "bitmap.h"
+#include "decompose.h"
+#include "progress.h"
+
+/* ---------------------------------------------------------------------- */
+/* deterministically and efficiently hash (x,y) into a pseudo-random bit */
+
+static inline int detrand(int x, int y) {
+ unsigned int z;
+ static const unsigned char t[256] = {
+ /* non-linear sequence: constant term of inverse in GF(8),
+ mod x^8+x^4+x^3+x+1 */
+ 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1,
+ 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0,
+ 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
+ 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
+ 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0,
+ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1,
+ 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
+ 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
+ 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ };
+
+ /* 0x04b3e375 and 0x05a8ef93 are chosen to contain every possible
+ 5-bit sequence */
+ z = ((0x04b3e375 * x) ^ y) * 0x05a8ef93;
+ z = t[z & 0xff] ^ t[(z>>8) & 0xff] ^ t[(z>>16) & 0xff] ^ t[(z>>24) & 0xff];
+ return z;
+}
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary bitmap manipulations */
+
+/* set the excess padding to 0 */
+static void bm_clearexcess(potrace_bitmap_t *bm) {
+ potrace_word mask;
+ int y;
+
+ if (bm->w % BM_WORDBITS != 0) {
+ mask = BM_ALLBITS << (BM_WORDBITS - (bm->w % BM_WORDBITS));
+ for (y=0; y<bm->h; y++) {
+ *bm_index(bm, bm->w, y) &= mask;
+ }
+ }
+}
+
+struct bbox_s {
+ int x0, x1, y0, y1; /* bounding box */
+};
+typedef struct bbox_s bbox_t;
+
+/* clear the bm, assuming the bounding box is set correctly (faster
+ than clearing the whole bitmap) */
+static void clear_bm_with_bbox(potrace_bitmap_t *bm, bbox_t *bbox) {
+ int imin = (bbox->x0 / BM_WORDBITS);
+ int imax = ((bbox->x1 + BM_WORDBITS-1) / BM_WORDBITS);
+ int i, y;
+
+ for (y=bbox->y0; y<bbox->y1; y++) {
+ for (i=imin; i<imax; i++) {
+ bm_scanline(bm, y)[i] = 0;
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary functions */
+
+/* return the "majority" value of bitmap bm at intersection (x,y). We
+ assume that the bitmap is balanced at "radius" 1. */
+static int majority(potrace_bitmap_t *bm, int x, int y) {
+ int i, a, ct;
+
+ for (i=2; i<5; i++) { /* check at "radius" i */
+ ct = 0;
+ for (a=-i+1; a<=i-1; a++) {
+ ct += BM_GET(bm, x+a, y+i-1) ? 1 : -1;
+ ct += BM_GET(bm, x+i-1, y+a-1) ? 1 : -1;
+ ct += BM_GET(bm, x+a-1, y-i) ? 1 : -1;
+ ct += BM_GET(bm, x-i, y+a) ? 1 : -1;
+ }
+ if (ct>0) {
+ return 1;
+ } else if (ct<0) {
+ return 0;
+ }
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* decompose image into paths */
+
+/* efficiently invert bits [x,infty) and [xa,infty) in line y. Here xa
+ must be a multiple of BM_WORDBITS. */
+static void xor_to_ref(potrace_bitmap_t *bm, int x, int y, int xa) {
+ int xhi = x & -BM_WORDBITS;
+ int xlo = x & (BM_WORDBITS-1); /* = x % BM_WORDBITS */
+ int i;
+
+ if (xhi<xa) {
+ for (i = xhi; i < xa; i+=BM_WORDBITS) {
+ *bm_index(bm, i, y) ^= BM_ALLBITS;
+ }
+ } else {
+ for (i = xa; i < xhi; i+=BM_WORDBITS) {
+ *bm_index(bm, i, y) ^= BM_ALLBITS;
+ }
+ }
+ /* note: the following "if" is needed because x86 treats a<<b as
+ a<<(b&31). I spent hours looking for this bug. */
+ if (xlo) {
+ *bm_index(bm, xhi, y) ^= (BM_ALLBITS << (BM_WORDBITS - xlo));
+ }
+}
+
+/* a path is represented as an array of points, which are thought to
+ lie on the corners of pixels (not on their centers). The path point
+ (x,y) is the lower left corner of the pixel (x,y). Paths are
+ represented by the len/pt components of a path_t object (which
+ also stores other information about the path) */
+
+/* xor the given pixmap with the interior of the given path. Note: the
+ path must be within the dimensions of the pixmap. */
+static void xor_path(potrace_bitmap_t *bm, path_t *p) {
+ int xa, x, y, k, y1;
+
+ if (p->priv->len <= 0) { /* a path of length 0 is silly, but legal */
+ return;
+ }
+
+ y1 = p->priv->pt[p->priv->len-1].y;
+
+ xa = p->priv->pt[0].x & -BM_WORDBITS;
+ for (k=0; k<p->priv->len; k++) {
+ x = p->priv->pt[k].x;
+ y = p->priv->pt[k].y;
+
+ if (y != y1) {
+ /* efficiently invert the rectangle [x,xa] x [y,y1] */
+ xor_to_ref(bm, x, min(y,y1), xa);
+ y1 = y;
+ }
+ }
+}
+
+/* Find the bounding box of a given path. Path is assumed to be of
+ non-zero length. */
+static void setbbox_path(bbox_t *bbox, path_t *p) {
+ int x, y;
+ int k;
+
+ bbox->y0 = INT_MAX;
+ bbox->y1 = 0;
+ bbox->x0 = INT_MAX;
+ bbox->x1 = 0;
+
+ for (k=0; k<p->priv->len; k++) {
+ x = p->priv->pt[k].x;
+ y = p->priv->pt[k].y;
+
+ if (x < bbox->x0) {
+ bbox->x0 = x;
+ }
+ if (x > bbox->x1) {
+ bbox->x1 = x;
+ }
+ if (y < bbox->y0) {
+ bbox->y0 = y;
+ }
+ if (y > bbox->y1) {
+ bbox->y1 = y;
+ }
+ }
+}
+
+/* compute a path in the given pixmap, separating black from white.
+ Start path at the point (x0,x1), which must be an upper left corner
+ of the path. Also compute the area enclosed by the path. Return a
+ new path_t object, or NULL on error (note that a legitimate path
+ cannot have length 0). Sign is required for correct interpretation
+ of turnpolicies. */
+static path_t *findpath(potrace_bitmap_t *bm, int x0, int y0, int sign, int turnpolicy) {
+ int x, y, dirx, diry, len, size;
+ uint64_t area;
+ int c, d, tmp;
+ point_t *pt, *pt1;
+ path_t *p = NULL;
+
+ x = x0;
+ y = y0;
+ dirx = 0;
+ diry = -1;
+
+ len = size = 0;
+ pt = NULL;
+ area = 0;
+
+ while (1) {
+ /* add point to path */
+ if (len>=size) {
+ size += 100;
+ size = (int)(1.3 * size);
+ pt1 = (point_t *)realloc(pt, size * sizeof(point_t));
+ if (!pt1) {
+ goto error;
+ }
+ pt = pt1;
+ }
+ pt[len].x = x;
+ pt[len].y = y;
+ len++;
+
+ /* move to next point */
+ x += dirx;
+ y += diry;
+ area += x*diry;
+
+ /* path complete? */
+ if (x==x0 && y==y0) {
+ break;
+ }
+
+ /* determine next direction */
+ c = BM_GET(bm, x + (dirx+diry-1)/2, y + (diry-dirx-1)/2);
+ d = BM_GET(bm, x + (dirx-diry-1)/2, y + (diry+dirx-1)/2);
+
+ if (c && !d) { /* ambiguous turn */
+ if (turnpolicy == POTRACE_TURNPOLICY_RIGHT
+ || (turnpolicy == POTRACE_TURNPOLICY_BLACK && sign == '+')
+ || (turnpolicy == POTRACE_TURNPOLICY_WHITE && sign == '-')
+ || (turnpolicy == POTRACE_TURNPOLICY_RANDOM && detrand(x,y))
+ || (turnpolicy == POTRACE_TURNPOLICY_MAJORITY && majority(bm, x, y))
+ || (turnpolicy == POTRACE_TURNPOLICY_MINORITY && !majority(bm, x, y))) {
+ tmp = dirx; /* right turn */
+ dirx = diry;
+ diry = -tmp;
+ } else {
+ tmp = dirx; /* left turn */
+ dirx = -diry;
+ diry = tmp;
+ }
+ } else if (c) { /* right turn */
+ tmp = dirx;
+ dirx = diry;
+ diry = -tmp;
+ } else if (!d) { /* left turn */
+ tmp = dirx;
+ dirx = -diry;
+ diry = tmp;
+ }
+ } /* while this path */
+
+ /* allocate new path object */
+ p = path_new();
+ if (!p) {
+ goto error;
+ }
+
+ p->priv->pt = pt;
+ p->priv->len = len;
+ p->area = area <= INT_MAX ? area : INT_MAX; /* avoid overflow */
+ p->sign = sign;
+
+ return p;
+
+ error:
+ free(pt);
+ return NULL;
+}
+
+/* Give a tree structure to the given path list, based on "insideness"
+ testing. I.e., path A is considered "below" path B if it is inside
+ path B. The input pathlist is assumed to be ordered so that "outer"
+ paths occur before "inner" paths. The tree structure is stored in
+ the "childlist" and "sibling" components of the path_t
+ structure. The linked list structure is also changed so that
+ negative path components are listed immediately after their
+ positive parent. Note: some backends may ignore the tree
+ structure, others may use it e.g. to group path components. We
+ assume that in the input, point 0 of each path is an "upper left"
+ corner of the path, as returned by bm_to_pathlist. This makes it
+ easy to find an "interior" point. The bm argument should be a
+ bitmap of the correct size (large enough to hold all the paths),
+ and will be used as scratch space. Return 0 on success or -1 on
+ error with errno set. */
+
+static void pathlist_to_tree(path_t *plist, potrace_bitmap_t *bm) {
+ path_t *p, *p1;
+ path_t *heap, *heap1;
+ path_t *cur;
+ path_t *head;
+ path_t **plist_hook; /* for fast appending to linked list */
+ path_t **hook_in, **hook_out; /* for fast appending to linked list */
+ bbox_t bbox;
+
+ bm_clear(bm, 0);
+
+ /* save original "next" pointers */
+ list_forall(p, plist) {
+ p->sibling = p->next;
+ p->childlist = NULL;
+ }
+
+ heap = plist;
+
+ /* the heap holds a list of lists of paths. Use "childlist" field
+ for outer list, "next" field for inner list. Each of the sublists
+ is to be turned into a tree. This code is messy, but it is
+ actually fast. Each path is rendered exactly once. We use the
+ heap to get a tail recursive algorithm: the heap holds a list of
+ pathlists which still need to be transformed. */
+
+ while (heap) {
+ /* unlink first sublist */
+ cur = heap;
+ heap = heap->childlist;
+ cur->childlist = NULL;
+
+ /* unlink first path */
+ head = cur;
+ cur = cur->next;
+ head->next = NULL;
+
+ /* render path */
+ xor_path(bm, head);
+ setbbox_path(&bbox, head);
+
+ /* now do insideness test for each element of cur; append it to
+ head->childlist if it's inside head, else append it to
+ head->next. */
+ hook_in=&head->childlist;
+ hook_out=&head->next;
+ list_forall_unlink(p, cur) {
+ if (p->priv->pt[0].y <= bbox.y0) {
+ list_insert_beforehook(p, hook_out);
+ /* append the remainder of the list to hook_out */
+ *hook_out = cur;
+ break;
+ }
+ if (BM_GET(bm, p->priv->pt[0].x, p->priv->pt[0].y-1)) {
+ list_insert_beforehook(p, hook_in);
+ } else {
+ list_insert_beforehook(p, hook_out);
+ }
+ }
+
+ /* clear bm */
+ clear_bm_with_bbox(bm, &bbox);
+
+ /* now schedule head->childlist and head->next for further
+ processing */
+ if (head->next) {
+ head->next->childlist = heap;
+ heap = head->next;
+ }
+ if (head->childlist) {
+ head->childlist->childlist = heap;
+ heap = head->childlist;
+ }
+ }
+
+ /* copy sibling structure from "next" to "sibling" component */
+ p = plist;
+ while (p) {
+ p1 = p->sibling;
+ p->sibling = p->next;
+ p = p1;
+ }
+
+ /* reconstruct a new linked list ("next") structure from tree
+ ("childlist", "sibling") structure. This code is slightly messy,
+ because we use a heap to make it tail recursive: the heap
+ contains a list of childlists which still need to be
+ processed. */
+ heap = plist;
+ if (heap) {
+ heap->next = NULL; /* heap is a linked list of childlists */
+ }
+ plist = NULL;
+ plist_hook = &plist;
+ while (heap) {
+ heap1 = heap->next;
+ for (p=heap; p; p=p->sibling) {
+ /* p is a positive path */
+ /* append to linked list */
+ list_insert_beforehook(p, plist_hook);
+
+ /* go through its children */
+ for (p1=p->childlist; p1; p1=p1->sibling) {
+ /* append to linked list */
+ list_insert_beforehook(p1, plist_hook);
+ /* append its childlist to heap, if non-empty */
+ if (p1->childlist) {
+ list_append(path_t, heap1, p1->childlist);
+ }
+ }
+ }
+ heap = heap1;
+ }
+
+ return;
+}
+
+/* find the next set pixel in a row <= y. Pixels are searched first
+ left-to-right, then top-down. In other words, (x,y)<(x',y') if y>y'
+ or y=y' and x<x'. If found, return 0 and store pixel in
+ (*xp,*yp). Else return 1. Note that this function assumes that
+ excess bytes have been cleared with bm_clearexcess. */
+static int findnext(potrace_bitmap_t *bm, int *xp, int *yp) {
+ int x;
+ int y;
+ int x0;
+
+ x0 = (*xp) & ~(BM_WORDBITS-1);
+
+ for (y=*yp; y>=0; y--) {
+ for (x=x0; x<bm->w && x>=0; x+=(unsigned)BM_WORDBITS) {
+ if (*bm_index(bm, x, y)) {
+ while (!BM_GET(bm, x, y)) {
+ x++;
+ }
+ /* found */
+ *xp = x;
+ *yp = y;
+ return 0;
+ }
+ }
+ x0 = 0;
+ }
+ /* not found */
+ return 1;
+}
+
+/* Decompose the given bitmap into paths. Returns a linked list of
+ path_t objects with the fields len, pt, area, sign filled
+ in. Returns 0 on success with plistp set, or -1 on error with errno
+ set. */
+
+int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param, progress_t *progress) {
+ int x;
+ int y;
+ path_t *p;
+ path_t *plist = NULL; /* linked list of path objects */
+ path_t **plist_hook = &plist; /* used to speed up appending to linked list */
+ potrace_bitmap_t *bm1 = NULL;
+ int sign;
+
+ bm1 = bm_dup(bm);
+ if (!bm1) {
+ goto error;
+ }
+
+ /* be sure the byte padding on the right is set to 0, as the fast
+ pixel search below relies on it */
+ bm_clearexcess(bm1);
+
+ /* iterate through components */
+ x = 0;
+ y = bm1->h - 1;
+ while (findnext(bm1, &x, &y) == 0) {
+ /* calculate the sign by looking at the original */
+ sign = BM_GET(bm, x, y) ? '+' : '-';
+
+ /* calculate the path */
+ p = findpath(bm1, x, y+1, sign, param->turnpolicy);
+ if (p==NULL) {
+ goto error;
+ }
+
+ /* update buffered image */
+ xor_path(bm1, p);
+
+ /* if it's a turd, eliminate it, else append it to the list */
+ if (p->area <= param->turdsize) {
+ path_free(p);
+ } else {
+ list_insert_beforehook(p, plist_hook);
+ }
+
+ if (bm1->h > 0) { /* to be sure */
+ progress_update(1-y/(double)bm1->h, progress);
+ }
+ }
+
+ pathlist_to_tree(plist, bm1);
+ bm_free(bm1);
+ *plistp = plist;
+
+ progress_update(1.0, progress);
+
+ return 0;
+
+ error:
+ bm_free(bm1);
+ list_forall_unlink(p, plist) {
+ path_free(p);
+ }
+ return -1;
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/decompose.h b/Build/source/libs/potrace/potrace-src/src/decompose.h
new file mode 100644
index 00000000000..584b383ef90
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/decompose.h
@@ -0,0 +1,16 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef DECOMPOSE_H
+#define DECOMPOSE_H
+
+#include "potracelib.h"
+#include "progress.h"
+#include "curve.h"
+
+int bm_to_pathlist(const potrace_bitmap_t *bm, path_t **plistp, const potrace_param_t *param, progress_t *progress);
+
+#endif /* DECOMPOSE_H */
+
diff --git a/Build/source/libs/potrace/potrace-src/src/flate.c b/Build/source/libs/potrace/potrace-src/src/flate.c
new file mode 100644
index 00000000000..0df9759569f
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/flate.c
@@ -0,0 +1,380 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+/* the PostScript compression module of Potrace. The basic interface
+ is through the *_xship function, which processes a byte array and
+ outputs it in compressed or verbatim form, depending on whether
+ filter is 1 or 0. To flush the output, simply call with the empty
+ string and filter=0. filter=2 is used to output encoded text but
+ without the PostScript header to turn on the encoding. Each
+ function has variants for shipping a single character, a
+ null-terminated string, or a byte array. */
+
+/* different compression algorithms are available. There is
+ dummy_xship, which is just the identity, and flate_xship, which
+ uses zlib compression. Also, lzw_xship provides LZW compression
+ from the file lzw.c/h. a85_xship provides a85-encoding without
+ compression. Each function returns the actual number of characters
+ written. */
+
+/* note: the functions provided here have global state and are not
+ reentrant */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#ifdef HAVE_ZLIB
+#include <zlib.h>
+#endif
+
+#include "flate.h"
+#include "lzw.h"
+
+#define OUTSIZE 1000
+
+static int a85init(FILE *f);
+static int a85finish(FILE *f);
+static int a85write(FILE *f, const char *buf, int n);
+static int a85out(FILE *f, int n);
+static int a85spool(FILE *f, char c);
+
+/* ---------------------------------------------------------------------- */
+/* dummy interface: no encoding */
+
+int dummy_xship(FILE *f, int filter, const char *s, int len) {
+ fwrite(s, 1, len, f);
+ return len;
+}
+
+/* ---------------------------------------------------------------------- */
+/* flate interface: zlib (=postscript level 3) compression and a85 */
+
+#ifdef HAVE_ZLIB
+
+int pdf_xship(FILE *f, int filter, const char *s, int len) {
+ static int fstate = 0;
+ static z_stream c_stream;
+ char outbuf[OUTSIZE];
+ int err;
+ int n=0;
+
+ if (filter && !fstate) {
+ /* switch on filtering */
+ c_stream.zalloc = Z_NULL;
+ c_stream.zfree = Z_NULL;
+ c_stream.opaque = Z_NULL;
+ err = deflateInit(&c_stream, 9);
+ if (err != Z_OK) {
+ fprintf(stderr, "deflateInit: %s (%d)\n", c_stream.msg, err);
+ exit(2);
+ }
+ c_stream.avail_in = 0;
+ fstate = 1;
+ } else if (!filter && fstate) {
+ /* switch off filtering */
+ /* flush stream */
+ do {
+ c_stream.next_out = (Bytef*)outbuf;
+ c_stream.avail_out = OUTSIZE;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_OK && err != Z_STREAM_END) {
+ fprintf(stderr, "deflate: %s (%d)\n", c_stream.msg, err);
+ exit(2);
+ }
+ n += fwrite(outbuf, 1, OUTSIZE-c_stream.avail_out, f);
+ } while (err != Z_STREAM_END);
+
+ fstate = 0;
+ }
+ if (!fstate) {
+ fwrite(s, 1, len, f);
+ return n+len;
+ }
+
+ /* do the actual compression */
+ c_stream.next_in = (Bytef*) s;
+ c_stream.avail_in = len;
+
+ do {
+ c_stream.next_out = (Bytef*) outbuf;
+ c_stream.avail_out = OUTSIZE;
+
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ if (err != Z_OK) {
+ fprintf(stderr, "deflate: %s (%d)\n", c_stream.msg, err);
+ exit(2);
+ }
+ n += fwrite(outbuf, 1, OUTSIZE-c_stream.avail_out, f);
+ } while (!c_stream.avail_out);
+
+ return n;
+}
+
+/* ship len bytes from s using zlib compression. */
+int flate_xship(FILE *f, int filter, const char *s, int len) {
+ static int fstate = 0;
+ static z_stream c_stream;
+ char outbuf[OUTSIZE];
+ int err;
+ int n=0;
+
+ if (filter && !fstate) {
+ /* switch on filtering */
+ if (filter == 1) {
+ n += fprintf(f, "currentfile /ASCII85Decode filter /FlateDecode filter cvx exec\n");
+ }
+ c_stream.zalloc = Z_NULL;
+ c_stream.zfree = Z_NULL;
+ c_stream.opaque = Z_NULL;
+ err = deflateInit(&c_stream, 9);
+ if (err != Z_OK) {
+ fprintf(stderr, "deflateInit: %s (%d)\n", c_stream.msg, err);
+ exit(2);
+ }
+ c_stream.avail_in = 0;
+ n += a85init(f);
+ fstate = 1;
+ } else if (!filter && fstate) {
+ /* switch off filtering */
+ /* flush stream */
+ do {
+ c_stream.next_out = (Bytef*)outbuf;
+ c_stream.avail_out = OUTSIZE;
+
+ err = deflate(&c_stream, Z_FINISH);
+ if (err != Z_OK && err != Z_STREAM_END) {
+ fprintf(stderr, "deflate: %s (%d)\n", c_stream.msg, err);
+ exit(2);
+ }
+ n += a85write(f, outbuf, OUTSIZE-c_stream.avail_out);
+ } while (err != Z_STREAM_END);
+
+ n += a85finish(f);
+
+ fstate = 0;
+ }
+ if (!fstate) {
+ fwrite(s, 1, len, f);
+ return n+len;
+ }
+
+ /* do the actual compression */
+ c_stream.next_in = (Bytef*) s;
+ c_stream.avail_in = len;
+
+ do {
+ c_stream.next_out = (Bytef*) outbuf;
+ c_stream.avail_out = OUTSIZE;
+
+ err = deflate(&c_stream, Z_NO_FLUSH);
+ if (err != Z_OK) {
+ fprintf(stderr, "deflate: %s (%d)\n", c_stream.msg, err);
+ exit(2);
+ }
+ n += a85write(f, outbuf, OUTSIZE-c_stream.avail_out);
+ } while (!c_stream.avail_out);
+
+ return n;
+}
+
+#else /* HAVE_ZLIB */
+
+int pdf_xship(FILE *f, int filter, const char *s, int len) {
+ return dummy_xship(f, filter, s, len);
+}
+
+int flate_xship(FILE *f, int filter, const char *s, int len) {
+ return dummy_xship(f, filter, s, len);
+}
+
+#endif /* HAVE_ZLIB */
+
+/* ---------------------------------------------------------------------- */
+/* lzw interface: LZW (=postscript level 2) compression with a85.
+ This relies on lzw.c/h to do the actual compression. */
+
+/* use Postscript level 2 compression. Ship len bytes from str. */
+int lzw_xship(FILE *f, int filter, const char *str, int len) {
+ static int fstate = 0;
+ static lzw_stream_t *s = NULL;
+ char outbuf[OUTSIZE];
+ int err;
+ int n=0;
+
+ if (filter && !fstate) {
+ /* switch on filtering */
+ if (filter == 1) {
+ n += fprintf(f, "currentfile /ASCII85Decode filter /LZWDecode filter cvx exec\n");
+ }
+ s = lzw_init();
+ if (s == NULL) {
+ fprintf(stderr, "lzw_init: %s\n", strerror(errno));
+ exit(2);
+ }
+ n += a85init(f);
+ fstate = 1;
+ } else if (!filter && fstate) {
+ /* switch off filtering */
+ /* flush stream */
+ s->next_in = 0;
+ s->avail_in = 0;
+ do {
+ s->next_out = outbuf;
+ s->avail_out = OUTSIZE;
+
+ err = lzw_compress(s, LZW_EOD);
+ if (err) {
+ fprintf(stderr, "lzw_compress: %s\n", strerror(errno));
+ exit(2);
+ }
+ n += a85write(f, outbuf, OUTSIZE - s->avail_out);
+ } while (s->avail_out == 0);
+
+ n += a85finish(f);
+
+ lzw_free(s);
+ s = NULL;
+
+ fstate = 0;
+ }
+ if (!fstate) {
+ fwrite(str, 1, len, f);
+ return n+len;
+ }
+
+ /* do the actual compression */
+ s->next_in = str;
+ s->avail_in = len;
+
+ do {
+ s->next_out = outbuf;
+ s->avail_out = OUTSIZE;
+
+ err = lzw_compress(s, LZW_NORMAL);
+ if (err) {
+ fprintf(stderr, "lzw_compress: %s\n", strerror(errno));
+ exit(2);
+ }
+ n += a85write(f, outbuf, OUTSIZE - s->avail_out);
+ } while (s->avail_out == 0);
+
+ return n;
+}
+
+/* ---------------------------------------------------------------------- */
+/* a85 interface: a85 encoding without compression */
+
+/* ship len bytes from s using a85 encoding only. */
+int a85_xship(FILE *f, int filter, const char *s, int len) {
+ static int fstate = 0;
+ int n=0;
+
+ if (filter && !fstate) {
+ /* switch on filtering */
+ if (filter == 1) {
+ n += fprintf(f, "currentfile /ASCII85Decode filter cvx exec\n");
+ }
+ n += a85init(f);
+ fstate = 1;
+ } else if (!filter && fstate) {
+ /* switch off filtering */
+ /* flush stream */
+ n += a85finish(f);
+ fstate = 0;
+ }
+ if (!fstate) {
+ fwrite(s, 1, len, f);
+ return n+len;
+ }
+
+ n += a85write(f, s, len);
+
+ return n;
+}
+
+/* ---------------------------------------------------------------------- */
+/* low-level a85 backend */
+
+static unsigned long a85buf[4];
+static int a85n;
+static int a85col;
+
+static int a85init(FILE *f) {
+ a85n = 0;
+ a85col = 0;
+ return 0;
+}
+
+static int a85finish(FILE *f) {
+ int r=0;
+
+ if (a85n) {
+ r+=a85out(f, a85n);
+ }
+ fputs("~>\n", f);
+ return r+2;
+}
+
+static int a85write(FILE *f, const char *buf, int n) {
+ int i;
+ int r=0;
+
+ for (i=0; i<n; i++) {
+ a85buf[a85n] = (unsigned char)buf[i];
+ a85n++;
+
+ if (a85n == 4) {
+ r+=a85out(f, 4);
+ a85n = 0;
+ }
+ }
+ return r;
+}
+
+static int a85out(FILE *f, int n) {
+ char out[5];
+ unsigned long s;
+ int r=0;
+ int i;
+
+ for (i=n; i<4; i++) {
+ a85buf[i] = 0;
+ }
+
+ s = (a85buf[0]<<24) + (a85buf[1]<<16) + (a85buf[2]<<8) + (a85buf[3]<<0);
+
+ if (!s) {
+ r+=a85spool(f, 'z');
+ } else {
+ for (i=4; i>=0; i--) {
+ out[i] = s % 85;
+ s /= 85;
+ }
+ for (i=0; i<n+1; i++) {
+ r+=a85spool(f, out[i]+33);
+ }
+ }
+ return r;
+}
+
+static int a85spool(FILE *f, char c) {
+ fputc(c, f);
+
+ a85col++;
+ if (a85col>70) {
+ fputc('\n', f);
+ a85col=0;
+ return 2;
+ }
+
+ return 1;
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/flate.h b/Build/source/libs/potrace/potrace-src/src/flate.h
new file mode 100644
index 00000000000..47cea3a77f9
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/flate.h
@@ -0,0 +1,15 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef FLATE_H
+#define FLATE_H
+
+int dummy_xship(FILE *f, int filter, const char *s, int len);
+int flate_xship(FILE *f, int filter, const char *s, int len);
+int pdf_xship(FILE *f, int filter, const char *s, int len);
+int lzw_xship(FILE *f, int filter, const char *s, int len);
+int a85_xship(FILE *f, int filter, const char *s, int len);
+
+#endif /* FLATE_H */
diff --git a/Build/source/libs/potrace/potrace-src/src/getopt.c b/Build/source/libs/potrace/potrace-src/src/getopt.c
new file mode 100644
index 00000000000..d889c3c8686
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/getopt.c
@@ -0,0 +1,1041 @@
+/* Getopt for GNU.
+ NOTE: getopt is now part of the C library, so if you don't know what
+ "Keep this file name-space clean" means, talk to drepper@gnu.org
+ before changing it!
+
+ Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 2000
+ Free Software Foundation, Inc.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
+ Ditto for AIX 3.2 and <stdlib.h>. */
+#ifndef _NO_PROTO
+# define _NO_PROTO
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+# ifndef const
+# define const
+# endif
+#endif
+
+#include <stdio.h>
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+/* Don't include stdlib.h for non-GNU C libraries because some of them
+ contain conflicting prototypes for getopt. */
+# include <stdlib.h>
+# include <unistd.h>
+#endif /* GNU C library. */
+
+#ifdef VMS
+# include <unixlib.h>
+# if HAVE_STRING_H - 0
+# include <string.h>
+# endif
+#endif
+
+#ifndef _
+/* This is for other GNU distributions with internationalized messages. */
+# if defined HAVE_LIBINTL_H || defined _LIBC
+# include <libintl.h>
+# ifndef _
+# define _(msgid) gettext (msgid)
+# endif
+# else
+# define _(msgid) (msgid)
+# endif
+#endif
+
+/* This version of `getopt' appears to the caller like standard Unix `getopt'
+ but it behaves differently for the user, since it allows the user
+ to intersperse the options with the other arguments.
+
+ As `getopt' works, it permutes the elements of ARGV so that,
+ when it is done, all the options precede everything else. Thus
+ all application programs are extended to handle flexible argument order.
+
+ Setting the environment variable POSIXLY_CORRECT disables permutation.
+ Then the behavior is completely standard.
+
+ GNU application programs can use a third alternative mode in which
+ they can distinguish the relative order of options and other arguments. */
+
+#include "getopt.h"
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+/* 1003.2 says this must be 1 before any call. */
+int optind = 1;
+
+/* Formerly, initialization of getopt depended on optind==0, which
+ causes problems with re-calling getopt as programs generally don't
+ know that. */
+
+int __getopt_initialized;
+
+/* The next char to be scanned in the option-element
+ in which the last option character we returned was found.
+ This allows us to pick up the scan where we left off.
+
+ If this is zero, or a null string, it means resume the scan
+ by advancing to the next ARGV-element. */
+
+static char *nextchar;
+
+/* Callers store zero here to inhibit the error message
+ for unrecognized options. */
+
+int opterr = 1;
+
+/* Set to an option character which was unrecognized.
+ This must be initialized on some systems to avoid linking in the
+ system's own getopt implementation. */
+
+int optopt = '?';
+
+/* Describe how to deal with options that follow non-option ARGV-elements.
+
+ If the caller did not specify anything,
+ the default is REQUIRE_ORDER if the environment variable
+ POSIXLY_CORRECT is defined, PERMUTE otherwise.
+
+ REQUIRE_ORDER means don't recognize them as options;
+ stop option processing when the first non-option is seen.
+ This is what Unix does.
+ This mode of operation is selected by either setting the environment
+ variable POSIXLY_CORRECT, or using `+' as the first character
+ of the list of option characters.
+
+ PERMUTE is the default. We permute the contents of ARGV as we scan,
+ so that eventually all the non-options are at the end. This allows options
+ to be given in any order, even with programs that were not written to
+ expect this.
+
+ RETURN_IN_ORDER is an option available to programs that were written
+ to expect options and other ARGV-elements in any order and that care about
+ the ordering of the two. We describe each non-option ARGV-element
+ as if it were the argument of an option with character code 1.
+ Using `-' as the first character of the list of option characters
+ selects this mode of operation.
+
+ The special argument `--' forces an end of option-scanning regardless
+ of the value of `ordering'. In the case of RETURN_IN_ORDER, only
+ `--' can cause `getopt' to return -1 with `optind' != ARGC. */
+
+static enum
+{
+ REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
+} ordering;
+
+/* Value of POSIXLY_CORRECT environment variable. */
+static char *posixly_correct;
+
+#ifdef __GNU_LIBRARY__
+/* We want to avoid inclusion of string.h with non-GNU libraries
+ because there are many ways it can cause trouble.
+ On some systems, it contains special magic macros that don't work
+ in GCC. */
+# include <string.h>
+# define my_index strchr
+#else
+
+# if HAVE_STRING_H
+# include <string.h>
+# else
+# include <strings.h>
+# endif
+
+/* Avoid depending on library functions or files
+ whose names are inconsistent. */
+
+#ifndef getenv
+extern char *getenv ();
+#endif
+
+static char *
+my_index (str, chr)
+ const char *str;
+ int chr;
+{
+ while (*str)
+ {
+ if (*str == chr)
+ return (char *) str;
+ str++;
+ }
+ return 0;
+}
+
+/* If using GCC, we can safely declare strlen this way.
+ If not using GCC, it is ok not to declare it. */
+#ifdef __GNUC__
+/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
+ That was relevant to code that was here before. */
+# if (!defined __STDC__ || !__STDC__) && !defined strlen
+/* gcc with -traditional declares the built-in strlen to return int,
+ and has done so at least since version 2.4.5. -- rms. */
+extern int strlen (const char *);
+# endif /* not __STDC__ */
+#endif /* __GNUC__ */
+
+#endif /* not __GNU_LIBRARY__ */
+
+/* Handle permutation of arguments. */
+
+/* Describe the part of ARGV that contains non-options that have
+ been skipped. `first_nonopt' is the index in ARGV of the first of them;
+ `last_nonopt' is the index after the last of them. */
+
+static int first_nonopt;
+static int last_nonopt;
+
+#ifdef _LIBC
+/* Bash 2.0 gives us an environment variable containing flags
+ indicating ARGV elements that should not be considered arguments. */
+
+/* Defined in getopt_init.c */
+extern char *__getopt_nonoption_flags;
+
+static int nonoption_flags_max_len;
+static int nonoption_flags_len;
+
+static int original_argc;
+static char *const *original_argv;
+
+/* Make sure the environment variable bash 2.0 puts in the environment
+ is valid for the getopt call we must make sure that the ARGV passed
+ to getopt is that one passed to the process. */
+static void
+__attribute__ ((unused))
+store_args_and_env (int argc, char *const *argv)
+{
+ /* XXX This is no good solution. We should rather copy the args so
+ that we can compare them later. But we must not use malloc(3). */
+ original_argc = argc;
+ original_argv = argv;
+}
+# ifdef text_set_element
+text_set_element (__libc_subinit, store_args_and_env);
+# endif /* text_set_element */
+
+# define SWAP_FLAGS(ch1, ch2) \
+ if (nonoption_flags_len > 0) \
+ { \
+ char __tmp = __getopt_nonoption_flags[ch1]; \
+ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \
+ __getopt_nonoption_flags[ch2] = __tmp; \
+ }
+#else /* !_LIBC */
+# define SWAP_FLAGS(ch1, ch2)
+#endif /* _LIBC */
+
+/* Exchange two adjacent subsequences of ARGV.
+ One subsequence is elements [first_nonopt,last_nonopt)
+ which contains all the non-options that have been skipped so far.
+ The other is elements [last_nonopt,optind), which contains all
+ the options processed since those non-options were skipped.
+
+ `first_nonopt' and `last_nonopt' are relocated so that they describe
+ the new indices of the non-options in ARGV after they are moved. */
+
+#if defined __STDC__ && __STDC__
+static void exchange (char **);
+#endif
+
+static void
+exchange (argv)
+ char **argv;
+{
+ int bottom = first_nonopt;
+ int middle = last_nonopt;
+ int top = optind;
+ char *tem;
+
+ /* Exchange the shorter segment with the far end of the longer segment.
+ That puts the shorter segment into the right place.
+ It leaves the longer segment in the right place overall,
+ but it consists of two parts that need to be swapped next. */
+
+#ifdef _LIBC
+ /* First make sure the handling of the `__getopt_nonoption_flags'
+ string can work normally. Our top argument must be in the range
+ of the string. */
+ if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len)
+ {
+ /* We must extend the array. The user plays games with us and
+ presents new arguments. */
+ char *new_str = malloc (top + 1);
+ if (new_str == NULL)
+ nonoption_flags_len = nonoption_flags_max_len = 0;
+ else
+ {
+ memset (__mempcpy (new_str, __getopt_nonoption_flags,
+ nonoption_flags_max_len),
+ '\0', top + 1 - nonoption_flags_max_len);
+ nonoption_flags_max_len = top + 1;
+ __getopt_nonoption_flags = new_str;
+ }
+ }
+#endif
+
+ while (top > middle && middle > bottom)
+ {
+ if (top - middle > middle - bottom)
+ {
+ /* Bottom segment is the short one. */
+ int len = middle - bottom;
+ register int i;
+
+ /* Swap it with the top part of the top segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[top - (middle - bottom) + i];
+ argv[top - (middle - bottom) + i] = tem;
+ SWAP_FLAGS (bottom + i, top - (middle - bottom) + i);
+ }
+ /* Exclude the moved bottom segment from further swapping. */
+ top -= len;
+ }
+ else
+ {
+ /* Top segment is the short one. */
+ int len = top - middle;
+ register int i;
+
+ /* Swap it with the bottom part of the bottom segment. */
+ for (i = 0; i < len; i++)
+ {
+ tem = argv[bottom + i];
+ argv[bottom + i] = argv[middle + i];
+ argv[middle + i] = tem;
+ SWAP_FLAGS (bottom + i, middle + i);
+ }
+ /* Exclude the moved top segment from further swapping. */
+ bottom += len;
+ }
+ }
+
+ /* Update records for the slots the non-options now occupy. */
+
+ first_nonopt += (optind - last_nonopt);
+ last_nonopt = optind;
+}
+
+/* Initialize the internal data when the first call is made. */
+
+#if defined __STDC__ && __STDC__
+static const char *_getopt_initialize (int, char *const *, const char *);
+#endif
+static const char *
+_getopt_initialize (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ /* Start processing options with ARGV-element 1 (since ARGV-element 0
+ is the program name); the sequence of previously skipped
+ non-option ARGV-elements is empty. */
+
+ first_nonopt = last_nonopt = optind;
+
+ nextchar = NULL;
+
+ posixly_correct = getenv ("POSIXLY_CORRECT");
+
+ /* Determine how to handle the ordering of options and nonoptions. */
+
+ if (optstring[0] == '-')
+ {
+ ordering = RETURN_IN_ORDER;
+ ++optstring;
+ }
+ else if (optstring[0] == '+')
+ {
+ ordering = REQUIRE_ORDER;
+ ++optstring;
+ }
+ else if (posixly_correct != NULL)
+ ordering = REQUIRE_ORDER;
+ else
+ ordering = PERMUTE;
+
+#ifdef _LIBC
+ if (posixly_correct == NULL
+ && argc == original_argc && argv == original_argv)
+ {
+ if (nonoption_flags_max_len == 0)
+ {
+ if (__getopt_nonoption_flags == NULL
+ || __getopt_nonoption_flags[0] == '\0')
+ nonoption_flags_max_len = -1;
+ else
+ {
+ const char *orig_str = __getopt_nonoption_flags;
+ int len = nonoption_flags_max_len = strlen (orig_str);
+ if (nonoption_flags_max_len < argc)
+ nonoption_flags_max_len = argc;
+ __getopt_nonoption_flags =
+ (char *) malloc (nonoption_flags_max_len);
+ if (__getopt_nonoption_flags == NULL)
+ nonoption_flags_max_len = -1;
+ else
+ memset (__mempcpy (__getopt_nonoption_flags, orig_str, len),
+ '\0', nonoption_flags_max_len - len);
+ }
+ }
+ nonoption_flags_len = nonoption_flags_max_len;
+ }
+ else
+ nonoption_flags_len = 0;
+#endif
+
+ return optstring;
+}
+
+/* Scan elements of ARGV (whose length is ARGC) for option characters
+ given in OPTSTRING.
+
+ If an element of ARGV starts with '-', and is not exactly "-" or "--",
+ then it is an option element. The characters of this element
+ (aside from the initial '-') are option characters. If `getopt'
+ is called repeatedly, it returns successively each of the option characters
+ from each of the option elements.
+
+ If `getopt' finds another option character, it returns that character,
+ updating `optind' and `nextchar' so that the next call to `getopt' can
+ resume the scan with the following option character or ARGV-element.
+
+ If there are no more option characters, `getopt' returns -1.
+ Then `optind' is the index in ARGV of the first ARGV-element
+ that is not an option. (The ARGV-elements have been permuted
+ so that those that are not options now come last.)
+
+ OPTSTRING is a string containing the legitimate option characters.
+ If an option character is seen that is not listed in OPTSTRING,
+ return '?' after printing an error message. If you set `opterr' to
+ zero, the error message is suppressed but we still return '?'.
+
+ If a char in OPTSTRING is followed by a colon, that means it wants an arg,
+ so the following text in the same ARGV-element, or the text of the following
+ ARGV-element, is returned in `optarg'. Two colons mean an option that
+ wants an optional arg; if there is text in the current ARGV-element,
+ it is returned in `optarg', otherwise `optarg' is set to zero.
+
+ If OPTSTRING starts with `-' or `+', it requests different methods of
+ handling the non-option ARGV-elements.
+ See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
+
+ Long-named options begin with `--' instead of `-'.
+ Their names may be abbreviated as long as the abbreviation is unique
+ or is an exact match for some defined option. If they have an
+ argument, it follows the option name in the same ARGV-element, separated
+ from the option name by a `=', or else the in next ARGV-element.
+ When `getopt' finds a long-named option, it returns 0 if that option's
+ `flag' field is nonzero, the value of the option's `val' field
+ if the `flag' field is zero.
+
+ The elements of ARGV aren't really const, because we permute them.
+ But we pretend they're const in the prototype to be compatible
+ with other systems.
+
+ LONGOPTS is a vector of `struct option' terminated by an
+ element containing a name which is zero.
+
+ LONGIND returns the index in LONGOPT of the long-named option found.
+ It is only valid when a long-named option has been found by the most
+ recent call.
+
+ If LONG_ONLY is nonzero, '-' as well as '--' can introduce
+ long-named options. */
+
+int
+_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+ const struct option *longopts;
+ int *longind;
+ int long_only;
+{
+ int print_errors = opterr;
+ if (optstring[0] == ':')
+ print_errors = 0;
+
+ if (argc < 1)
+ return -1;
+
+ optarg = NULL;
+
+ if (optind == 0 || !__getopt_initialized)
+ {
+ if (optind == 0)
+ optind = 1; /* Don't scan ARGV[0], the program name. */
+ optstring = _getopt_initialize (argc, argv, optstring);
+ __getopt_initialized = 1;
+ }
+
+ /* Test whether ARGV[optind] points to a non-option argument.
+ Either it does not have option syntax, or there is an environment flag
+ from the shell indicating it is not an option. The later information
+ is only used when the used in the GNU libc. */
+#ifdef _LIBC
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \
+ || (optind < nonoption_flags_len \
+ && __getopt_nonoption_flags[optind] == '1'))
+#else
+# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')
+#endif
+
+ if (nextchar == NULL || *nextchar == '\0')
+ {
+ /* Advance to the next ARGV-element. */
+
+ /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been
+ moved back by the user (who may also have changed the arguments). */
+ if (last_nonopt > optind)
+ last_nonopt = optind;
+ if (first_nonopt > optind)
+ first_nonopt = optind;
+
+ if (ordering == PERMUTE)
+ {
+ /* If we have just processed some options following some non-options,
+ exchange them so that the options come first. */
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (last_nonopt != optind)
+ first_nonopt = optind;
+
+ /* Skip any additional non-options
+ and extend the range of non-options previously skipped. */
+
+ while (optind < argc && NONOPTION_P)
+ optind++;
+ last_nonopt = optind;
+ }
+
+ /* The special ARGV-element `--' means premature end of options.
+ Skip it like a null option,
+ then exchange with previous non-options as if it were an option,
+ then skip everything else like a non-option. */
+
+ if (optind != argc && !strcmp (argv[optind], "--"))
+ {
+ optind++;
+
+ if (first_nonopt != last_nonopt && last_nonopt != optind)
+ exchange ((char **) argv);
+ else if (first_nonopt == last_nonopt)
+ first_nonopt = optind;
+ last_nonopt = argc;
+
+ optind = argc;
+ }
+
+ /* If we have done all the ARGV-elements, stop the scan
+ and back over any non-options that we skipped and permuted. */
+
+ if (optind == argc)
+ {
+ /* Set the next-arg-index to point at the non-options
+ that we previously skipped, so the caller will digest them. */
+ if (first_nonopt != last_nonopt)
+ optind = first_nonopt;
+ return -1;
+ }
+
+ /* If we have come to a non-option and did not permute it,
+ either stop the scan or describe it to the caller and pass it by. */
+
+ if (NONOPTION_P)
+ {
+ if (ordering == REQUIRE_ORDER)
+ return -1;
+ optarg = argv[optind++];
+ return 1;
+ }
+
+ /* We have found another option-ARGV-element.
+ Skip the initial punctuation. */
+
+ nextchar = (argv[optind] + 1
+ + (longopts != NULL && argv[optind][1] == '-'));
+ }
+
+ /* Decode the current option-ARGV-element. */
+
+ /* Check whether the ARGV-element is a long option.
+
+ If long_only and the ARGV-element has the form "-f", where f is
+ a valid short option, don't consider it an abbreviated form of
+ a long option that starts with f. Otherwise there would be no
+ way to give the -f short option.
+
+ On the other hand, if there's a long option "fubar" and
+ the ARGV-element is "-fu", do consider that an abbreviation of
+ the long option, just like "--fu", and not "-f" with arg "u".
+
+ This distinction seems to be the most useful approach. */
+
+ if (longopts != NULL
+ && (argv[optind][1] == '-'
+ || (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = -1;
+ int option_index;
+
+ for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar)
+ == (unsigned int) strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else if (long_only
+ || pfound->has_arg != p->has_arg
+ || pfound->flag != p->flag
+ || pfound->val != p->val)
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+
+ if (ambig && !exact)
+ {
+ if (print_errors)
+ fprintf (stderr, _("%s: option `%s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ optind++;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (print_errors)
+ {
+ if (argv[optind - 1][1] == '-')
+ /* --option */
+ fprintf (stderr,
+ _("%s: option `--%s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+ else
+ /* +option or -option */
+ fprintf (stderr,
+ _("%s: option `%c%s' doesn't allow an argument\n"),
+ argv[0], argv[optind - 1][0], pfound->name);
+ }
+
+ nextchar += strlen (nextchar);
+
+ optopt = pfound->val;
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (print_errors)
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ optopt = pfound->val;
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+
+ /* Can't find it as a long option. If this is not getopt_long_only,
+ or the option starts with '--' or is not a valid short
+ option, then it's an error.
+ Otherwise interpret it as a short option. */
+ if (!long_only || argv[optind][1] == '-'
+ || my_index (optstring, *nextchar) == NULL)
+ {
+ if (print_errors)
+ {
+ if (argv[optind][1] == '-')
+ /* --option */
+ fprintf (stderr, _("%s: unrecognized option `--%s'\n"),
+ argv[0], nextchar);
+ else
+ /* +option or -option */
+ fprintf (stderr, _("%s: unrecognized option `%c%s'\n"),
+ argv[0], argv[optind][0], nextchar);
+ }
+ nextchar = (char *) "";
+ optind++;
+ optopt = 0;
+ return '?';
+ }
+ }
+
+ /* Look at and handle the next short option-character. */
+
+ {
+ char c = *nextchar++;
+ char *temp = my_index (optstring, c);
+
+ /* Increment `optind' when we start to process its last character. */
+ if (*nextchar == '\0')
+ ++optind;
+
+ if (temp == NULL || c == ':')
+ {
+ if (print_errors)
+ {
+ if (posixly_correct)
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: illegal option -- %c\n"),
+ argv[0], c);
+ else
+ fprintf (stderr, _("%s: invalid option -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ return '?';
+ }
+ /* Convenience. Treat POSIX -W foo same as long option --foo */
+ if (temp[0] == 'W' && temp[1] == ';')
+ {
+ char *nameend;
+ const struct option *p;
+ const struct option *pfound = NULL;
+ int exact = 0;
+ int ambig = 0;
+ int indfound = 0;
+ int option_index;
+
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (print_errors)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr, _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ return c;
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+
+ /* optarg is now the argument, see if it's in the
+ table of longopts. */
+
+ for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++)
+ /* Do nothing. */ ;
+
+ /* Test all long options for either exact match
+ or abbreviated matches. */
+ for (p = longopts, option_index = 0; p->name; p++, option_index++)
+ if (!strncmp (p->name, nextchar, nameend - nextchar))
+ {
+ if ((unsigned int) (nameend - nextchar) == strlen (p->name))
+ {
+ /* Exact match found. */
+ pfound = p;
+ indfound = option_index;
+ exact = 1;
+ break;
+ }
+ else if (pfound == NULL)
+ {
+ /* First nonexact match found. */
+ pfound = p;
+ indfound = option_index;
+ }
+ else
+ /* Second or later nonexact match found. */
+ ambig = 1;
+ }
+ if (ambig && !exact)
+ {
+ if (print_errors)
+ fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"),
+ argv[0], argv[optind]);
+ nextchar += strlen (nextchar);
+ optind++;
+ return '?';
+ }
+ if (pfound != NULL)
+ {
+ option_index = indfound;
+ if (*nameend)
+ {
+ /* Don't test has_arg with >, because some C compilers don't
+ allow it to be used on enums. */
+ if (pfound->has_arg)
+ optarg = nameend + 1;
+ else
+ {
+ if (print_errors)
+ fprintf (stderr, _("%s: option `-W %s' doesn't allow an argument\n"),
+ argv[0], pfound->name);
+
+ nextchar += strlen (nextchar);
+ return '?';
+ }
+ }
+ else if (pfound->has_arg == 1)
+ {
+ if (optind < argc)
+ optarg = argv[optind++];
+ else
+ {
+ if (print_errors)
+ fprintf (stderr,
+ _("%s: option `%s' requires an argument\n"),
+ argv[0], argv[optind - 1]);
+ nextchar += strlen (nextchar);
+ return optstring[0] == ':' ? ':' : '?';
+ }
+ }
+ nextchar += strlen (nextchar);
+ if (longind != NULL)
+ *longind = option_index;
+ if (pfound->flag)
+ {
+ *(pfound->flag) = pfound->val;
+ return 0;
+ }
+ return pfound->val;
+ }
+ nextchar = NULL;
+ return 'W'; /* Let the application handle it. */
+ }
+ if (temp[1] == ':')
+ {
+ if (temp[2] == ':')
+ {
+ /* This is an option that accepts an argument optionally. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ optind++;
+ }
+ else
+ optarg = NULL;
+ nextchar = NULL;
+ }
+ else
+ {
+ /* This is an option that requires an argument. */
+ if (*nextchar != '\0')
+ {
+ optarg = nextchar;
+ /* If we end this ARGV-element by taking the rest as an arg,
+ we must advance to the next element now. */
+ optind++;
+ }
+ else if (optind == argc)
+ {
+ if (print_errors)
+ {
+ /* 1003.2 specifies the format of this message. */
+ fprintf (stderr,
+ _("%s: option requires an argument -- %c\n"),
+ argv[0], c);
+ }
+ optopt = c;
+ if (optstring[0] == ':')
+ c = ':';
+ else
+ c = '?';
+ }
+ else
+ /* We already incremented `optind' once;
+ increment it again when taking next ARGV-elt as argument. */
+ optarg = argv[optind++];
+ nextchar = NULL;
+ }
+ }
+ return c;
+ }
+}
+
+int
+getopt (argc, argv, optstring)
+ int argc;
+ char *const *argv;
+ const char *optstring;
+{
+ return _getopt_internal (argc, argv, optstring,
+ (const struct option *) 0,
+ (int *) 0,
+ 0);
+}
+
+
+#ifdef TEST
+
+/* Compile with -DTEST to make an executable for use in testing
+ the above definition of `getopt'. */
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+
+ c = getopt (argc, argv, "abc:d:0123456789");
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/Build/source/libs/potrace/potrace-src/src/getopt1.c b/Build/source/libs/potrace/potrace-src/src/getopt1.c
new file mode 100644
index 00000000000..d983d120ac0
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/getopt1.c
@@ -0,0 +1,168 @@
+/* getopt_long and getopt_long_only entry points for GNU getopt.
+ Copyright (C) 1987,88,89,90,91,92,93,94,96,97,98
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "getopt.h"
+
+#if !defined __STDC__ || !__STDC__
+/* This is a separate conditional since some stdc systems
+ reject `defined (const)'. */
+#ifndef const
+#define const
+#endif
+#endif
+
+#include <stdio.h>
+
+/* This needs to come after some library #include
+ to get __GNU_LIBRARY__ defined. */
+#ifdef __GNU_LIBRARY__
+#include <stdlib.h>
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+int
+getopt_long (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
+}
+
+/* Like getopt_long, but '-' as well as '--' can indicate a long option.
+ If an option that starts with '-' (not '--') doesn't match a long option,
+ but does match a short option, it is parsed as a short option
+ instead. */
+
+int
+getopt_long_only (argc, argv, options, long_options, opt_index)
+ int argc;
+ char *const *argv;
+ const char *options;
+ const struct option *long_options;
+ int *opt_index;
+{
+ return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
+}
+
+
+
+#ifdef TEST
+
+#include <stdio.h>
+
+int
+main (argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ int digit_optind = 0;
+
+ while (1)
+ {
+ int this_option_optind = optind ? optind : 1;
+ int option_index = 0;
+ static struct option long_options[] =
+ {
+ {"add", 1, 0, 0},
+ {"append", 0, 0, 0},
+ {"delete", 1, 0, 0},
+ {"verbose", 0, 0, 0},
+ {"create", 0, 0, 0},
+ {"file", 1, 0, 0},
+ {0, 0, 0, 0}
+ };
+
+ c = getopt_long (argc, argv, "abc:d:0123456789",
+ long_options, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c)
+ {
+ case 0:
+ printf ("option %s", long_options[option_index].name);
+ if (optarg)
+ printf (" with arg %s", optarg);
+ printf ("\n");
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (digit_optind != 0 && digit_optind != this_option_optind)
+ printf ("digits occur in two different argv-elements.\n");
+ digit_optind = this_option_optind;
+ printf ("option %c\n", c);
+ break;
+
+ case 'a':
+ printf ("option a\n");
+ break;
+
+ case 'b':
+ printf ("option b\n");
+ break;
+
+ case 'c':
+ printf ("option c with value `%s'\n", optarg);
+ break;
+
+ case 'd':
+ printf ("option d with value `%s'\n", optarg);
+ break;
+
+ case '?':
+ break;
+
+ default:
+ printf ("?? getopt returned character code 0%o ??\n", c);
+ }
+ }
+
+ if (optind < argc)
+ {
+ printf ("non-option ARGV-elements: ");
+ while (optind < argc)
+ printf ("%s ", argv[optind++]);
+ printf ("\n");
+ }
+
+ exit (0);
+}
+
+#endif /* TEST */
diff --git a/Build/source/libs/potrace/potrace-src/src/greymap.c b/Build/source/libs/potrace/potrace-src/src/greymap.c
new file mode 100644
index 00000000000..756f207486b
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/greymap.c
@@ -0,0 +1,1090 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+/* Routines for manipulating greymaps, including reading pgm files. We
+ only deal with greymaps of depth 8 bits. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <errno.h>
+#include <stddef.h>
+#ifdef HAVE_INTTYPES_H
+#include <inttypes.h>
+#endif
+
+#include "greymap.h"
+#include "bitops.h"
+
+#define INTBITS (8*sizeof(int))
+
+#define mod(a,n) ((a)>=(n) ? (a)%(n) : (a)>=0 ? (a) : (n)-1-(-1-(a))%(n))
+
+static int gm_readbody_pnm(FILE *f, greymap_t **gmp, int magic);
+static int gm_readbody_bmp(FILE *f, greymap_t **gmp);
+
+#define TRY(x) if (x) goto try_error
+#define TRY_EOF(x) if (x) goto eof
+#define TRY_STD(x) if (x) goto std_error
+
+/* ---------------------------------------------------------------------- */
+/* basic greymap routines */
+
+/* calculate the size, in bytes, required for the data area of a
+ greymap of the given dy and h. Assume h >= 0. Return -1 if the size
+ does not fit into the ptrdiff_t type. */
+static inline ptrdiff_t getsize(int dy, int h) {
+ ptrdiff_t size;
+
+ if (dy < 0) {
+ dy = -dy;
+ }
+
+ size = (ptrdiff_t)dy * (ptrdiff_t)h * (ptrdiff_t)GM_SAMPLESIZE;
+
+ /* check for overflow error */
+ if (size < 0 || (h != 0 && dy != 0 && size / h / dy != GM_SAMPLESIZE)) {
+ return -1;
+ }
+
+ return size;
+}
+
+/* return the size, in bytes, of the data area of the greymap. Return
+ -1 if the size does not fit into the ptrdiff_t type; however, this
+ cannot happen if the bitmap is well-formed, i.e., if created with
+ gm_new or gm_dup. */
+static inline ptrdiff_t gm_size(const greymap_t *gm) {
+ return getsize(gm->dy, gm->h);
+}
+
+
+
+/* return new greymap initialized to 0. NULL with errno on error.
+ Assumes w, h >= 0. */
+greymap_t *gm_new(int w, int h) {
+ greymap_t *gm;
+ int dy = w;
+ ptrdiff_t size;
+
+ size = getsize(dy, h);
+ if (size < 0) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ if (size == 0) {
+ size = GM_SAMPLESIZE; /* make sure calloc() doesn't return NULL */
+ }
+
+ gm = (greymap_t *) malloc(sizeof(greymap_t));
+ if (!gm) {
+ return NULL;
+ }
+ gm->w = w;
+ gm->h = h;
+ gm->dy = dy;
+ gm->base = (gm_sample_t *) calloc(1, size);
+ if (!gm->base) {
+ free(gm);
+ return NULL;
+ }
+ gm->map = gm->base;
+ return gm;
+}
+
+/* free the given greymap */
+void gm_free(greymap_t *gm) {
+ if (gm) {
+ free(gm->base);
+ }
+ free(gm);
+}
+
+/* duplicate the given greymap. Return NULL on error with errno set. */
+greymap_t *gm_dup(greymap_t *gm) {
+ greymap_t *gm1 = gm_new(gm->w, gm->h);
+ int y;
+
+ if (!gm1) {
+ return NULL;
+ }
+ for (y=0; y<gm->h; y++) {
+ memcpy(gm_scanline(gm1, y), gm_scanline(gm, y), (size_t)gm1->dy * GM_SAMPLESIZE);
+ }
+ return gm1;
+}
+
+/* clear the given greymap to color b. */
+void gm_clear(greymap_t *gm, int b) {
+ ptrdiff_t size = gm_size(gm);
+ int x, y;
+
+ if (b==0) {
+ memset(gm->base, 0, size);
+ } else {
+ for (y=0; y<gm->h; y++) {
+ for (x=0; x<gm->w; x++) {
+ GM_UPUT(gm, x, y, b);
+ }
+ }
+ }
+}
+
+/* turn the given greymap upside down. This does not move the pixel
+ data or change the base address. */
+static inline void gm_flip(greymap_t *gm) {
+ int dy = gm->dy;
+
+ if (gm->h == 0 || gm->h == 1) {
+ return;
+ }
+
+ gm->map = gm_scanline(gm, gm->h - 1);
+ gm->dy = -dy;
+}
+
+/* resize the greymap to the given new height. The pixel data remains
+ bottom-aligned (truncated at the top) when dy >= 0 and top-aligned
+ (truncated at the bottom) when dy < 0. Return 0 on success, or 1 on
+ error with errno set. If the new height is <= the old one, no error
+ should occur. If the new height is larger, the additional pixel
+ data is *not* initialized. */
+static inline int gm_resize(greymap_t *gm, int h) {
+ int dy = gm->dy;
+ ptrdiff_t newsize;
+ gm_sample_t *newbase;
+
+ if (dy < 0) {
+ gm_flip(gm);
+ }
+
+ newsize = getsize(dy, h);
+ if (newsize < 0) {
+ errno = ENOMEM;
+ goto error;
+ }
+ if (newsize == 0) {
+ newsize = GM_SAMPLESIZE; /* make sure realloc() doesn't return NULL */
+ }
+
+ newbase = (gm_sample_t *)realloc(gm->base, newsize);
+ if (newbase == NULL) {
+ goto error;
+ }
+ gm->base = newbase;
+ gm->map = newbase;
+ gm->h = h;
+
+ if (dy < 0) {
+ gm_flip(gm);
+ }
+ return 0;
+
+ error:
+ if (dy < 0) {
+ gm_flip(gm);
+ }
+ return 1;
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* routines for reading pnm streams */
+
+/* read next character after whitespace and comments. Return EOF on
+ end of file or error. */
+static int fgetc_ws(FILE *f) {
+ int c;
+
+ while (1) {
+ c = fgetc(f);
+ if (c=='#') {
+ while (1) {
+ c = fgetc(f);
+ if (c=='\n' || c==EOF) {
+ break;
+ }
+ }
+ }
+ /* space, tab, line feed, carriage return, form-feed */
+ if (c!=' ' && c!='\t' && c!='\r' && c!='\n' && c!=12) {
+ return c;
+ }
+ }
+}
+
+/* skip whitespace and comments, then read a non-negative decimal
+ number from a stream. Return -1 on EOF. Tolerate other errors (skip
+ bad characters). Do not the read any characters following the
+ number (put next character back into the stream) */
+
+static int readnum(FILE *f) {
+ int c;
+ uint64_t acc;
+
+ /* skip whitespace and comments */
+ while (1) {
+ c = fgetc_ws(f);
+ if (c==EOF) {
+ return -1;
+ }
+ if (c>='0' && c<='9') {
+ break;
+ }
+ }
+
+ /* first digit is already in c */
+ acc = c-'0';
+ while (1) {
+ c = fgetc(f);
+ if (c==EOF) {
+ break;
+ }
+ if (c<'0' || c>'9') {
+ ungetc(c, f);
+ break;
+ }
+ acc *= 10;
+ acc += c-'0';
+ if (acc > 0x7fffffff) {
+ return -1;
+ }
+ }
+ return acc;
+}
+
+/* similar to readnum, but read only a single 0 or 1, and do not read
+ any characters after it. */
+
+static int readbit(FILE *f) {
+ int c;
+
+ /* skip whitespace and comments */
+ while (1) {
+ c = fgetc_ws(f);
+ if (c==EOF) {
+ return -1;
+ }
+ if (c>='0' && c<='1') {
+ break;
+ }
+ }
+
+ return c-'0';
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* read a PNM stream: P1-P6 format (see pnm(5)), or a BMP stream, and
+ convert the output to a greymap. Return greymap in *gmp. Return 0
+ on success, -1 on error with errno set, -2 on bad file format (with
+ error message in gm_read_error), and 1 on premature end of file, -3
+ on empty file (including files with only whitespace and comments),
+ -4 if wrong magic number. If the return value is >=0, *gmp is
+ valid. */
+
+const char *gm_read_error = NULL;
+
+int gm_read(FILE *f, greymap_t **gmp) {
+ int magic[2];
+
+ /* read magic number. We ignore whitespace and comments before the
+ magic, for the benefit of concatenated files in P1-P3 format.
+ Multiple P1-P3 images in a single file are not formally allowed
+ by the PNM standard, but there is no harm in being lenient. */
+
+ magic[0] = fgetc_ws(f);
+ if (magic[0] == EOF) {
+ /* files which contain only comments and whitespace count as "empty" */
+ return -3;
+ }
+ magic[1] = fgetc(f);
+ if (magic[0] == 'P' && magic[1] >= '1' && magic[1] <= '6') {
+ return gm_readbody_pnm(f, gmp, magic[1]);
+ }
+ if (magic[0] == 'B' && magic[1] == 'M') {
+ return gm_readbody_bmp(f, gmp);
+ }
+ return -4;
+}
+
+/* ---------------------------------------------------------------------- */
+/* read PNM format */
+
+/* read PNM stream after magic number. Return values as for gm_read */
+static int gm_readbody_pnm(FILE *f, greymap_t **gmp, int magic) {
+ greymap_t *gm;
+ int x, y, i, j, b, b1, sum;
+ int bpr; /* bytes per row (as opposed to 4*gm->c) */
+ int w, h, max;
+ int realheight; /* in case of incomplete file, keeps track of how
+ many scan lines actually contain data */
+
+ gm = NULL;
+
+ w = readnum(f);
+ if (w<0) {
+ goto format_error;
+ }
+
+ h = readnum(f);
+ if (h<0) {
+ goto format_error;
+ }
+
+ /* allocate greymap */
+ gm = gm_new(w, h);
+ if (!gm) {
+ goto std_error;
+ }
+
+ realheight = 0;
+
+ switch (magic) {
+ default:
+ /* not reached */
+ goto format_error;
+
+ case '1':
+ /* read P1 format: PBM ascii */
+
+ for (y=0; y<h; y++) {
+ realheight = y+1;
+ for (x=0; x<w; x++) {
+ b = readbit(f);
+ if (b<0) {
+ goto eof;
+ }
+ GM_UPUT(gm, x, y, b ? 0 : 255);
+ }
+ }
+ break;
+
+ case '2':
+ /* read P2 format: PGM ascii */
+
+ max = readnum(f);
+ if (max<1) {
+ goto format_error;
+ }
+
+ for (y=0; y<h; y++) {
+ realheight = y+1;
+ for (x=0; x<w; x++) {
+ b = readnum(f);
+ if (b<0) {
+ goto eof;
+ }
+ GM_UPUT(gm, x, y, b*255/max);
+ }
+ }
+ break;
+
+ case '3':
+ /* read P3 format: PPM ascii */
+
+ max = readnum(f);
+ if (max<1) {
+ goto format_error;
+ }
+
+ for (y=0; y<h; y++) {
+ realheight = y+1;
+ for (x=0; x<w; x++) {
+ sum = 0;
+ for (i=0; i<3; i++) {
+ b = readnum(f);
+ if (b<0) {
+ goto eof;
+ }
+ sum += b;
+ }
+ GM_UPUT(gm, x, y, sum*(255/3)/max);
+ }
+ }
+ break;
+
+ case '4':
+ /* read P4 format: PBM raw */
+
+ b = fgetc(f); /* read single white-space character after height */
+ if (b==EOF) {
+ goto format_error;
+ }
+
+ bpr = (w+7)/8;
+
+ for (y=0; y<h; y++) {
+ realheight = y+1;
+ for (i=0; i<bpr; i++) {
+ b = fgetc(f);
+ if (b==EOF) {
+ goto eof;
+ }
+ for (j=0; j<8; j++) {
+ GM_PUT(gm, i*8+j, y, b & (0x80 >> j) ? 0 : 255);
+ }
+ }
+ }
+ break;
+
+ case '5':
+ /* read P5 format: PGM raw */
+
+ max = readnum(f);
+ if (max<1) {
+ goto format_error;
+ }
+
+ b = fgetc(f); /* read single white-space character after max */
+ if (b==EOF) {
+ goto format_error;
+ }
+
+ for (y=0; y<h; y++) {
+ realheight = y+1;
+ for (x=0; x<w; x++) {
+ b = fgetc(f);
+ if (b==EOF)
+ goto eof;
+ if (max>=256) {
+ b <<= 8;
+ b1 = fgetc(f);
+ if (b1==EOF)
+ goto eof;
+ b |= b1;
+ }
+ GM_UPUT(gm, x, y, b*255/max);
+ }
+ }
+ break;
+
+ case '6':
+ /* read P6 format: PPM raw */
+
+ max = readnum(f);
+ if (max<1) {
+ goto format_error;
+ }
+
+ b = fgetc(f); /* read single white-space character after max */
+ if (b==EOF) {
+ goto format_error;
+ }
+
+ for (y=0; y<h; y++) {
+ realheight = y+1;
+ for (x=0; x<w; x++) {
+ sum = 0;
+ for (i=0; i<3; i++) {
+ b = fgetc(f);
+ if (b==EOF) {
+ goto eof;
+ }
+ if (max>=256) {
+ b <<= 8;
+ b1 = fgetc(f);
+ if (b1==EOF)
+ goto eof;
+ b |= b1;
+ }
+ sum += b;
+ }
+ GM_UPUT(gm, x, y, sum*(255/3)/max);
+ }
+ }
+ break;
+ }
+
+ gm_flip(gm);
+ *gmp = gm;
+ return 0;
+
+ eof:
+ TRY_STD(gm_resize(gm, realheight));
+ gm_flip(gm);
+ *gmp = gm;
+ return 1;
+
+ format_error:
+ gm_free(gm);
+ if (magic == '1' || magic == '4') {
+ gm_read_error = "invalid pbm file";
+ } else if (magic == '2' || magic == '5') {
+ gm_read_error = "invalid pgm file";
+ } else {
+ gm_read_error = "invalid ppm file";
+ }
+ return -2;
+
+ std_error:
+ gm_free(gm);
+ return -1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* read BMP format */
+
+struct bmp_info_s {
+ unsigned int FileSize;
+ unsigned int reserved;
+ unsigned int DataOffset;
+ unsigned int InfoSize;
+ unsigned int w; /* width */
+ unsigned int h; /* height */
+ unsigned int Planes;
+ unsigned int bits; /* bits per sample */
+ unsigned int comp; /* compression mode */
+ unsigned int ImageSize;
+ unsigned int XpixelsPerM;
+ unsigned int YpixelsPerM;
+ unsigned int ncolors; /* number of colors in palette */
+ unsigned int ColorsImportant;
+ unsigned int RedMask;
+ unsigned int GreenMask;
+ unsigned int BlueMask;
+ unsigned int AlphaMask;
+ unsigned int ctbits; /* sample size for color table */
+ int topdown; /* top-down mode? */
+};
+typedef struct bmp_info_s bmp_info_t;
+
+/* auxiliary */
+
+static int bmp_count = 0; /* counter for byte padding */
+static int bmp_pos = 0; /* counter from start of BMP data */
+
+/* read n-byte little-endian integer. Return 1 on EOF or error, else
+ 0. Assume n<=4. */
+static int bmp_readint(FILE *f, int n, unsigned int *p) {
+ int i;
+ unsigned int sum = 0;
+ int b;
+
+ for (i=0; i<n; i++) {
+ b = fgetc(f);
+ if (b==EOF) {
+ return 1;
+ }
+ sum += (unsigned)b << (8*i);
+ }
+ bmp_count += n;
+ bmp_pos += n;
+ *p = sum;
+ return 0;
+}
+
+/* reset padding boundary */
+static void bmp_pad_reset(void) {
+ bmp_count = 0;
+}
+
+/* read padding bytes to 4-byte boundary. Return 1 on EOF or error,
+ else 0. */
+static int bmp_pad(FILE *f) {
+ int c, i, b;
+
+ c = (-bmp_count) & 3;
+ for (i=0; i<c; i++) {
+ b = fgetc(f);
+ if (b==EOF) {
+ return 1;
+ }
+ }
+ bmp_pos += c;
+ bmp_count = 0;
+ return 0;
+}
+
+/* forward to the new file position. Return 1 on EOF or error, else 0 */
+static int bmp_forward(FILE *f, int pos) {
+ int b;
+
+ while (bmp_pos < pos) {
+ b = fgetc(f);
+ if (b==EOF) {
+ return 1;
+ }
+ bmp_pos++;
+ bmp_count++;
+ }
+ return 0;
+}
+
+/* safe colortable access */
+#define COLTABLE(c) ((c) < bmpinfo.ncolors ? coltable[(c)] : 0)
+
+/* read BMP stream after magic number. Return values as for gm_read.
+ We choose to be as permissive as possible, since there are many
+ programs out there which produce BMP. For instance, ppmtobmp can
+ produce codings with anywhere from 1-8 or 24 bits per sample,
+ although most specifications only allow 1,4,8,24,32. We can also
+ read both the old and new OS/2 BMP formats in addition to the
+ Windows BMP format. */
+static int gm_readbody_bmp(FILE *f, greymap_t **gmp) {
+ bmp_info_t bmpinfo;
+ int *coltable;
+ unsigned int b, c;
+ unsigned int i, j;
+ greymap_t *gm;
+ unsigned int x, y;
+ int col[2];
+ unsigned int bitbuf;
+ unsigned int n;
+ unsigned int redshift, greenshift, blueshift;
+ int realheight; /* in case of incomplete file, keeps track of how
+ many scan lines actually contain data */
+
+ gm_read_error = NULL;
+ gm = NULL;
+ coltable = NULL;
+
+ bmp_pos = 2; /* set file position */
+
+ /* file header (minus magic number) */
+ TRY(bmp_readint(f, 4, &bmpinfo.FileSize));
+ TRY(bmp_readint(f, 4, &bmpinfo.reserved));
+ TRY(bmp_readint(f, 4, &bmpinfo.DataOffset));
+
+ /* info header */
+ TRY(bmp_readint(f, 4, &bmpinfo.InfoSize));
+ if (bmpinfo.InfoSize == 40 || bmpinfo.InfoSize == 64
+ || bmpinfo.InfoSize == 108 || bmpinfo.InfoSize == 124) {
+ /* Windows or new OS/2 format */
+ bmpinfo.ctbits = 32; /* sample size in color table */
+ TRY(bmp_readint(f, 4, &bmpinfo.w));
+ TRY(bmp_readint(f, 4, &bmpinfo.h));
+ TRY(bmp_readint(f, 2, &bmpinfo.Planes));
+ TRY(bmp_readint(f, 2, &bmpinfo.bits));
+ TRY(bmp_readint(f, 4, &bmpinfo.comp));
+ TRY(bmp_readint(f, 4, &bmpinfo.ImageSize));
+ TRY(bmp_readint(f, 4, &bmpinfo.XpixelsPerM));
+ TRY(bmp_readint(f, 4, &bmpinfo.YpixelsPerM));
+ TRY(bmp_readint(f, 4, &bmpinfo.ncolors));
+ TRY(bmp_readint(f, 4, &bmpinfo.ColorsImportant));
+ if (bmpinfo.InfoSize >= 108) { /* V4 and V5 bitmaps */
+ TRY(bmp_readint(f, 4, &bmpinfo.RedMask));
+ TRY(bmp_readint(f, 4, &bmpinfo.GreenMask));
+ TRY(bmp_readint(f, 4, &bmpinfo.BlueMask));
+ TRY(bmp_readint(f, 4, &bmpinfo.AlphaMask));
+ }
+ if (bmpinfo.w > 0x7fffffff) {
+ goto format_error;
+ }
+ if (bmpinfo.h > 0x7fffffff) {
+ bmpinfo.h = (-bmpinfo.h) & 0xffffffff;
+ bmpinfo.topdown = 1;
+ } else {
+ bmpinfo.topdown = 0;
+ }
+ if (bmpinfo.h > 0x7fffffff) {
+ goto format_error;
+ }
+ } else if (bmpinfo.InfoSize == 12) {
+ /* old OS/2 format */
+ bmpinfo.ctbits = 24; /* sample size in color table */
+ TRY(bmp_readint(f, 2, &bmpinfo.w));
+ TRY(bmp_readint(f, 2, &bmpinfo.h));
+ TRY(bmp_readint(f, 2, &bmpinfo.Planes));
+ TRY(bmp_readint(f, 2, &bmpinfo.bits));
+ bmpinfo.comp = 0;
+ bmpinfo.ncolors = 0;
+ bmpinfo.topdown = 0;
+ } else {
+ goto format_error;
+ }
+
+ if (bmpinfo.comp == 3 && bmpinfo.InfoSize < 108) {
+ /* bitfield feature is only understood with V4 and V5 format */
+ goto format_error;
+ }
+
+ if (bmpinfo.comp > 3 || bmpinfo.bits > 32) {
+ goto format_error;
+ }
+
+ /* forward to color table (e.g., if bmpinfo.InfoSize == 64) */
+ TRY(bmp_forward(f, 14+bmpinfo.InfoSize));
+
+ if (bmpinfo.Planes != 1) {
+ gm_read_error = "cannot handle bmp planes";
+ goto format_error; /* can't handle planes */
+ }
+
+ if (bmpinfo.ncolors == 0 && bmpinfo.bits <= 8) {
+ bmpinfo.ncolors = 1 << bmpinfo.bits;
+ }
+
+ /* color table, present only if bmpinfo.bits <= 8. */
+ if (bmpinfo.bits <= 8) {
+ coltable = (int *) calloc(bmpinfo.ncolors, sizeof(int));
+ if (!coltable) {
+ goto std_error;
+ }
+ /* NOTE: since we are reading a greymap, we can immediately convert
+ the color table entries to grey values. */
+ for (i=0; i<bmpinfo.ncolors; i++) {
+ TRY(bmp_readint(f, bmpinfo.ctbits/8, &c));
+ c = ((c>>16) & 0xff) + ((c>>8) & 0xff) + (c & 0xff);
+ coltable[i] = c/3;
+ }
+ }
+
+ /* forward to data */
+ if (bmpinfo.InfoSize != 12) { /* not old OS/2 format */
+ TRY(bmp_forward(f, bmpinfo.DataOffset));
+ }
+
+ /* allocate greymap */
+ gm = gm_new(bmpinfo.w, bmpinfo.h);
+ if (!gm) {
+ goto std_error;
+ }
+
+ realheight = 0;
+
+ switch (bmpinfo.bits + 0x100*bmpinfo.comp) {
+
+ default:
+ goto format_error;
+ break;
+
+ case 0x001: /* monochrome palette */
+
+ /* raster data */
+ for (y=0; y<bmpinfo.h; y++) {
+ realheight = y+1;
+ bmp_pad_reset();
+ for (i=0; 8*i<bmpinfo.w; i++) {
+ TRY_EOF(bmp_readint(f, 1, &b));
+ for (j=0; j<8; j++) {
+ GM_PUT(gm, i*8+j, y, b & (0x80 >> j) ? COLTABLE(1) : COLTABLE(0));
+ }
+ }
+ TRY(bmp_pad(f));
+ }
+ break;
+
+ case 0x002: /* 2-bit to 8-bit palettes */
+ case 0x003:
+ case 0x004:
+ case 0x005:
+ case 0x006:
+ case 0x007:
+ case 0x008:
+ for (y=0; y<bmpinfo.h; y++) {
+ realheight = y+1;
+ bmp_pad_reset();
+ bitbuf = 0; /* bit buffer: bits in buffer are high-aligned */
+ n = 0; /* number of bits currently in bitbuffer */
+ for (x=0; x<bmpinfo.w; x++) {
+ if (n < bmpinfo.bits) {
+ TRY_EOF(bmp_readint(f, 1, &b));
+ bitbuf |= b << (INTBITS - 8 - n);
+ n += 8;
+ }
+ b = bitbuf >> (INTBITS - bmpinfo.bits);
+ bitbuf <<= bmpinfo.bits;
+ n -= bmpinfo.bits;
+ GM_UPUT(gm, x, y, COLTABLE(b));
+ }
+ TRY(bmp_pad(f));
+ }
+ break;
+
+ case 0x010: /* 16-bit encoding */
+ /* can't do this format because it is not well-documented and I
+ don't have any samples */
+ gm_read_error = "cannot handle bmp 16-bit coding";
+ goto format_error;
+ break;
+
+ case 0x018: /* 24-bit encoding */
+ case 0x020: /* 32-bit encoding */
+ for (y=0; y<bmpinfo.h; y++) {
+ realheight = y+1;
+ bmp_pad_reset();
+ for (x=0; x<bmpinfo.w; x++) {
+ TRY_EOF(bmp_readint(f, bmpinfo.bits/8, &c));
+ c = ((c>>16) & 0xff) + ((c>>8) & 0xff) + (c & 0xff);
+ GM_UPUT(gm, x, y, c/3);
+ }
+ TRY(bmp_pad(f));
+ }
+ break;
+
+ case 0x320: /* 32-bit encoding with bitfields */
+ redshift = lobit(bmpinfo.RedMask);
+ greenshift = lobit(bmpinfo.GreenMask);
+ blueshift = lobit(bmpinfo.BlueMask);
+
+ for (y=0; y<bmpinfo.h; y++) {
+ realheight = y+1;
+ bmp_pad_reset();
+ for (x=0; x<bmpinfo.w; x++) {
+ TRY_EOF(bmp_readint(f, bmpinfo.bits/8, &c));
+ c = ((c & bmpinfo.RedMask) >> redshift) + ((c & bmpinfo.GreenMask) >> greenshift) + ((c & bmpinfo.BlueMask) >> blueshift);
+ GM_UPUT(gm, x, y, c/3);
+ }
+ TRY(bmp_pad(f));
+ }
+ break;
+
+ case 0x204: /* 4-bit runlength compressed encoding (RLE4) */
+ x = 0;
+ y = 0;
+ while (1) {
+ TRY_EOF(bmp_readint(f, 1, &b)); /* opcode */
+ TRY_EOF(bmp_readint(f, 1, &c)); /* argument */
+ if (b>0) {
+ /* repeat count */
+ col[0] = COLTABLE((c>>4) & 0xf);
+ col[1] = COLTABLE(c & 0xf);
+ for (i=0; i<b && x<bmpinfo.w; i++) {
+ if (x>=bmpinfo.w) {
+ x=0;
+ y++;
+ }
+ if (x>=bmpinfo.w || y>=bmpinfo.h) {
+ break;
+ }
+ realheight = y+1;
+ GM_PUT(gm, x, y, col[i&1]);
+ x++;
+ }
+ } else if (c == 0) {
+ /* end of line */
+ y++;
+ x = 0;
+ } else if (c == 1) {
+ /* end of greymap */
+ break;
+ } else if (c == 2) {
+ /* "delta": skip pixels in x and y directions */
+ TRY_EOF(bmp_readint(f, 1, &b)); /* x offset */
+ TRY_EOF(bmp_readint(f, 1, &c)); /* y offset */
+ x += b;
+ y += c;
+ } else {
+ /* verbatim segment */
+ for (i=0; i<c; i++) {
+ if ((i&1)==0) {
+ TRY_EOF(bmp_readint(f, 1, &b));
+ }
+ if (x>=bmpinfo.w) {
+ x=0;
+ y++;
+ }
+ if (x>=bmpinfo.w || y>=bmpinfo.h) {
+ break;
+ }
+ realheight = y+1;
+ GM_PUT(gm, x, y, COLTABLE((b>>(4-4*(i&1))) & 0xf));
+ x++;
+ }
+ if ((c+1) & 2) {
+ /* pad to 16-bit boundary */
+ TRY_EOF(bmp_readint(f, 1, &b));
+ }
+ }
+ }
+ break;
+
+ case 0x108: /* 8-bit runlength compressed encoding (RLE8) */
+ x = 0;
+ y = 0;
+ while (1) {
+ TRY_EOF(bmp_readint(f, 1, &b)); /* opcode */
+ TRY_EOF(bmp_readint(f, 1, &c)); /* argument */
+ if (b>0) {
+ /* repeat count */
+ for (i=0; i<b; i++) {
+ if (x>=bmpinfo.w) {
+ x=0;
+ y++;
+ }
+ if (x>=bmpinfo.w || y>=bmpinfo.h) {
+ break;
+ }
+ realheight = y+1;
+ GM_PUT(gm, x, y, COLTABLE(c));
+ x++;
+ }
+ } else if (c == 0) {
+ /* end of line */
+ y++;
+ x = 0;
+ } else if (c == 1) {
+ /* end of greymap */
+ break;
+ } else if (c == 2) {
+ /* "delta": skip pixels in x and y directions */
+ TRY_EOF(bmp_readint(f, 1, &b)); /* x offset */
+ TRY_EOF(bmp_readint(f, 1, &c)); /* y offset */
+ x += b;
+ y += c;
+ } else {
+ /* verbatim segment */
+ for (i=0; i<c; i++) {
+ TRY_EOF(bmp_readint(f, 1, &b));
+ if (x>=bmpinfo.w) {
+ x=0;
+ y++;
+ }
+ if (x>=bmpinfo.w || y>=bmpinfo.h) {
+ break;
+ }
+ realheight = y+1;
+ GM_PUT(gm, x, y, COLTABLE(b));
+ x++;
+ }
+ if (c & 1) {
+ /* pad input to 16-bit boundary */
+ TRY_EOF(bmp_readint(f, 1, &b));
+ }
+ }
+ }
+ break;
+
+ } /* switch */
+
+ /* skip any potential junk after the data section, but don't
+ complain in case EOF is encountered */
+ bmp_forward(f, bmpinfo.FileSize);
+
+ free(coltable);
+ if (bmpinfo.topdown) {
+ gm_flip(gm);
+ }
+ *gmp = gm;
+ return 0;
+
+ eof:
+ TRY_STD(gm_resize(gm, realheight));
+ free(coltable);
+ if (bmpinfo.topdown) {
+ gm_flip(gm);
+ }
+ *gmp = gm;
+ return 1;
+
+ format_error:
+ try_error:
+ free(coltable);
+ gm_free(gm);
+ if (!gm_read_error) {
+ gm_read_error = "invalid bmp file";
+ }
+ return -2;
+
+ std_error:
+ free(coltable);
+ gm_free(gm);
+ return -1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* write a pgm stream, either P2 or (if raw != 0) P5 format. Include
+ one-line comment if non-NULL. Mode determines how out-of-range
+ color values are converted. Gamma is the desired gamma correction,
+ if any (set to 2.2 if the image is to look optimal on a CRT monitor,
+ 2.8 for LCD). Set to 1.0 for no gamma correction */
+
+int gm_writepgm(FILE *f, greymap_t *gm, const char *comment, int raw, int mode, double gamma) {
+ int x, y, v;
+ int gammatable[256];
+
+ /* prepare gamma correction lookup table */
+ if (gamma != 1.0) {
+ gammatable[0] = 0;
+ for (v=1; v<256; v++) {
+ gammatable[v] = (int)(255 * exp(log(v/255.0)/gamma) + 0.5);
+ }
+ } else {
+ for (v=0; v<256; v++) {
+ gammatable[v] = v;
+ }
+ }
+
+ fprintf(f, raw ? "P5\n" : "P2\n");
+ if (comment && *comment) {
+ fprintf(f, "# %s\n", comment);
+ }
+ fprintf(f, "%d %d 255\n", gm->w, gm->h);
+ for (y=gm->h-1; y>=0; y--) {
+ for (x=0; x<gm->w; x++) {
+ v = GM_UGET(gm, x, y);
+ if (mode == GM_MODE_NONZERO) {
+ if (v > 255) {
+ v = 510 - v;
+ }
+ if (v < 0) {
+ v = 0;
+ }
+ } else if (mode == GM_MODE_ODD) {
+ v = mod(v, 510);
+ if (v > 255) {
+ v = 510 - v;
+ }
+ } else if (mode == GM_MODE_POSITIVE) {
+ if (v < 0) {
+ v = 0;
+ } else if (v > 255) {
+ v = 255;
+ }
+ } else if (mode == GM_MODE_NEGATIVE) {
+ v = 510 - v;
+ if (v < 0) {
+ v = 0;
+ } else if (v > 255) {
+ v = 255;
+ }
+ }
+ v = gammatable[v];
+
+ if (raw) {
+ fputc(v, f);
+ } else {
+ fprintf(f, x == gm->w-1 ? "%d\n" : "%d ", v);
+ }
+ }
+ }
+ return 0;
+}
+
+/* ---------------------------------------------------------------------- */
+/* output - for primitive debugging purposes only! */
+
+/* print greymap to screen */
+int gm_print(FILE *f, greymap_t *gm) {
+ int x, y;
+ int xx, yy;
+ int d, t;
+ int sw, sh;
+
+ sw = gm->w < 79 ? gm->w : 79;
+ sh = gm->w < 79 ? gm->h : gm->h*sw*44/(79*gm->w);
+
+ for (yy=sh-1; yy>=0; yy--) {
+ for (xx=0; xx<sw; xx++) {
+ d=0;
+ t=0;
+ for (x=xx*gm->w/sw; x<(xx+1)*gm->w/sw; x++) {
+ for (y=yy*gm->h/sh; y<(yy+1)*gm->h/sh; y++) {
+ d += GM_GET(gm, x, y);
+ t += 256;
+ }
+ }
+ fputc("*#=- "[5*d/t], f); /* what a cute trick :) */
+ }
+ fputc('\n', f);
+ }
+ return 0;
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/greymap.h b/Build/source/libs/potrace/potrace-src/src/greymap.h
new file mode 100644
index 00000000000..619ae6c7549
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/greymap.h
@@ -0,0 +1,67 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef GREYMAP_H
+#define GREYMAP_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+
+/* type for greymap samples */
+typedef signed short int gm_sample_t;
+
+#define GM_SAMPLESIZE (sizeof(gm_sample_t))
+
+/* internal format for greymaps. Note: in this format, rows are
+ ordered from bottom to top. The pixels in each row are given from
+ left to right. */
+struct greymap_s {
+ int w; /* width, in pixels */
+ int h; /* height, in pixels */
+ int dy; /* offset between scanlines (in samples);
+ can be negative */
+ gm_sample_t *base; /* root of allocated data */
+ gm_sample_t *map; /* points to the lower left pixel */
+};
+typedef struct greymap_s greymap_t;
+
+/* macros for accessing pixel at index (x,y). Note that the origin is
+ in the *lower* left corner. U* macros omit the bounds check. */
+
+#define gm_scanline(gm, y) ((gm)->map + (ptrdiff_t)(y)*(ptrdiff_t)(gm)->dy)
+#define gm_index(gm, x, y) (gm_scanline(gm, y) + (x))
+#define gm_safe(gm, x, y) ((int)(x)>=0 && (int)(x)<(gm)->w && (int)(y)>=0 && (int)(y)<(gm)->h)
+#define gm_bound(x, m) ((x)<0 ? 0 : (x)>=(m) ? (m)-1 : (x))
+#define GM_UGET(gm, x, y) (*gm_index(gm, x, y))
+#define GM_UINC(gm, x, y, b) (*gm_index(gm, x, y) += (gm_sample_t)(b))
+#define GM_UINV(gm, x, y) (*gm_index(gm, x, y) = 255 - *gm_index(gm, x, y))
+#define GM_UPUT(gm, x, y, b) (*gm_index(gm, x, y) = (gm_sample_t)(b))
+#define GM_GET(gm, x, y) (gm_safe(gm, x, y) ? GM_UGET(gm, x, y) : 0)
+#define GM_INC(gm, x, y, b) (gm_safe(gm, x, y) ? GM_UINC(gm, x, y, b) : 0)
+#define GM_INV(gm, x, y) (gm_safe(gm, x, y) ? GM_UINV(gm, x, y) : 0)
+#define GM_PUT(gm, x, y, b) (gm_safe(gm, x, y) ? GM_UPUT(gm, x, y, b) : 0)
+#define GM_BGET(gm, x, y) ((gm)->w == 0 || (gm)->h == 0 ? 0 : GM_UGET(gm, gm_bound(x, (gm)->w), gm_bound(y, (gm)->h)))
+
+/* modes for cutting off out-of-range values. The following names
+ refer to winding numbers. I.e., make a pixel black if winding
+ number is nonzero, odd, or positive, respectively. We assume that 0
+ winding number corresponds to white (255). */
+#define GM_MODE_NONZERO 1
+#define GM_MODE_ODD 2
+#define GM_MODE_POSITIVE 3
+#define GM_MODE_NEGATIVE 4
+
+extern const char *gm_read_error;
+
+greymap_t *gm_new(int w, int h);
+greymap_t *gm_dup(greymap_t *gm);
+void gm_free(greymap_t *gm);
+void gm_clear(greymap_t *gm, int b);
+int gm_read(FILE *f, greymap_t **gmp);
+int gm_writepgm(FILE *f, greymap_t *gm, const char *comment, int raw, int mode, double gamma);
+int gm_print(FILE *f, greymap_t *gm);
+
+#endif /* GREYMAP_H */
diff --git a/Build/source/libs/potrace/potrace-src/src/include/getopt/getopt.h b/Build/source/libs/potrace/potrace-src/src/include/getopt/getopt.h
new file mode 100644
index 00000000000..20daef6168b
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/include/getopt/getopt.h
@@ -0,0 +1,180 @@
+/* Declarations for getopt.
+ Copyright (C) 1989,90,91,92,93,94,96,97,98,99 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#ifndef _GETOPT_H
+
+#ifndef __need_getopt
+# define _GETOPT_H 1
+#endif
+
+/* If __GNU_LIBRARY__ is not already defined, either we are being used
+ standalone, or this is the first header included in the source file.
+ If we are being used with glibc, we need to include <features.h>, but
+ that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
+ not defined, include <ctype.h>, which will pull in <features.h> for us
+ if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
+ doesn't flood the namespace with stuff the way some other headers do.) */
+#if !defined __GNU_LIBRARY__
+# include <ctype.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* For communication from `getopt' to the caller.
+ When `getopt' finds an option that takes an argument,
+ the argument value is returned here.
+ Also, when `ordering' is RETURN_IN_ORDER,
+ each non-option ARGV-element is returned here. */
+
+extern char *optarg;
+
+/* Index in ARGV of the next element to be scanned.
+ This is used for communication to and from the caller
+ and for communication between successive calls to `getopt'.
+
+ On entry to `getopt', zero means this is the first call; initialize.
+
+ When `getopt' returns -1, this is the index of the first of the
+ non-option elements that the caller should itself scan.
+
+ Otherwise, `optind' communicates from one call to the next
+ how much of ARGV has been scanned so far. */
+
+extern int optind;
+
+/* Callers store zero here to inhibit the error message `getopt' prints
+ for unrecognized options. */
+
+extern int opterr;
+
+/* Set to an option character which was unrecognized. */
+
+extern int optopt;
+
+#ifndef __need_getopt
+/* Describe the long-named options requested by the application.
+ The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
+ of `struct option' terminated by an element containing a name which is
+ zero.
+
+ The field `has_arg' is:
+ no_argument (or 0) if the option does not take an argument,
+ required_argument (or 1) if the option requires an argument,
+ optional_argument (or 2) if the option takes an optional argument.
+
+ If the field `flag' is not NULL, it points to a variable that is set
+ to the value given in the field `val' when the option is found, but
+ left unchanged if the option is not found.
+
+ To have a long-named option do something other than set an `int' to
+ a compiled-in constant, such as set a value from `optarg', set the
+ option's `flag' field to zero and its `val' field to a nonzero
+ value (the equivalent single-letter option character, if there is
+ one). For long options that have a zero `flag' field, `getopt'
+ returns the contents of the `val' field. */
+
+struct option
+{
+# if defined __STDC__ && __STDC__
+ const char *name;
+# else
+ char *name;
+# endif
+ /* has_arg can't be an enum because some compilers complain about
+ type mismatches in all the code that assumes it is an int. */
+ int has_arg;
+ int *flag;
+ int val;
+};
+
+/* Names for the values of the `has_arg' field of `struct option'. */
+
+# define no_argument 0
+# define required_argument 1
+# define optional_argument 2
+#endif /* need getopt */
+
+
+/* Get definitions and prototypes for functions to process the
+ arguments in ARGV (ARGC of them, minus the program name) for
+ options given in OPTS.
+
+ Return the option character from OPTS just read. Return -1 when
+ there are no more options. For unrecognized options, or options
+ missing arguments, `optopt' is set to the option letter, and '?' is
+ returned.
+
+ The OPTS string is a list of characters which are recognized option
+ letters, optionally followed by colons, specifying that that letter
+ takes an argument, to be placed in `optarg'.
+
+ If a letter in OPTS is followed by two colons, its argument is
+ optional. This behavior is specific to the GNU `getopt'.
+
+ The argument `--' causes premature termination of argument
+ scanning, explicitly telling `getopt' that there are no more
+ options.
+
+ If OPTS begins with `--', then non-option arguments are treated as
+ arguments to the option '\0'. This behavior is specific to the GNU
+ `getopt'. */
+
+#if defined __STDC__ && __STDC__
+# ifdef __GNU_LIBRARY__
+/* Many other libraries have conflicting prototypes for getopt, with
+ differences in the consts, in stdlib.h. To avoid compilation
+ errors, only prototype getopt for the GNU C library. */
+extern int getopt (int argc, char *const *argv, const char *shortopts);
+# else /* not __GNU_LIBRARY__ */
+extern int getopt ();
+# endif /* __GNU_LIBRARY__ */
+
+# ifndef __need_getopt
+extern int getopt_long (int argc, char *const *argv, const char *shortopts,
+ const struct option *longopts, int *longind);
+extern int getopt_long_only (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind);
+
+/* Internal only. Users should not call this directly. */
+extern int _getopt_internal (int argc, char *const *argv,
+ const char *shortopts,
+ const struct option *longopts, int *longind,
+ int long_only);
+# endif
+#else /* not __STDC__ */
+extern int getopt ();
+# ifndef __need_getopt
+extern int getopt_long ();
+extern int getopt_long_only ();
+
+extern int _getopt_internal ();
+# endif
+#endif /* __STDC__ */
+
+#ifdef __cplusplus
+}
+#endif
+
+/* Make sure we later can get all the definitions and declarations. */
+#undef __need_getopt
+
+#endif /* getopt.h */
diff --git a/Build/source/libs/potrace/potrace-src/src/libpotrace-export.sym b/Build/source/libs/potrace/potrace-src/src/libpotrace-export.sym
new file mode 100644
index 00000000000..74d55c87482
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/libpotrace-export.sym
@@ -0,0 +1,5 @@
+potrace_state_free
+potrace_param_default
+potrace_trace
+potrace_param_free
+potrace_version
diff --git a/Build/source/libs/potrace/potrace-src/src/lists.h b/Build/source/libs/potrace/potrace-src/src/lists.h
new file mode 100644
index 00000000000..507cf15bdfb
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/lists.h
@@ -0,0 +1,285 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef _PS_LISTS_H
+#define _PS_LISTS_H
+
+/* here we define some general list macros. Because they are macros,
+ they should work on any datatype with a "->next" component. Some of
+ them use a "hook". If elt and list are of type t* then hook is of
+ type t**. A hook stands for an insertion point in the list, i.e.,
+ either before the first element, or between two elements, or after
+ the last element. If an operation "sets the hook" for an element,
+ then the hook is set to just before the element. One can insert
+ something at a hook. One can also unlink at a hook: this means,
+ unlink the element just after the hook. By "to unlink", we mean the
+ element is removed from the list, but not deleted. Thus, it and its
+ components still need to be freed. */
+
+/* Note: these macros are somewhat experimental. Only the ones that
+ are actually *used* have been tested. So be careful to test any
+ that you use. Looking at the output of the preprocessor, "gcc -E"
+ (possibly piped though "indent"), might help too. Also: these
+ macros define some internal (local) variables that start with
+ "_". */
+
+/* we enclose macro definitions whose body consists of more than one
+ statement in MACRO_BEGIN and MACRO_END, rather than '{' and '}'. The
+ reason is that we want to be able to use the macro in a context
+ such as "if (...) macro(...); else ...". If we didn't use this obscure
+ trick, we'd have to omit the ";" in such cases. */
+
+#define MACRO_BEGIN do {
+#define MACRO_END } while (0)
+
+/* ---------------------------------------------------------------------- */
+/* macros for singly-linked lists */
+
+/* traverse list. At the end, elt is set to NULL. */
+#define list_forall(elt, list) for (elt=list; elt!=NULL; elt=elt->next)
+
+/* set elt to the first element of list satisfying boolean condition
+ c, or NULL if not found */
+#define list_find(elt, list, c) \
+ MACRO_BEGIN list_forall(elt, list) if (c) break; MACRO_END
+
+/* like forall, except also set hook for elt. */
+#define list_forall2(elt, list, hook) \
+ for (elt=list, hook=&list; elt!=NULL; hook=&elt->next, elt=elt->next)
+
+/* same as list_find, except also set hook for elt. */
+#define list_find2(elt, list, c, hook) \
+ MACRO_BEGIN list_forall2(elt, list, hook) if (c) break; MACRO_END
+
+/* same, except only use hook. */
+#define _list_forall_hook(list, hook) \
+ for (hook=&list; *hook!=NULL; hook=&(*hook)->next)
+
+/* same, except only use hook. Note: c may only refer to *hook, not elt. */
+#define _list_find_hook(list, c, hook) \
+ MACRO_BEGIN _list_forall_hook(list, hook) if (c) break; MACRO_END
+
+/* insert element after hook */
+#define list_insert_athook(elt, hook) \
+ MACRO_BEGIN elt->next = *hook; *hook = elt; MACRO_END
+
+/* insert element before hook */
+#define list_insert_beforehook(elt, hook) \
+ MACRO_BEGIN elt->next = *hook; *hook = elt; hook=&elt->next; MACRO_END
+
+/* unlink element after hook, let elt be unlinked element, or NULL.
+ hook remains. */
+#define list_unlink_athook(list, elt, hook) \
+ MACRO_BEGIN \
+ elt = hook ? *hook : NULL; if (elt) { *hook = elt->next; elt->next = NULL; }\
+ MACRO_END
+
+/* unlink the specific element, if it is in the list. Otherwise, set
+ elt to NULL */
+#define list_unlink(listtype, list, elt) \
+ MACRO_BEGIN \
+ listtype **_hook; \
+ _list_find_hook(list, *_hook==elt, _hook); \
+ list_unlink_athook(list, elt, _hook); \
+ MACRO_END
+
+/* prepend elt to list */
+#define list_prepend(list, elt) \
+ MACRO_BEGIN elt->next = list; list = elt; MACRO_END
+
+/* append elt to list. */
+#define list_append(listtype, list, elt) \
+ MACRO_BEGIN \
+ listtype **_hook; \
+ _list_forall_hook(list, _hook) {} \
+ list_insert_athook(elt, _hook); \
+ MACRO_END
+
+/* unlink the first element that satisfies the condition. */
+#define list_unlink_cond(listtype, list, elt, c) \
+ MACRO_BEGIN \
+ listtype **_hook; \
+ list_find2(elt, list, c, _hook); \
+ list_unlink_athook(list, elt, _hook); \
+ MACRO_END
+
+/* let elt be the nth element of the list, starting to count from 0.
+ Return NULL if out of bounds. */
+#define list_nth(elt, list, n) \
+ MACRO_BEGIN \
+ int _x; /* only evaluate n once */ \
+ for (_x=(n), elt=list; _x && elt; _x--, elt=elt->next) {} \
+ MACRO_END
+
+/* let elt be the nth element of the list, starting to count from 0.
+ Return NULL if out of bounds. */
+#define list_nth_hook(elt, list, n, hook) \
+ MACRO_BEGIN \
+ int _x; /* only evaluate n once */ \
+ for (_x=(n), elt=list, hook=&list; _x && elt; _x--, hook=&elt->next, elt=elt->next) {} \
+ MACRO_END
+
+/* set n to the length of the list */
+#define list_length(listtype, list, n) \
+ MACRO_BEGIN \
+ listtype *_elt; \
+ n=0; \
+ list_forall(_elt, list) \
+ n++; \
+ MACRO_END
+
+/* set n to the index of the first element satisfying cond, or -1 if
+ none found. Also set elt to the element, or NULL if none found. */
+#define list_index(list, n, elt, c) \
+ MACRO_BEGIN \
+ n=0; \
+ list_forall(elt, list) { \
+ if (c) break; \
+ n++; \
+ } \
+ if (!elt) \
+ n=-1; \
+ MACRO_END
+
+/* set n to the number of elements in the list that satisfy condition c */
+#define list_count(list, n, elt, c) \
+ MACRO_BEGIN \
+ n=0; \
+ list_forall(elt, list) { \
+ if (c) n++; \
+ } \
+ MACRO_END
+
+/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
+#define list_forall_unlink(elt, list) \
+ for (elt=list; elt ? (list=elt->next, elt->next=NULL), 1 : 0; elt=list)
+
+/* reverse a list (efficient) */
+#define list_reverse(listtype, list) \
+ MACRO_BEGIN \
+ listtype *_list1=NULL, *elt; \
+ list_forall_unlink(elt, list) \
+ list_prepend(_list1, elt); \
+ list = _list1; \
+ MACRO_END
+
+/* insert the element ELT just before the first element TMP of the
+ list for which COND holds. Here COND must be a condition of ELT and
+ TMP. Typical usage is to insert an element into an ordered list:
+ for instance, list_insert_ordered(listtype, list, elt, tmp,
+ elt->size <= tmp->size). Note: if we give a "less than or equal"
+ condition, the new element will be inserted just before a sequence
+ of equal elements. If we give a "less than" condition, the new
+ element will be inserted just after a list of equal elements.
+ Note: it is much more efficient to construct a list with
+ list_prepend and then order it with list_merge_sort, than to
+ construct it with list_insert_ordered. */
+#define list_insert_ordered(listtype, list, elt, tmp, cond) \
+ MACRO_BEGIN \
+ listtype **_hook; \
+ _list_find_hook(list, (tmp=*_hook, (cond)), _hook); \
+ list_insert_athook(elt, _hook); \
+ MACRO_END
+
+/* sort the given list, according to the comparison condition.
+ Typical usage is list_sort(listtype, list, a, b, a->size <
+ b->size). Note: if we give "less than or equal" condition, each
+ segment of equal elements will be reversed in order. If we give a
+ "less than" condition, each segment of equal elements will retain
+ the original order. The latter is slower but sometimes
+ prettier. Average running time: n*n/2. */
+#define list_sort(listtype, list, a, b, cond) \
+ MACRO_BEGIN \
+ listtype *_newlist=NULL; \
+ list_forall_unlink(a, list) \
+ list_insert_ordered(listtype, _newlist, a, b, cond); \
+ list = _newlist; \
+ MACRO_END
+
+/* a much faster sort algorithm (merge sort, n log n worst case). It
+ is required that the list type has an additional, unused next1
+ component. Note there is no curious reversal of order of equal
+ elements as for list_sort. */
+
+#define list_mergesort(listtype, list, a, b, cond) \
+ MACRO_BEGIN \
+ listtype *_elt, **_hook1; \
+ \
+ for (_elt=list; _elt; _elt=_elt->next1) { \
+ _elt->next1 = _elt->next; \
+ _elt->next = NULL; \
+ } \
+ do { \
+ _hook1 = &(list); \
+ while ((a = *_hook1) != NULL && (b = a->next1) != NULL ) { \
+ _elt = b->next1; \
+ _list_merge_cond(listtype, a, b, cond, *_hook1); \
+ _hook1 = &((*_hook1)->next1); \
+ *_hook1 = _elt; \
+ } \
+ } while (_hook1 != &(list)); \
+ MACRO_END
+
+/* merge two sorted lists. Store result at &result */
+#define _list_merge_cond(listtype, a, b, cond, result) \
+ MACRO_BEGIN \
+ listtype **_hook; \
+ _hook = &(result); \
+ while (1) { \
+ if (a==NULL) { \
+ *_hook = b; \
+ break; \
+ } else if (b==NULL) { \
+ *_hook = a; \
+ break; \
+ } else if (cond) { \
+ *_hook = a; \
+ _hook = &(a->next); \
+ a = a->next; \
+ } else { \
+ *_hook = b; \
+ _hook = &(b->next); \
+ b = b->next; \
+ } \
+ } \
+ MACRO_END
+
+/* ---------------------------------------------------------------------- */
+/* macros for doubly-linked lists */
+
+#define dlist_append(head, end, elt) \
+ MACRO_BEGIN \
+ elt->prev = end; \
+ elt->next = NULL; \
+ if (end) { \
+ end->next = elt; \
+ } else { \
+ head = elt; \
+ } \
+ end = elt; \
+ MACRO_END
+
+/* let elt be each element of the list, unlinked. At the end, set list=NULL. */
+#define dlist_forall_unlink(elt, head, end) \
+ for (elt=head; elt ? (head=elt->next, elt->next=NULL, elt->prev=NULL), 1 : (end=NULL, 0); elt=head)
+
+/* unlink the first element of the list */
+#define dlist_unlink_first(head, end, elt) \
+ MACRO_BEGIN \
+ elt = head; \
+ if (head) { \
+ head = head->next; \
+ if (head) { \
+ head->prev = NULL; \
+ } else { \
+ end = NULL; \
+ } \
+ elt->prev = NULL; \
+ elt->next = NULL; \
+ } \
+ MACRO_END
+
+#endif /* _PS_LISTS_H */
+
diff --git a/Build/source/libs/potrace/potrace-src/src/lzw.c b/Build/source/libs/potrace/potrace-src/src/lzw.c
new file mode 100644
index 00000000000..2c90d6b2d76
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/lzw.c
@@ -0,0 +1,415 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+/* code for adaptive LZW compression, as used in PostScript. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#include "lists.h"
+#include "bitops.h"
+#include "lzw.h"
+
+/* ---------------------------------------------------------------------- */
+/* compression state specification */
+
+/* The compression algorithm follows the following specification,
+ expressed as a state machine. A state is a triple {s,d,n}, where s
+ is a string of input symbols, d is a dictionary, which is a
+ function from strings to output symbols, and n is the dictionary
+ size, or equivalently, the next unused output symbol. There are
+ also special states init and stop. emit[b, code] is a function
+ which emits the code 'code' as a b-bit value into the output
+ bitstream. hibit(n) returns the least number of binary digits
+ required to represent n.
+
+ init ---> {[], newdict, 258}
+
+ where [] is the empty string, and newdict maps each of the 256
+ singleton strings to itself. (Note that there are two special
+ output symbols 256 and 257, so that the next available one is
+ 258). Note: hibit(258)=9.
+
+ {[], d, n} (input c) ---> (emit[hibit(n), 256]) {c, d, n}
+
+ {s,d,n} (input c) ---> {s*c,d,n}
+
+ if s!=[], s*c is in the domain of d. Here s*c is the strings s
+ extended by the character c.
+
+ {s,d,n} (input c) ---> (emit[hibit(n), d(s)]) {c,d',n+1}
+
+ if s!=[], s*c is not in the domain of d, and hibit(n+2) <= 12.
+ Here d'=d+{s*c->n}.
+
+ {s,d,n} (input c) --->
+ (emit[hibit(n), d(s)]) (emit[hibit(n+1), 256]) {c, newdict, 258}
+
+ if s!=[], s*c is not in the domain of d, and hibit(n+2) > 12.
+
+ {s,d,n} (input EOD) ---> (emit[hibit(n), d(s)]) (emit[hibit(n+1), 257]) stop
+
+ where s != []. Here, EOD stands for end-of-data.
+
+ {[],d,n} (input EOD) ---> (emit[hibit(n), 256]) (emit[hibit(n), 257]) stop
+
+ Notes:
+
+ * Each reachable state {s,d,n} satisfies hibit(n+1) <= 12.
+ * Only codes of 12 or fewer bits are emitted.
+ * Each reachable state {s,d,n} satisfies s=[] or s is in the domain of d.
+ * The domain of d is always prefix closed (except for the empty prefix)
+ * The state machine is deterministic and non-blocking.
+
+*/
+
+
+/* ---------------------------------------------------------------------- */
+/* private state */
+
+#define BITBUF_TYPE unsigned int
+
+/* the dictionary is implemented as a tree of strings under the prefix
+ order. The tree is in turns represented as a linked list of
+ lzw_dict_t structures, with "children" pointing to a node's first
+ child, and "next" pointing to a node's next sibling. As an
+ optimization, the top-level nodes (singleton strings) are
+ implemented lazily, i.e., the corresponding entry is not actually
+ created until it is accessed. */
+
+struct lzw_dict_s {
+ char c; /* last character of string represented by this entry */
+ unsigned int code; /* code for the string represented by this entry */
+ int freq; /* how often searched? For optimization only */
+ struct lzw_dict_s *children; /* list of sub-entries */
+ struct lzw_dict_s *next; /* for making a linked list */
+};
+typedef struct lzw_dict_s lzw_dict_t;
+
+/* A state {s,d,n} is represented by the "dictionary state" part of
+ the lzw_state_t structure. Here, s is a pointer directly to the node
+ of the dictionary structure corresponding to the string s, or NULL
+ if s=[]. Further, the lzw_state_t structure contains a buffer of
+ pending output bits, and a flag indicating whether the EOD (end of
+ data) has been reached in the input. */
+
+struct lzw_state_s {
+ /* dictionary state */
+ int n; /* current size of the dictionary */
+ lzw_dict_t *d; /* pointer to dictionary */
+ lzw_dict_t *s; /* pointer to current string, or NULL at beginning */
+
+ /* buffers for pending output */
+ BITBUF_TYPE buf; /* bits scheduled for output - left aligned, 0 padded */
+ int bufsize; /* number of bits scheduled for output. */
+ int eod; /* flush buffer? */
+};
+typedef struct lzw_state_s lzw_state_t;
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary functions which operate on dictionary states */
+
+/* recursively free an lzw_dict_t object */
+static void lzw_free_dict(lzw_dict_t *s) {
+ lzw_dict_t *e;
+
+ list_forall_unlink(e, s) {
+ lzw_free_dict(e->children);
+ free(e);
+ }
+}
+
+/* re-initialize the lzw state's dictionary state to "newdict",
+ freeing any old dictionary. */
+static void lzw_clear_table(lzw_state_t *st) {
+
+ lzw_free_dict(st->d);
+ st->d = NULL;
+ st->n = 258;
+ st->s = NULL;
+}
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary functions for reading/writing the bit buffer */
+
+/* write the code to the bit buffer. Precondition st->bufsize <= 7.
+ Note: this does not change the dictionary state; in particular,
+ n must be updated between consecutive calls. */
+static inline void lzw_emit(unsigned int code, lzw_state_t *st) {
+ BITBUF_TYPE mask;
+ int bits = hibit(st->n);
+
+ /* fill bit buffer */
+ mask = (1 << bits) - 1;
+ code &= mask;
+
+ st->buf |= code << (8*sizeof(BITBUF_TYPE) - st->bufsize - bits);
+ st->bufsize += bits;
+}
+
+/* transfer one byte from bit buffer to output. Precondition:
+ s->avail_out > 0. */
+static inline void lzw_read_bitbuf(lzw_stream_t *s) {
+ int ch;
+ lzw_state_t *st = (lzw_state_t *)s->internal;
+
+ ch = st->buf >> (8*sizeof(BITBUF_TYPE)-8);
+ st->buf <<= 8;
+ st->bufsize -= 8;
+
+ s->next_out[0] = ch;
+ s->next_out++;
+ s->avail_out--;
+}
+
+/* ---------------------------------------------------------------------- */
+/* The following functions implement the state machine. */
+
+/* perform state transition of the state st on input character
+ ch. This updates the dictionary state and/or writes to the bit
+ buffer. Precondition: st->bufsize <= 7. Return 0 on success, or 1
+ on error with errno set. */
+static int lzw_encode_char(lzw_state_t *st, char c) {
+ lzw_dict_t *e;
+
+ /* st = {s,d,n}. hibit(n+1)<=12. */
+
+ /* {[], d, n} (input c) ---> (emit[hibit(n), 256]) {c, d, n} */
+ if (st->s == NULL) {
+ lzw_emit(256, st);
+ goto singleton; /* enter singleton state c */
+ }
+
+ /* {s,d,n} (input c) ---> {s*c,d,n} */
+ list_find(e, st->s->children, e->c == c);
+ if (e) {
+ e->freq++;
+ st->s = e;
+ return 0;
+ }
+
+ /* {s,d,n} (input c) ---> (emit[hibit(n), d(s)]) {c,d',n+1} */
+ /* {s,d,n} (input c) --->
+ (emit[hibit(n), d(s)]) (emit[hibit(n+1), 256]) {c, newdict, 258} */
+
+ lzw_emit(st->s->code, st); /* 9-12 bits */
+ if (st->n >= 4094) { /* hibit(n+2) > 12 */
+ st->n++;
+ lzw_emit(256, st);
+ goto dictfull; /* reset dictionary and enter singleton state c */
+ }
+
+ /* insert new code in dictionary, if possible */
+ e = (lzw_dict_t *)malloc(sizeof(lzw_dict_t));
+ if (!e) {
+ return 1;
+ }
+ e->c = c;
+ e->code = st->n;
+ e->freq = 1;
+ e->children = NULL;
+ list_prepend(st->s->children, e);
+ st->n++;
+ goto singleton; /* enter singleton state c */
+
+ dictfull: /* reset dictionary and enter singleton state c */
+ lzw_clear_table(st);
+ /* fall through */
+
+ singleton: /* enter singleton state c */
+ list_find(e, st->d, e->c == c);
+ if (!e) { /* not found: lazily add it */
+ e = (lzw_dict_t *)malloc(sizeof(lzw_dict_t));
+ if (!e) {
+ return 1;
+ }
+ e->c = c;
+ e->code = (unsigned char)c;
+ e->freq = 0;
+ e->children = NULL;
+ list_prepend(st->d, e);
+ }
+ e->freq++;
+ st->s = e;
+ return 0;
+}
+
+/* perform state transition of the state st on input EOD. The leaves
+ the dictionary state undefined and writes to the bit buffer.
+ Precondition: st->bufsize <= 7. This function must be called
+ exactly once, at the end of the stream. */
+static void lzw_encode_eod(lzw_state_t *st) {
+
+ /* {[],d,n} (input EOD) --->
+ (emit[hibit(n), 256]) (emit[hibit(n), 257]) stop */
+ if (st->s == NULL) {
+ lzw_emit(256, st); /* 9 bits */
+ st->n=258;
+ lzw_emit(257, st); /* 9 bits */
+ return;
+ }
+
+ /* {s,d,n} (input EOD) --->
+ (emit[hibit(n), code]) (emit[hibit(n+1), 257]) stop */
+
+ lzw_emit(st->s->code, st); /* 9-12 bits */
+ st->n++;
+ lzw_emit(257, st); /* 9-12 bits */
+ return;
+}
+
+/* ---------------------------------------------------------------------- */
+/* User visible functions. These implement a buffer interface. See
+ lzw.h for the API description. */
+
+lzw_stream_t *lzw_init(void) {
+ lzw_stream_t *s = NULL;
+ lzw_state_t *st = NULL;
+
+ s = (lzw_stream_t *)malloc(sizeof(lzw_stream_t));
+ if (s==NULL) {
+ goto fail;
+ }
+ st = (lzw_state_t *)malloc(sizeof(lzw_state_t));
+ if (st==NULL) {
+ goto fail;
+ }
+ st->buf = 0;
+ st->bufsize = 0;
+ st->eod = 0;
+ st->d = NULL;
+ lzw_clear_table(st);
+ s->internal = (void *) st;
+ return s;
+
+ fail:
+ free(s);
+ free(st);
+ return NULL;
+}
+
+int lzw_compress(lzw_stream_t *s, int mode) {
+ int r;
+ lzw_state_t *st = (lzw_state_t *)s->internal;
+
+ while (st->eod == 0) {
+ /* empty bit buffer */
+ while (st->bufsize > 7) {
+ if (s->avail_out == 0) {
+ return 0;
+ } else {
+ lzw_read_bitbuf(s);
+ }
+ }
+ /* fill bit buffer */
+ if (s->avail_in == 0) {
+ break;
+ } else {
+ r = lzw_encode_char(st, s->next_in[0]);
+ if (r) {
+ if (r==2) {
+ errno = EINVAL;
+ }
+ return 1;
+ }
+ s->next_in++;
+ s->avail_in--;
+ }
+ }
+
+ if (mode==LZW_EOD && st->eod == 0) {
+ st->eod = 1;
+ lzw_encode_eod(st);
+ }
+
+ /* flush bit buffer */
+ if (st->eod) {
+ while (st->bufsize > 0) {
+ if (s->avail_out == 0) {
+ return 0;
+ } else {
+ lzw_read_bitbuf(s);
+ }
+ }
+ }
+
+ return 0;
+}
+
+void lzw_free(lzw_stream_t *s) {
+ lzw_state_t *st = (lzw_state_t *)s->internal;
+
+ lzw_free_dict(st->d);
+ free(st);
+ free(s);
+}
+
+/* ---------------------------------------------------------------------- */
+/* main function for testing and illustration purposes */
+
+#ifdef LZW_MAIN
+
+int main() {
+ lzw_stream_t *s;
+ int ch;
+ char inbuf[100];
+ char outbuf[100];
+ int i, r;
+ int mode;
+
+ s = lzw_init();
+ if (!s) {
+ goto error;
+ }
+ mode = LZW_NORMAL;
+
+ while (1) {
+ /* fill inbuf */
+ for (i=0; i<100; i++) {
+ ch = fgetc(stdin);
+ if (ch==EOF) {
+ break;
+ }
+ inbuf[i] = ch;
+ }
+ if (i<100) { /* end of input */
+ mode = LZW_EOD;
+ }
+
+ /* compress */
+ s->next_in = inbuf;
+ s->avail_in = i;
+ do {
+ s->next_out = outbuf;
+ s->avail_out = 100;
+ r = lzw_compress(s, mode);
+ if (r) {
+ goto error;
+ }
+ fwrite(outbuf, 1, 100-s->avail_out, stdout);
+ } while (s->avail_out==0);
+ if (mode == LZW_EOD) {
+ break;
+ }
+ }
+ fflush(stdout);
+ lzw_free(s);
+
+ return 0;
+
+ error:
+ fprintf(stderr, "lzw: %s\n", strerror(errno));
+ lzw_free(s);
+ return 1;
+
+}
+#endif
+
diff --git a/Build/source/libs/potrace/potrace-src/src/lzw.h b/Build/source/libs/potrace/potrace-src/src/lzw.h
new file mode 100644
index 00000000000..695a0c81023
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/lzw.h
@@ -0,0 +1,50 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#define LZW_NORMAL 0
+#define LZW_EOD 1
+
+/* user visible state */
+
+struct lzw_stream_s {
+ const char *next_in; /* pointer to next input character */
+ int avail_in; /* number of input chars available */
+ char *next_out; /* pointer to next free byte in output buffer */
+ int avail_out; /* remaining size of output buffer */
+
+ void *internal; /* internal state, not user accessible */
+};
+typedef struct lzw_stream_s lzw_stream_t;
+
+/* user visible functions */
+
+/* The interface for compression and decompression is the same. The
+ application must first call lzw_init to create and initialize a
+ compression object. Then it calls lzw_compress on this object
+ repeatedly, as follows: next_in and next_out must point to valid,
+ non-overlapping regions of memory of size at least avail_in and
+ avail_out, respectively. The lzw_compress function will read and
+ process as many input bytes as possible as long as there is room in
+ the output buffer. It will update next_in, avail_in, next_out, and
+ avail_out accordingly. Some input may be consumed without producing
+ any output, or some output may be produced without consuming any
+ input. However, the lzw_compress function makes progress in the
+ sense that, after calling this function, at least one of avail_in
+ or avail_out is guaranteed to be 0. The mode flag is normally set
+ to LZW_NORMAL. It can be set to LZW_EOD (end of data) to indicate
+ that the current input buffer represents the entire remaining input
+ data stream. When called with mode=LZW_EOD, and avail_out is
+ non-zero after the call, then the application may conclude that the
+ end of output has been reached. (However, if avail_out==0 after the
+ call, then lzw_compress should be called again with the remaining
+ input, if any). Finally, lzw_free should be called to deallocate
+ the lzw_stream. Lzw_init returns NULL on error, with errno
+ set. Lzw_compress returns 0 on success, and 1 on error with errno
+ set. EINVAL is used to indicate an internal error, which should not
+ happen. */
+
+lzw_stream_t *lzw_init(void);
+int lzw_compress(lzw_stream_t *s, int mode);
+void lzw_free(lzw_stream_t *s);
diff --git a/Build/source/libs/potrace/potrace-src/src/main.c b/Build/source/libs/potrace/potrace-src/src/main.c
new file mode 100644
index 00000000000..2785b19bb6e
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/main.c
@@ -0,0 +1,1269 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include <getopt.h>
+#include <math.h>
+
+#include "main.h"
+#include "potracelib.h"
+#include "backend_pdf.h"
+#include "backend_eps.h"
+#include "backend_pgm.h"
+#include "backend_svg.h"
+#include "backend_xfig.h"
+#include "backend_dxf.h"
+#include "backend_geojson.h"
+#include "potracelib.h"
+#include "bitmap_io.h"
+#include "bitmap.h"
+#include "platform.h"
+#include "auxiliary.h"
+#include "progress_bar.h"
+#include "trans.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#define UNDEF ((double)(1e30)) /* a value to represent "undefined" */
+
+struct info_s info;
+
+/* ---------------------------------------------------------------------- */
+/* some data structures for option processing */
+
+struct pageformat_s {
+ const char *name;
+ int w, h;
+};
+typedef struct pageformat_s pageformat_t;
+
+/* dimensions of the various page formats, in postscript points */
+static pageformat_t pageformat[] = {
+ { "a4", 595, 842 },
+ { "a3", 842, 1191 },
+ { "a5", 421, 595 },
+ { "b5", 516, 729 },
+ { "letter", 612, 792 },
+ { "legal", 612, 1008 },
+ { "tabloid", 792, 1224 },
+ { "statement", 396, 612 },
+ { "executive", 540, 720 },
+ { "folio", 612, 936 },
+ { "quarto", 610, 780 },
+ { "10x14", 720, 1008 },
+ { NULL, 0, 0 },
+};
+
+struct turnpolicy_s {
+ const char *name;
+ int n;
+};
+typedef struct turnpolicy_s turnpolicy_t;
+
+/* names of turn policies */
+static turnpolicy_t turnpolicy[] = {
+ {"black", POTRACE_TURNPOLICY_BLACK},
+ {"white", POTRACE_TURNPOLICY_WHITE},
+ {"left", POTRACE_TURNPOLICY_LEFT},
+ {"right", POTRACE_TURNPOLICY_RIGHT},
+ {"minority", POTRACE_TURNPOLICY_MINORITY},
+ {"majority", POTRACE_TURNPOLICY_MAJORITY},
+ {"random", POTRACE_TURNPOLICY_RANDOM},
+ {NULL, 0},
+};
+
+/* backends and their characteristics */
+struct backend_s {
+ const char *name; /* name of this backend */
+ const char *ext; /* file extension */
+ int fixed; /* fixed page size backend? */
+ int pixel; /* pixel-based backend? */
+ int multi; /* multi-page backend? */
+ int (*init_f)(FILE *fout); /* initialization function */
+ int (*page_f)(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo);
+ /* per-bitmap function */
+ int (*term_f)(FILE *fout); /* finalization function */
+ int opticurve; /* opticurve capable (true Bezier curves?) */
+};
+typedef struct backend_s backend_t;
+
+static backend_t backend[] = {
+ { "svg", ".svg", 0, 0, 0, NULL, page_svg, NULL, 1 },
+ { "pdf", ".pdf", 0, 0, 1, init_pdf, page_pdf, term_pdf, 1 },
+ { "pdfpage", ".pdf", 1, 0, 1, init_pdf, page_pdfpage, term_pdf, 1 },
+ { "eps", ".eps", 0, 0, 0, NULL, page_eps, NULL, 1 },
+ { "postscript", ".ps", 1, 0, 1, init_ps, page_ps, term_ps, 1 },
+ { "ps", ".ps", 1, 0, 1, init_ps, page_ps, term_ps, 1 },
+ { "dxf", ".dxf", 0, 1, 0, NULL, page_dxf, NULL, 1 },
+ { "geojson", ".json",0, 1, 0, NULL, page_geojson, NULL, 1 },
+ { "pgm", ".pgm", 0, 1, 1, NULL, page_pgm, NULL, 1 },
+ { "gimppath", ".svg", 0, 1, 0, NULL, page_gimp, NULL, 1 },
+ { "xfig", ".fig", 1, 0, 0, NULL, page_xfig, NULL, 0 },
+ { NULL, NULL, 0, 0, 0, NULL, NULL, NULL, 0 },
+};
+
+/* look up a backend by name. If found, return 0 and set *bp. If not
+ found leave *bp unchanged and return 1, or 2 on ambiguous
+ prefix. */
+static int backend_lookup(const char *name, backend_t **bp) {
+ int i;
+ int m=0; /* prefix matches */
+ backend_t *b = NULL;
+
+ for (i=0; backend[i].name; i++) {
+ if (strcasecmp(backend[i].name, name)==0) {
+ *bp = &backend[i];
+ return 0;
+ } else if (strncasecmp(backend[i].name, name, strlen(name))==0) {
+ m++;
+ b = &backend[i];
+ }
+ }
+ /* if there was no exact match, and exactly one prefix match, use that */
+ if (m==1) {
+ *bp = b;
+ return 0;
+ } else if (m) {
+ return 2;
+ } else {
+ return 1;
+ }
+}
+
+/* list all available backends by name, in a comma separated list.
+ Assume the cursor starts in column j, and break lines at length
+ linelen. Do not output any trailing punctuation. Return the column
+ the cursor is in. */
+static int backend_list(FILE *fout, int j, int linelen) {
+ int i;
+
+ for (i=0; backend[i].name; i++) {
+ if (j + (int)strlen(backend[i].name) > linelen) {
+ fprintf(fout, "\n");
+ j = 0;
+ }
+ j += fprintf(fout, "%s", backend[i].name);
+ if (backend[i+1].name) {
+ j += fprintf(fout, ", ");
+ }
+ }
+ return j;
+}
+
+/* ---------------------------------------------------------------------- */
+/* some info functions */
+
+static void license(FILE *f) {
+ fprintf(f,
+ "This program is free software; you can redistribute it and/or modify\n"
+ "it under the terms of the GNU General Public License as published by\n"
+ "the Free Software Foundation; either version 2 of the License, or\n"
+ "(at your option) any later version.\n"
+ "\n"
+ "This program is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+ "GNU General Public License for more details.\n"
+ "\n"
+ "You should have received a copy of the GNU General Public License\n"
+ "along with this program; if not, write to the Free Software Foundation\n"
+ "Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
+ );
+}
+
+static void show_defaults(FILE *f) {
+ fprintf(f, "Default unit: " DEFAULT_DIM_NAME "\n");
+ fprintf(f, "Default page size: " DEFAULT_PAPERFORMAT "\n");
+}
+
+static void usage(FILE *f) {
+ int j;
+
+ fprintf(f, "Usage: " POTRACE " [options] [filename...]\n");
+ fprintf(f, "General options:\n");
+ fprintf(f, " -h, --help - print this help message and exit\n");
+ fprintf(f, " -v, --version - print version info and exit\n");
+ fprintf(f, " -l, --license - print license info and exit\n");
+ fprintf(f, "File selection:\n");
+ fprintf(f, " <filename> - an input file\n");
+ fprintf(f, " -o, --output <filename> - write all output to this file\n");
+ fprintf(f, " -- - end of options; 0 or more input filenames follow\n");
+ fprintf(f, "Backend selection:\n");
+ fprintf(f, " -b, --backend <name> - select backend by name\n");
+ fprintf(f, " -b svg, -s, --svg - SVG backend (scalable vector graphics)\n");
+ fprintf(f, " -b pdf - PDF backend (portable document format)\n");
+ fprintf(f, " -b pdfpage - fixed page-size PDF backend\n");
+ fprintf(f, " -b eps, -e, --eps - EPS backend (encapsulated PostScript) (default)\n");
+ fprintf(f, " -b ps, -p, --postscript - PostScript backend\n");
+ fprintf(f, " -b pgm, -g, --pgm - PGM backend (portable greymap)\n");
+ fprintf(f, " -b dxf - DXF backend (drawing interchange format)\n");
+ fprintf(f, " -b geojson - GeoJSON backend\n");
+ fprintf(f, " -b gimppath - Gimppath backend (GNU Gimp)\n");
+ fprintf(f, " -b xfig - XFig backend\n");
+ fprintf(f, "Algorithm options:\n");
+ fprintf(f, " -z, --turnpolicy <policy> - how to resolve ambiguities in path decomposition\n");
+ fprintf(f, " -t, --turdsize <n> - suppress speckles of up to this size (default 2)\n");
+ fprintf(f, " -a, --alphamax <n> - corner threshold parameter (default 1)\n");
+ fprintf(f, " -n, --longcurve - turn off curve optimization\n");
+ fprintf(f, " -O, --opttolerance <n> - curve optimization tolerance (default 0.2)\n");
+ fprintf(f, " -u, --unit <n> - quantize output to 1/unit pixels (default 10)\n");
+ fprintf(f, " -d, --debug <n> - produce debugging output of type n (n=1,2,3)\n");
+ fprintf(f, "Scaling and placement options:\n");
+ fprintf(f, " -P, --pagesize <format> - page size (default is " DEFAULT_PAPERFORMAT ")\n");
+ fprintf(f, " -W, --width <dim> - width of output image\n");
+ fprintf(f, " -H, --height <dim> - height of output image\n");
+ fprintf(f, " -r, --resolution <n>[x<n>] - resolution (in dpi) (dimension-based backends)\n");
+ fprintf(f, " -x, --scale <n>[x<n>] - scaling factor (pixel-based backends)\n");
+ fprintf(f, " -S, --stretch <n> - yresolution/xresolution\n");
+ fprintf(f, " -A, --rotate <angle> - rotate counterclockwise by angle\n");
+ fprintf(f, " -M, --margin <dim> - margin\n");
+ fprintf(f, " -L, --leftmargin <dim> - left margin\n");
+ fprintf(f, " -R, --rightmargin <dim> - right margin\n");
+ fprintf(f, " -T, --topmargin <dim> - top margin\n");
+ fprintf(f, " -B, --bottommargin <dim> - bottom margin\n");
+ fprintf(f, " --tight - remove whitespace around the input image\n");
+ fprintf(f, "Color options, supported by some backends:\n");
+ fprintf(f, " -C, --color #rrggbb - set foreground color (default black)\n");
+ fprintf(f, " --fillcolor #rrggbb - set fill color (default transparent)\n");
+ fprintf(f, " --opaque - make white shapes opaque\n");
+ fprintf(f, "SVG options:\n");
+ fprintf(f, " --group - group related paths together\n");
+ fprintf(f, " --flat - whole image as a single path\n");
+ fprintf(f, "Postscript/EPS/PDF options:\n");
+ fprintf(f, " -c, --cleartext - do not compress the output\n");
+ fprintf(f, " -2, --level2 - use postscript level 2 compression (default)\n");
+#ifdef HAVE_ZLIB
+ fprintf(f, " -3, --level3 - use postscript level 3 compression\n");
+#endif
+ fprintf(f, " -q, --longcoding - do not optimize for file size\n");
+ fprintf(f, "PGM options:\n");
+ fprintf(f, " -G, --gamma <n> - gamma value for anti-aliasing (default 2.2)\n");
+ fprintf(f, "Frontend options:\n");
+ fprintf(f, " -k, --blacklevel <n> - black/white cutoff in input file (default 0.5)\n");
+ fprintf(f, " -i, --invert - invert bitmap\n");
+ fprintf(f, "Progress bar options:\n");
+ fprintf(f, " --progress - show progress bar\n");
+ fprintf(f, " --tty <mode> - progress bar rendering: vt100 or dumb\n");
+ fprintf(f, "\n");
+ fprintf(f, "Dimensions can have optional units, e.g. 6.5in, 15cm, 100pt.\n");
+ fprintf(f, "Default is " DEFAULT_DIM_NAME " (or pixels for pgm, dxf, and gimppath backends).\n");
+ fprintf(f, "Possible input file formats are: pnm (pbm, pgm, ppm), bmp.\n");
+ j = fprintf(f, "Backends are: ");
+ backend_list(f, j, 78);
+ fprintf(f, ".\n");
+}
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary functions for parameter parsing */
+
+/* parse a dimension of the kind "1.5in", "7cm", etc. Return result in
+ postscript points (=1/72 in). If endptr!=NULL, store pointer to
+ next character in *endptr in the manner of strtod(3). */
+static dim_t parse_dimension(char *s, char **endptr) {
+ char *p;
+ dim_t res;
+
+ res.x = strtod(s, &p);
+ res.d = 0;
+ if (p!=s) {
+ if (!strncasecmp(p, "in", 2)) {
+ res.d = DIM_IN;
+ p += 2;
+ } else if (!strncasecmp(p, "cm", 2)) {
+ res.d = DIM_CM;
+ p += 2;
+ } else if (!strncasecmp(p, "mm", 2)) {
+ res.d = DIM_MM;
+ p += 2;
+ } else if (!strncasecmp(p, "pt", 2)) {
+ res.d = DIM_PT;
+ p += 2;
+ }
+ }
+ if (endptr!=NULL) {
+ *endptr = p;
+ }
+ return res;
+}
+
+/* parse a pair of dimensions, such as "8.5x11in", "30mmx4cm" */
+static void parse_dimensions(char *s, char **endptr, dim_t *dxp, dim_t *dyp) {
+ char *p, *q;
+ dim_t dx, dy;
+
+ dx = parse_dimension(s, &p);
+ if (p==s) {
+ goto fail;
+ }
+ if (*p != 'x') {
+ goto fail;
+ }
+ p++;
+ dy = parse_dimension(p, &q);
+ if (q==p) {
+ goto fail;
+ }
+ if (dx.d && !dy.d) {
+ dy.d = dx.d;
+ } else if (!dx.d && dy.d) {
+ dx.d = dy.d;
+ }
+ *dxp = dx;
+ *dyp = dy;
+ if (endptr != NULL) {
+ *endptr = q;
+ }
+ return;
+
+ fail:
+ dx.x = dx.d = dy.x = dy.d = 0;
+ *dxp = dx;
+ *dyp = dy;
+ if (endptr != NULL) {
+ *endptr = s;
+ }
+ return;
+}
+
+static inline double double_of_dim(dim_t d, double def) {
+ if (d.d) {
+ return d.x * d.d;
+ } else {
+ return d.x * def;
+ }
+}
+
+static int parse_color(char *s) {
+ int i, d;
+ int col = 0;
+
+ if (s[0] != '#' || strlen(s) != 7) {
+ return -1;
+ }
+ for (i=0; i<6; i++) {
+ d = s[6-i];
+ if (d >= '0' && d <= '9') {
+ col |= (d-'0') << (4*i);
+ } else if (d >= 'a' && d <= 'f') {
+ col |= (d-'a'+10) << (4*i);
+ } else if (d >= 'A' && d <= 'F') {
+ col |= (d-'A'+10) << (4*i);
+ } else {
+ return -1;
+ }
+ }
+ return col;
+}
+
+/* ---------------------------------------------------------------------- */
+/* option processing */
+
+/* codes for options that don't have short form */
+enum {
+ OPT_TIGHT = 300,
+ OPT_FILLCOLOR,
+ OPT_OPAQUE,
+ OPT_GROUP,
+ OPT_FLAT,
+ OPT_PROGRESS,
+ OPT_TTY
+};
+
+static struct option longopts[] = {
+ {"help", 0, 0, 'h'},
+ {"version", 0, 0, 'v'},
+ {"show-defaults", 0, 0, 'V'}, /* undocumented option for compatibility */
+ {"license", 0, 0, 'l'},
+ {"width", 1, 0, 'W'},
+ {"height", 1, 0, 'H'},
+ {"resolution", 1, 0, 'r'},
+ {"scale", 1, 0, 'x'},
+ {"stretch", 1, 0, 'S'},
+ {"margin", 1, 0, 'M'},
+ {"leftmargin", 1, 0, 'L'},
+ {"rightmargin", 1, 0, 'R'},
+ {"topmargin", 1, 0, 'T'},
+ {"bottommargin", 1, 0, 'B'},
+ {"tight", 0, 0, OPT_TIGHT},
+ {"rotate", 1, 0, 'A'},
+ {"pagesize", 1, 0, 'P'},
+ {"turdsize", 1, 0, 't'},
+ {"unit", 1, 0, 'u'},
+ {"cleartext", 0, 0, 'c'},
+ {"level2", 0, 0, '2'},
+ {"level3", 0, 0, '3'},
+ {"eps", 0, 0, 'e'},
+ {"postscript", 0, 0, 'p'},
+ {"svg", 0, 0, 's'},
+ {"pgm", 0, 0, 'g'},
+ {"backend", 1, 0, 'b'},
+ {"debug", 1, 0, 'd'},
+ {"color", 1, 0, 'C'},
+ {"fillcolor", 1, 0, OPT_FILLCOLOR},
+ {"turnpolicy", 1, 0, 'z'},
+ {"gamma", 1, 0, 'G'},
+ {"longcurve", 0, 0, 'n'},
+ {"longcoding", 0, 0, 'q'},
+ {"alphamax", 1, 0, 'a'},
+ {"opttolerance", 1, 0, 'O'},
+ {"output", 1, 0, 'o'},
+ {"blacklevel", 1, 0, 'k'},
+ {"invert", 0, 0, 'i'},
+ {"opaque", 0, 0, OPT_OPAQUE},
+ {"group", 0, 0, OPT_GROUP},
+ {"flat", 0, 0, OPT_FLAT},
+ {"progress", 0, 0, OPT_PROGRESS},
+ {"tty", 1, 0, OPT_TTY},
+
+ {0, 0, 0, 0}
+};
+
+static const char *shortopts = "hvVlW:H:r:x:S:M:L:R:T:B:A:P:t:u:c23epsgb:d:C:z:G:nqa:O:o:k:i";
+
+static void dopts(int ac, char *av[]) {
+ int c;
+ char *p;
+ int i, j, r;
+ dim_t dim, dimx, dimy;
+ int matches, bestmatch;
+
+ /* defaults */
+ backend_lookup("eps", &info.backend);
+ info.debug = 0;
+ info.width_d.x = UNDEF;
+ info.height_d.x = UNDEF;
+ info.rx = UNDEF;
+ info.ry = UNDEF;
+ info.sx = UNDEF;
+ info.sy = UNDEF;
+ info.stretch = 1;
+ info.lmar_d.x = UNDEF;
+ info.rmar_d.x = UNDEF;
+ info.tmar_d.x = UNDEF;
+ info.bmar_d.x = UNDEF;
+ info.angle = 0;
+ info.paperwidth = DEFAULT_PAPERWIDTH;
+ info.paperheight = DEFAULT_PAPERHEIGHT;
+ info.tight = 0;
+ info.unit = 10;
+ info.compress = 1;
+ info.pslevel = 2;
+ info.color = 0x000000;
+ info.gamma = 2.2;
+ info.param = potrace_param_default();
+ if (!info.param) {
+ fprintf(stderr, "" POTRACE ": %s\n", strerror(errno));
+ exit(2);
+ }
+ info.longcoding = 0;
+ info.outfile = NULL;
+ info.blacklevel = 0.5;
+ info.invert = 0;
+ info.opaque = 0;
+ info.grouping = 1;
+ info.fillcolor = 0xffffff;
+ info.progress = 0;
+ info.progress_bar = DEFAULT_PROGRESS_BAR;
+
+ while ((c = getopt_long(ac, av, shortopts, longopts, NULL)) != -1) {
+ switch (c) {
+ case 'h':
+ fprintf(stdout, "" POTRACE " " VERSION ". Transforms bitmaps into vector graphics.\n\n");
+ usage(stdout);
+ exit(0);
+ break;
+ case 'v':
+ case 'V':
+ fprintf(stdout, "" POTRACE " " VERSION ". Copyright (C) 2001-2019 Peter Selinger.\n");
+ fprintf(stdout, "Library version: %s\n", potrace_version());
+ show_defaults(stdout);
+ exit(0);
+ break;
+ case 'l':
+ fprintf(stdout, "" POTRACE " " VERSION ". Copyright (C) 2001-2019 Peter Selinger.\n\n");
+ license(stdout);
+ exit(0);
+ break;
+ case 'W':
+ info.width_d = parse_dimension(optarg, &p);
+ if (*p) {
+ fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'H':
+ info.height_d = parse_dimension(optarg, &p);
+ if (*p) {
+ fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'r':
+ parse_dimensions(optarg, &p, &dimx, &dimy);
+ if (*p == 0 && dimx.d == 0 && dimy.d == 0 && dimx.x != 0.0 && dimy.x != 0.0) {
+ info.rx = dimx.x;
+ info.ry = dimy.x;
+ break;
+ }
+ dim = parse_dimension(optarg, &p);
+ if (*p == 0 && dim.d == 0 && dim.x != 0.0) {
+ info.rx = info.ry = dim.x;
+ break;
+ }
+ fprintf(stderr, "" POTRACE ": invalid resolution -- %s\n", optarg);
+ exit(1);
+ break;
+ case 'x':
+ parse_dimensions(optarg, &p, &dimx, &dimy);
+ if (*p == 0 && dimx.d == 0 && dimy.d == 0) {
+ info.sx = dimx.x;
+ info.sy = dimy.x;
+ break;
+ }
+ dim = parse_dimension(optarg, &p);
+ if (*p == 0 && dim.d == 0) {
+ info.sx = info.sy = dim.x;
+ break;
+ }
+ fprintf(stderr, "" POTRACE ": invalid scaling factor -- %s\n", optarg);
+ exit(1);
+ break;
+ case 'S':
+ info.stretch = atof(optarg);
+ break;
+ case 'M':
+ info.lmar_d = parse_dimension(optarg, &p);
+ if (*p) {
+ fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
+ exit(1);
+ }
+ info.rmar_d = info.tmar_d = info.bmar_d = info.lmar_d;
+ break;
+ case 'L':
+ info.lmar_d = parse_dimension(optarg, &p);
+ if (*p) {
+ fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'R':
+ info.rmar_d = parse_dimension(optarg, &p);
+ if (*p) {
+ fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'T':
+ info.tmar_d = parse_dimension(optarg, &p);
+ if (*p) {
+ fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'B':
+ info.bmar_d = parse_dimension(optarg, &p);
+ if (*p) {
+ fprintf(stderr, "" POTRACE ": invalid dimension -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case OPT_TIGHT:
+ info.tight = 1;
+ break;
+ case 'A':
+ info.angle = strtod(optarg, &p);
+ if (*p) {
+ fprintf(stderr, "" POTRACE ": invalid angle -- %s\n", optarg);
+ exit(1);
+ }
+ if (info.angle <= -180 || info.angle > 180) {
+ info.angle -= 360 * ceil(info.angle / 360 - 0.5);
+ }
+ break;
+ case 'P':
+ matches = 0;
+ bestmatch = 0;
+ for (i=0; pageformat[i].name!=NULL; i++) {
+ if (strcasecmp(pageformat[i].name, optarg)==0) {
+ matches = 1;
+ bestmatch = i;
+ break;
+ } else if (strncasecmp(pageformat[i].name, optarg, strlen(optarg))==0) {
+ /* don't allow partial match on "10x14" */
+ if (optarg[0] != '1') {
+ matches++;
+ bestmatch = i;
+ }
+ }
+ }
+ if (matches == 1) {
+ info.paperwidth = pageformat[bestmatch].w;
+ info.paperheight = pageformat[bestmatch].h;
+ break;
+ }
+ parse_dimensions(optarg, &p, &dimx, &dimy);
+ if (*p == 0) {
+ info.paperwidth = (int)round(double_of_dim(dimx, DEFAULT_DIM));
+ info.paperheight = (int)round(double_of_dim(dimy, DEFAULT_DIM));
+ break;
+ }
+ if (matches == 0) {
+ fprintf(stderr, "" POTRACE ": unrecognized page format -- %s\n", optarg);
+ } else {
+ fprintf(stderr, "" POTRACE ": ambiguous page format -- %s\n", optarg);
+ }
+ j = fprintf(stderr, "Use one of: ");
+ for (i=0; pageformat[i].name!=NULL; i++) {
+ if (j + strlen(pageformat[i].name) > 75) {
+ fprintf(stderr, "\n");
+ j = 0;
+ }
+ j += fprintf(stderr, "%s, ", pageformat[i].name);
+ }
+ fprintf(stderr, "or specify <dim>x<dim>.\n");
+ exit(1);
+ break;
+ case 't':
+ info.param->turdsize = atoi(optarg);
+ break;
+ case 'u':
+ info.unit = strtod(optarg, &p);
+ if (*p) {
+ fprintf(stderr, "" POTRACE ": invalid unit -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'c':
+ info.pslevel = 2;
+ info.compress = 0;
+ break;
+ case '2':
+ info.pslevel = 2;
+ info.compress = 1;
+ break;
+ case '3':
+#ifdef HAVE_ZLIB
+ info.pslevel = 3;
+ info.compress = 1;
+#else
+ fprintf(stderr, "" POTRACE ": option -3 not supported, using -2 instead.\n");
+ fflush(stderr);
+ info.pslevel = 2;
+ info.compress = 1;
+#endif
+ break;
+ case 'e':
+ backend_lookup("eps", &info.backend);
+ break;
+ case 'p':
+ backend_lookup("postscript", &info.backend);
+ break;
+ case 's':
+ backend_lookup("svg", &info.backend);
+ break;
+ case 'g':
+ backend_lookup("pgm", &info.backend);
+ break;
+ case 'b':
+ r = backend_lookup(optarg, &info.backend);
+ if (r==1 || r==2) {
+ if (r==1) {
+ fprintf(stderr, "" POTRACE ": unrecognized backend -- %s\n", optarg);
+ } else {
+ fprintf(stderr, "" POTRACE ": ambiguous backend -- %s\n", optarg);
+ }
+ j = fprintf(stderr, "Use one of: ");
+ backend_list(stderr, j, 70);
+ fprintf(stderr, ".\n");
+ exit(1);
+ }
+ break;
+ case 'd':
+ info.debug = atoi(optarg);
+ break;
+ case 'C':
+ info.color = parse_color(optarg);
+ if (info.color == -1) {
+ fprintf(stderr, "" POTRACE ": invalid color -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case OPT_FILLCOLOR:
+ info.fillcolor = parse_color(optarg);
+ if (info.fillcolor == -1) {
+ fprintf(stderr, "" POTRACE ": invalid color -- %s\n", optarg);
+ exit(1);
+ }
+ info.opaque = 1;
+ break;
+ case 'z':
+ matches = 0;
+ bestmatch = 0;
+ for (i=0; turnpolicy[i].name!=NULL; i++) {
+ if (strcasecmp(turnpolicy[i].name, optarg)==0) {
+ matches = 1;
+ bestmatch = i;
+ break;
+ } else if (strncasecmp(turnpolicy[i].name, optarg, strlen(optarg))==0) {
+ matches++;
+ bestmatch = i;
+ }
+ }
+ if (matches == 1) {
+ info.param->turnpolicy = turnpolicy[bestmatch].n;
+ break;
+ }
+ if (matches == 0) {
+ fprintf(stderr, "" POTRACE ": unrecognized turnpolicy -- %s\n", optarg);
+ } else {
+ fprintf(stderr, "" POTRACE ": ambiguous turnpolicy -- %s\n", optarg);
+ }
+ j = fprintf(stderr, "Use one of: ");
+ for (i=0; turnpolicy[i].name!=NULL; i++) {
+ if (j + strlen(turnpolicy[i].name) > 75) {
+ fprintf(stderr, "\n");
+ j = 0;
+ }
+ j += fprintf(stderr, "%s%s", turnpolicy[i].name, turnpolicy[i+1].name ? ", " : "");
+ }
+ fprintf(stderr, ".\n");
+ exit(1);
+ break;
+ case 'G':
+ info.gamma = atof(optarg);
+ break;
+ case 'n':
+ info.param->opticurve = 0;
+ break;
+ case 'q':
+ info.longcoding = 1;
+ break;
+ case 'a':
+ info.param->alphamax = strtod(optarg, &p);
+ if (*p) {
+ fprintf(stderr, "" POTRACE ": invalid alphamax -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'O':
+ info.param->opttolerance = strtod(optarg, &p);
+ if (*p) {
+ fprintf(stderr, "" POTRACE ": invalid opttolerance -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'o':
+ free(info.outfile);
+ info.outfile = strdup(optarg);
+ if (!info.outfile) {
+ fprintf(stderr, "" POTRACE ": %s\n", strerror(errno));
+ exit(2);
+ }
+ break;
+ case 'k':
+ info.blacklevel = strtod(optarg, &p);
+ if (*p) {
+ fprintf(stderr, "" POTRACE ": invalid blacklevel -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'i':
+ info.invert = 1;
+ break;
+ case OPT_OPAQUE:
+ info.opaque = 1;
+ break;
+ case OPT_GROUP:
+ info.grouping = 2;
+ break;
+ case OPT_FLAT:
+ info.grouping = 0;
+ break;
+ case OPT_PROGRESS:
+ info.progress = 1;
+ break;
+ case OPT_TTY:
+ if (strcmp(optarg, "dumb") == 0) {
+ info.progress_bar = progress_bar_simplified;
+ } else if (strcmp(optarg, "vt100") == 0) {
+ info.progress_bar = progress_bar_vt100;
+ } else {
+ fprintf(stderr, "" POTRACE ": invalid tty mode -- %s. Try --help for more info\n", optarg);
+ exit(1);
+ }
+ break;
+ case '?':
+ fprintf(stderr, "Try --help for more info\n");
+ exit(1);
+ break;
+ default:
+ fprintf(stderr, "" POTRACE ": Unimplemented option -- %c\n", c);
+ exit(1);
+ }
+ }
+ info.infiles = &av[optind];
+ info.infilecount = ac-optind;
+ info.some_infiles = info.infilecount ? 1 : 0;
+
+ /* if "--" was used, even an empty list of filenames is considered
+ "some" filenames. */
+ if (strcmp(av[optind-1], "--") == 0) {
+ info.some_infiles = 1;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* calculations with bitmap dimensions, positioning etc */
+
+/* determine the dimensions of the output based on command line and
+ image dimensions, and optionally, based on the actual image outline. */
+static void calc_dimensions(imginfo_t *imginfo, potrace_path_t *plist) {
+ double dim_def;
+ double maxwidth, maxheight, sc;
+ int default_scaling = 0;
+
+ /* we take care of a special case: if one of the image dimensions is
+ 0, we change it to 1. Such an image is empty anyway, so there
+ will be 0 paths in it. Changing the dimensions avoids division by
+ 0 error in calculating scaling factors, bounding boxes and
+ such. This doesn't quite do the right thing in all cases, but it
+ is better than causing overflow errors or "nan" output in
+ backends. Human users don't tend to process images of size 0
+ anyway; they might occur in some pipelines. */
+ if (imginfo->pixwidth == 0) {
+ imginfo->pixwidth = 1;
+ }
+ if (imginfo->pixheight == 0) {
+ imginfo->pixheight = 1;
+ }
+
+ /* set the default dimension for width, height, margins */
+ if (info.backend->pixel) {
+ dim_def = DIM_PT;
+ } else {
+ dim_def = DEFAULT_DIM;
+ }
+
+ /* apply default dimension to width, height, margins */
+ imginfo->width = info.width_d.x == UNDEF ? UNDEF : double_of_dim(info.width_d, dim_def);
+ imginfo->height = info.height_d.x == UNDEF ? UNDEF : double_of_dim(info.height_d, dim_def);
+ imginfo->lmar = info.lmar_d.x == UNDEF ? UNDEF : double_of_dim(info.lmar_d, dim_def);
+ imginfo->rmar = info.rmar_d.x == UNDEF ? UNDEF : double_of_dim(info.rmar_d, dim_def);
+ imginfo->tmar = info.tmar_d.x == UNDEF ? UNDEF : double_of_dim(info.tmar_d, dim_def);
+ imginfo->bmar = info.bmar_d.x == UNDEF ? UNDEF : double_of_dim(info.bmar_d, dim_def);
+
+ /* start with a standard rectangle */
+ trans_from_rect(&imginfo->trans, imginfo->pixwidth, imginfo->pixheight);
+
+ /* if info.tight is set, tighten the bounding box */
+ if (info.tight) {
+ trans_tighten(&imginfo->trans, plist);
+ }
+
+ /* sx/rx is just an alternate way to specify width; sy/ry is just an
+ alternate way to specify height. */
+ if (info.backend->pixel) {
+ if (imginfo->width == UNDEF && info.sx != UNDEF) {
+ imginfo->width = imginfo->trans.bb[0] * info.sx;
+ }
+ if (imginfo->height == UNDEF && info.sy != UNDEF) {
+ imginfo->height = imginfo->trans.bb[1] * info.sy;
+ }
+ } else {
+ if (imginfo->width == UNDEF && info.rx != UNDEF) {
+ imginfo->width = imginfo->trans.bb[0] / info.rx * 72;
+ }
+ if (imginfo->height == UNDEF && info.ry != UNDEF) {
+ imginfo->height = imginfo->trans.bb[1] / info.ry * 72;
+ }
+ }
+
+ /* if one of width/height is specified, use stretch to determine the
+ other */
+ if (imginfo->width == UNDEF && imginfo->height != UNDEF) {
+ imginfo->width = imginfo->height / imginfo->trans.bb[1] * imginfo->trans.bb[0] / info.stretch;
+ } else if (imginfo->width != UNDEF && imginfo->height == UNDEF) {
+ imginfo->height = imginfo->width / imginfo->trans.bb[0] * imginfo->trans.bb[1] * info.stretch;
+ }
+
+ /* if width and height are still variable, tenatively use the
+ default scaling factor of 72dpi (for dimension-based backends) or
+ 1 (for pixel-based backends). For fixed-size backends, this will
+ be adjusted later to fit the page. */
+ if (imginfo->width == UNDEF && imginfo->height == UNDEF) {
+ imginfo->width = imginfo->trans.bb[0];
+ imginfo->height = imginfo->trans.bb[1] * info.stretch;
+ default_scaling = 1;
+ }
+
+ /* apply scaling */
+ trans_scale_to_size(&imginfo->trans, imginfo->width, imginfo->height);
+
+ /* apply rotation, and tighten the bounding box again, if necessary */
+ if (info.angle != 0.0) {
+ trans_rotate(&imginfo->trans, info.angle);
+ if (info.tight) {
+ trans_tighten(&imginfo->trans, plist);
+ }
+ }
+
+ /* for fixed-size backends, if default scaling was in effect,
+ further adjust the scaling to be the "best fit" for the given
+ page size and margins. */
+ if (default_scaling && info.backend->fixed) {
+
+ /* try to squeeze it between margins */
+ maxwidth = UNDEF;
+ maxheight = UNDEF;
+
+ if (imginfo->lmar != UNDEF && imginfo->rmar != UNDEF) {
+ maxwidth = info.paperwidth - imginfo->lmar - imginfo->rmar;
+ }
+ if (imginfo->bmar != UNDEF && imginfo->tmar != UNDEF) {
+ maxheight = info.paperheight - imginfo->bmar - imginfo->tmar;
+ }
+ if (maxwidth == UNDEF && maxheight == UNDEF) {
+ maxwidth = max(info.paperwidth - 144, info.paperwidth * 0.75);
+ maxheight = max(info.paperheight - 144, info.paperheight * 0.75);
+ }
+
+ if (maxwidth == UNDEF) {
+ sc = maxheight / imginfo->trans.bb[1];
+ } else if (maxheight == UNDEF) {
+ sc = maxwidth / imginfo->trans.bb[0];
+ } else {
+ sc = min(maxwidth / imginfo->trans.bb[0], maxheight / imginfo->trans.bb[1]);
+ }
+
+ /* re-scale coordinate system */
+ imginfo->width *= sc;
+ imginfo->height *= sc;
+ trans_rescale(&imginfo->trans, sc);
+ }
+
+ /* adjust margins */
+ if (info.backend->fixed) {
+ if (imginfo->lmar == UNDEF && imginfo->rmar == UNDEF) {
+ imginfo->lmar = (info.paperwidth-imginfo->trans.bb[0])/2;
+ } else if (imginfo->lmar == UNDEF) {
+ imginfo->lmar = (info.paperwidth-imginfo->trans.bb[0]-imginfo->rmar);
+ } else if (imginfo->lmar != UNDEF && imginfo->rmar != UNDEF) {
+ imginfo->lmar += (info.paperwidth-imginfo->trans.bb[0]-imginfo->lmar-imginfo->rmar)/2;
+ }
+ if (imginfo->bmar == UNDEF && imginfo->tmar == UNDEF) {
+ imginfo->bmar = (info.paperheight-imginfo->trans.bb[1])/2;
+ } else if (imginfo->bmar == UNDEF) {
+ imginfo->bmar = (info.paperheight-imginfo->trans.bb[1]-imginfo->tmar);
+ } else if (imginfo->bmar != UNDEF && imginfo->tmar != UNDEF) {
+ imginfo->bmar += (info.paperheight-imginfo->trans.bb[1]-imginfo->bmar-imginfo->tmar)/2;
+ }
+ } else {
+ if (imginfo->lmar == UNDEF) {
+ imginfo->lmar = 0;
+ }
+ if (imginfo->rmar == UNDEF) {
+ imginfo->rmar = 0;
+ }
+ if (imginfo->bmar == UNDEF) {
+ imginfo->bmar = 0;
+ }
+ if (imginfo->tmar == UNDEF) {
+ imginfo->tmar = 0;
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary functions for file handling */
+
+/* open a file for reading. Return stdin if filename is NULL or "-" */
+static FILE *my_fopen_read(const char *filename) {
+ if (filename == NULL || strcmp(filename, "-") == 0) {
+ return stdin;
+ }
+ return fopen(filename, "rb");
+}
+
+/* open a file for writing. Return stdout if filename is NULL or "-" */
+static FILE *my_fopen_write(const char *filename) {
+ if (filename == NULL || strcmp(filename, "-") == 0) {
+ return stdout;
+ }
+ return fopen(filename, "wb");
+}
+
+/* close a file, but do nothing is filename is NULL or "-" */
+static void my_fclose(FILE *f, const char *filename) {
+ if (filename == NULL || strcmp(filename, "-") == 0) {
+ return;
+ }
+ fclose(f);
+}
+
+/* make output filename from input filename. Return an allocated value. */
+static char *make_outfilename(const char *infile, const char *ext) {
+ char *outfile;
+ char *p;
+
+ if (strcmp(infile, "-") == 0) {
+ return strdup("-");
+ }
+
+ outfile = (char *) malloc(strlen(infile)+strlen(ext)+5);
+ if (!outfile) {
+ return NULL;
+ }
+ strcpy(outfile, infile);
+ p = strrchr(outfile, '.');
+ if (p) {
+ *p = 0;
+ }
+ strcat(outfile, ext);
+
+ /* check that input and output filenames are different */
+ if (strcmp(infile, outfile) == 0) {
+ strcpy(outfile, infile);
+ strcat(outfile, "-out");
+ }
+
+ return outfile;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Process one infile */
+
+/* Process one or more bitmaps from fin, and write the results to fout
+ using the page_f function of the appropriate backend. */
+
+static void process_file(backend_t *b, const char *infile, const char *outfile, FILE *fin, FILE *fout) {
+ int r;
+ potrace_bitmap_t *bm = NULL;
+ imginfo_t imginfo;
+ int eof_flag = 0; /* to indicate premature eof */
+ int count; /* number of bitmaps successfully processed, this file */
+ potrace_state_t *st;
+
+ for (count=0; ; count++) {
+ /* read a bitmap */
+ r = bm_read(fin, info.blacklevel, &bm);
+ switch (r) {
+ case -1: /* system error */
+ fprintf(stderr, "" POTRACE ": %s: %s\n", infile, strerror(errno));
+ exit(2);
+ case -2: /* corrupt file format */
+ fprintf(stderr, "" POTRACE ": %s: file format error: %s\n", infile, bm_read_error);
+ exit(2);
+ case -3: /* empty file */
+ if (count>0) { /* end of file */
+ return;
+ }
+ fprintf(stderr, "" POTRACE ": %s: empty file\n", infile);
+ exit(2);
+ case -4: /* wrong magic */
+ if (count>0) {
+ fprintf(stderr, "" POTRACE ": %s: warning: junk at end of file\n", infile);
+ return;
+ }
+ fprintf(stderr, "" POTRACE ": %s: file format not recognized\n", infile);
+ fprintf(stderr, "Possible input file formats are: pnm (pbm, pgm, ppm), bmp.\n");
+ exit(2);
+ case 1: /* unexpected end of file */
+ fprintf(stderr, "" POTRACE ": warning: %s: premature end of file\n", infile);
+ eof_flag = 1;
+ break;
+ }
+
+ /* prepare progress bar, if requested */
+ if (info.progress) {
+ r = info.progress_bar->init(&info.param->progress, infile, count);
+ if (r) {
+ fprintf(stderr, "" POTRACE ": %s\n", strerror(errno));
+ exit(2);
+ }
+ } else {
+ info.param->progress.callback = NULL;
+ }
+
+ if (info.invert) {
+ bm_invert(bm);
+ }
+
+ /* process the image */
+ st = potrace_trace(info.param, bm);
+ if (!st || st->status != POTRACE_STATUS_OK) {
+ fprintf(stderr, "" POTRACE ": %s: %s\n", infile, strerror(errno));
+ exit(2);
+ }
+
+ /* calculate image dimensions */
+ imginfo.pixwidth = bm->w;
+ imginfo.pixheight = bm->h;
+ bm_free(bm);
+
+ calc_dimensions(&imginfo, st->plist);
+
+ r = b->page_f(fout, st->plist, &imginfo);
+ if (r) {
+ fprintf(stderr, "" POTRACE ": %s: %s\n", outfile, strerror(errno));
+ exit(2);
+ }
+
+ potrace_state_free(st);
+
+ if (info.progress) {
+ info.progress_bar->term(&info.param->progress);
+ }
+
+ if (eof_flag || !b->multi) {
+ return;
+ }
+ }
+ /* not reached */
+}
+
+/* ---------------------------------------------------------------------- */
+/* main: handle file i/o */
+
+#define TRY(x) if (x) goto try_error
+
+int main(int ac, char *av[]) {
+ backend_t *b; /* backend info */
+ FILE *fin, *fout;
+ int i;
+ char *outfile;
+
+ /* platform-specific initializations, e.g., set file i/o to binary */
+ platform_init();
+
+ /* process options */
+ dopts(ac, av);
+
+ b = info.backend;
+ if (b==NULL) {
+ fprintf(stderr, "" POTRACE ": internal error: selected backend not found\n");
+ exit(1);
+ }
+
+ /* fix some parameters */
+ /* if backend cannot handle opticurve, disable it */
+ if (b->opticurve == 0) {
+ info.param->opticurve = 0;
+ }
+
+ /* there are several ways to call us:
+ potrace -- stdin to stdout
+ potrace -o outfile -- stdin to outfile
+ potrace file... -- encode each file and generate outfile names
+ potrace -o outfile file... -- concatenate files and write to outfile
+
+ The latter form is only allowed one file for single-page
+ backends. For multi-page backends, each file must contain 0 or
+ more complete bitmaps.
+ */
+
+ if (!info.some_infiles) { /* read from stdin */
+
+ fout = my_fopen_write(info.outfile);
+ if (!fout) {
+ fprintf(stderr, "" POTRACE ": %s: %s\n", info.outfile ? info.outfile : "stdout", strerror(errno));
+ exit(2);
+ }
+ if (b->init_f) {
+ TRY(b->init_f(fout));
+ }
+ process_file(b, "stdin", info.outfile ? info.outfile : "stdout", stdin, fout);
+ if (b->term_f) {
+ TRY(b->term_f(fout));
+ }
+ my_fclose(fout, info.outfile);
+ free(info.outfile);
+ potrace_param_free(info.param);
+ return 0;
+
+ } else if (!info.outfile) { /* infiles -> multiple outfiles */
+
+ for (i=0; i<info.infilecount; i++) {
+ outfile = make_outfilename(info.infiles[i], b->ext);
+ if (!outfile) {
+ fprintf(stderr, "" POTRACE ": %s\n", strerror(errno));
+ exit(2);
+ }
+ fin = my_fopen_read(info.infiles[i]);
+ if (!fin) {
+ fprintf(stderr, "" POTRACE ": %s: %s\n", info.infiles[i], strerror(errno));
+ exit(2);
+ }
+ fout = my_fopen_write(outfile);
+ if (!fout) {
+ fprintf(stderr, "" POTRACE ": %s: %s\n", outfile, strerror(errno));
+ exit(2);
+ }
+ if (b->init_f) {
+ TRY(b->init_f(fout));
+ }
+ process_file(b, info.infiles[i], outfile, fin, fout);
+ if (b->term_f) {
+ TRY(b->term_f(fout));
+ }
+ my_fclose(fin, info.infiles[i]);
+ my_fclose(fout, outfile);
+ free(outfile);
+ }
+ potrace_param_free(info.param);
+ return 0;
+
+ } else { /* infiles to single outfile */
+
+ if (!b->multi && info.infilecount >= 2) {
+ fprintf(stderr, "" POTRACE ": cannot use multiple input files with -o in %s mode\n", b->name);
+ exit(1);
+ }
+ if (info.infilecount == 0) {
+ fprintf(stderr, "" POTRACE ": cannot use empty list of input files with -o\n");
+ exit(1);
+ }
+
+ fout = my_fopen_write(info.outfile);
+ if (!fout) {
+ fprintf(stderr, "" POTRACE ": %s: %s\n", info.outfile, strerror(errno));
+ exit(2);
+ }
+ if (b->init_f) {
+ TRY(b->init_f(fout));
+ }
+ for (i=0; i<info.infilecount; i++) {
+ fin = my_fopen_read(info.infiles[i]);
+ if (!fin) {
+ fprintf(stderr, "" POTRACE ": %s: %s\n", info.infiles[i], strerror(errno));
+ exit(2);
+ }
+ process_file(b, info.infiles[i], info.outfile, fin, fout);
+ my_fclose(fin, info.infiles[i]);
+ }
+ if (b->term_f) {
+ TRY(b->term_f(fout));
+ }
+ my_fclose(fout, info.outfile);
+ free(info.outfile);
+ potrace_param_free(info.param);
+ return 0;
+
+ }
+
+ /* not reached */
+
+ try_error:
+ fprintf(stderr, "" POTRACE ": %s\n", strerror(errno));
+ exit(2);
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/main.h b/Build/source/libs/potrace/potrace-src/src/main.h
new file mode 100644
index 00000000000..b7f6805ce4d
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/main.h
@@ -0,0 +1,109 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "potracelib.h"
+#include "progress_bar.h"
+#include "auxiliary.h"
+#include "trans.h"
+
+/* structure to hold a dimensioned value */
+struct dim_s {
+ double x; /* value */
+ double d; /* dimension (in pt), or 0 if not given */
+};
+typedef struct dim_s dim_t;
+
+#define DIM_IN (72)
+#define DIM_CM (72 / 2.54)
+#define DIM_MM (72 / 25.4)
+#define DIM_PT (1)
+
+/* set some configurable defaults */
+
+#ifdef USE_METRIC
+#define DEFAULT_DIM DIM_CM
+#define DEFAULT_DIM_NAME "centimeters"
+#else
+#define DEFAULT_DIM DIM_IN
+#define DEFAULT_DIM_NAME "inches"
+#endif
+
+#ifdef USE_A4
+#define DEFAULT_PAPERWIDTH 595
+#define DEFAULT_PAPERHEIGHT 842
+#define DEFAULT_PAPERFORMAT "a4"
+#else
+#define DEFAULT_PAPERWIDTH 612
+#define DEFAULT_PAPERHEIGHT 792
+#define DEFAULT_PAPERFORMAT "letter"
+#endif
+
+#ifdef DUMB_TTY
+#define DEFAULT_PROGRESS_BAR progress_bar_simplified
+#else
+#define DEFAULT_PROGRESS_BAR progress_bar_vt100
+#endif
+
+
+
+struct backend_s;
+
+/* structure to hold command line options */
+struct info_s {
+ struct backend_s *backend; /* type of backend (eps,ps,pgm etc) */
+ potrace_param_t *param; /* tracing parameters, see potracelib.h */
+ int debug; /* type of output (0-2) (for BACKEND_PS/EPS only) */
+ dim_t width_d; /* desired width of image */
+ dim_t height_d; /* desired height of image */
+ double rx; /* desired x resolution (in dpi) */
+ double ry; /* desired y resolution (in dpi) */
+ double sx; /* desired x scaling factor */
+ double sy; /* desired y scaling factor */
+ double stretch; /* ry/rx, if not otherwise determined */
+ dim_t lmar_d, rmar_d, tmar_d, bmar_d; /* margins */
+ double angle; /* rotate by this many degrees */
+ int paperwidth, paperheight; /* paper size for ps backend (in pt) */
+ int tight; /* should bounding box follow actual vector outline? */
+ double unit; /* granularity of output grid */
+ int compress; /* apply compression? */
+ int pslevel; /* postscript level to use: affects only compression */
+ int color; /* rgb color code 0xrrggbb: line color */
+ int fillcolor; /* rgb color code 0xrrggbb: fill color */
+ double gamma; /* gamma value for pgm backend */
+ int longcoding; /* do not optimize for file size? */
+ char *outfile; /* output filename, if given */
+ char **infiles; /* array of input filenames */
+ int infilecount; /* number of input filenames */
+ int some_infiles; /* do we process a list of input filenames? */
+ double blacklevel; /* 0 to 1: black/white cutoff in input file */
+ int invert; /* invert bitmap? */
+ int opaque; /* paint white shapes opaquely? */
+ int grouping; /* 0=flat; 1=connected components; 2=hierarchical */
+ int progress; /* should we display a progress bar? */
+ progress_bar_t *progress_bar; /* which progress bar to use */
+};
+typedef struct info_s info_t;
+
+extern info_t info;
+
+/* structure to hold per-image information, set e.g. by calc_dimensions */
+struct imginfo_s {
+ int pixwidth; /* width of input pixmap */
+ int pixheight; /* height of input pixmap */
+ double width; /* desired width of image (in pt or pixels) */
+ double height; /* desired height of image (in pt or pixels) */
+ double lmar, rmar, tmar, bmar; /* requested margins (in pt) */
+ trans_t trans; /* specify relative position of a tilted rectangle */
+};
+typedef struct imginfo_s imginfo_t;
+
+#endif /* MAIN_H */
diff --git a/Build/source/libs/potrace/potrace-src/src/mkbitmap.c b/Build/source/libs/potrace/potrace-src/src/mkbitmap.c
new file mode 100644
index 00000000000..9b302c45a40
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/mkbitmap.c
@@ -0,0 +1,794 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* mkbitmap.c: a standalone program for converting greymaps to bitmaps
+ while optionally applying the following enhancements: highpass
+ filter (evening out background gradients), lowpass filter
+ (smoothing foreground details), interpolated scaling, inversion. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <getopt.h>
+
+#include "greymap.h"
+#include "bitmap_io.h"
+#include "platform.h"
+
+#define SAFE_CALLOC(var, n, typ) \
+ if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error
+
+/* structure to hold command line options */
+struct info_s {
+ char *outfile; /* output file */
+ char **infiles; /* input files */
+ int infilecount; /* how many input files? */
+ int invert; /* invert input? */
+ int highpass; /* use highpass filter? */
+ double lambda; /* highpass filter radius */
+ int lowpass; /* use lowpass filter? */
+ double lambda1; /* lowpass filter radius */
+ int scale; /* scaling factor */
+ int linear; /* linear scaling? */
+ int bilevel; /* convert to bilevel? */
+ double level; /* cutoff grey level */
+ const char *outext; /* default output file extension */
+};
+typedef struct info_s info_t;
+
+static info_t info;
+
+/* apply lowpass filter (an approximate Gaussian blur) to greymap.
+ Lambda is the standard deviation of the kernel of the filter (i.e.,
+ the approximate filter radius). */
+static void lowpass(greymap_t *gm, double lambda) {
+ double f, g;
+ double c, d;
+ double B;
+ int x, y;
+
+ if (gm->h == 0 || gm->w == 0) {
+ return;
+ }
+
+ /* calculate filter coefficients from given lambda */
+ B = 1+2/(lambda*lambda);
+ c = B-sqrt(B*B-1);
+ d = 1-c;
+
+ for (y=0; y<gm->h; y++) {
+ /* apply low-pass filter to row y */
+ /* left-to-right */
+ f = g = 0;
+ for (x=0; x<gm->w; x++) {
+ f = f*c + GM_UGET(gm, x, y)*d;
+ g = g*c + f*d;
+ GM_UPUT(gm, x, y, g);
+ }
+
+ /* right-to-left */
+ for (x=gm->w-1; x>=0; x--) {
+ f = f*c + GM_UGET(gm, x, y)*d;
+ g = g*c + f*d;
+ GM_UPUT(gm, x, y, g);
+ }
+
+ /* left-to-right mop-up */
+ for (x=0; x<gm->w; x++) {
+ f = f*c;
+ g = g*c + f*d;
+ if (f+g < 1/255.0) {
+ break;
+ }
+ GM_UPUT(gm, x, y, GM_UGET(gm, x, y)+g);
+ }
+ }
+
+ for (x=0; x<gm->w; x++) {
+ /* apply low-pass filter to column x */
+ /* bottom-to-top */
+ f = g = 0;
+ for (y=0; y<gm->h; y++) {
+ f = f*c + GM_UGET(gm, x, y)*d;
+ g = g*c + f*d;
+ GM_UPUT(gm, x, y, g);
+ }
+
+ /* top-to-bottom */
+ for (y=gm->h-1; y>=0; y--) {
+ f = f*c + GM_UGET(gm, x, y)*d;
+ g = g*c + f*d;
+ GM_UPUT(gm, x, y, g);
+ }
+
+ /* bottom-to-top mop-up */
+ for (y=0; y<gm->h; y++) {
+ f = f*c;
+ g = g*c + f*d;
+ if (f+g < 1/255.0) {
+ break;
+ }
+ GM_UPUT(gm, x, y, GM_UGET(gm, x, y)+g);
+ }
+ }
+}
+
+/* apply highpass filter to greymap. Return 0 on success, 1 on error
+ with errno set. */
+static int highpass(greymap_t *gm, double lambda) {
+ greymap_t *gm1;
+ double f;
+ int x, y;
+
+ if (gm->h == 0 || gm->w == 0) {
+ return 0;
+ }
+
+ /* create a copy */
+ gm1 = gm_dup(gm);
+ if (!gm1) {
+ return 1;
+ }
+
+ /* apply lowpass filter to the copy */
+ lowpass(gm1, lambda);
+
+ /* subtract copy from original */
+ for (y=0; y<gm->h; y++) {
+ for (x=0; x<gm->w; x++) {
+ f = GM_UGET(gm, x, y);
+ f -= GM_UGET(gm1, x, y);
+ f += 128; /* normalize! */
+ GM_UPUT(gm, x, y, f);
+ }
+ }
+ gm_free(gm1);
+ return 0;
+}
+
+/* Convert greymap to bitmap by using cutoff threshold c (0=black,
+ 1=white). On error, return NULL with errno set. */
+static potrace_bitmap_t *threshold(greymap_t *gm, double c) {
+ int w, h;
+ potrace_bitmap_t *bm_out = NULL;
+ double c1;
+ int x, y;
+ double p;
+
+ w = gm->w;
+ h = gm->h;
+
+ /* allocate output bitmap */
+ bm_out = bm_new(w, h);
+ if (!bm_out) {
+ return NULL;
+ }
+
+ /* thresholding */
+ c1 = c * 255;
+
+ for (y=0; y<h; y++) {
+ for (x=0; x<w; x++) {
+ p = GM_UGET(gm, x, y);
+ BM_UPUT(bm_out, x, y, p < c1);
+ }
+ }
+ return bm_out;
+}
+
+/* scale greymap by factor s, using linear interpolation. If
+ bilevel=0, return a pointer to a greymap_t. If bilevel=1, return a
+ pointer to a potrace_bitmap_t and use cutoff threshold c (0=black,
+ 1=white). On error, return NULL with errno set. */
+
+static void *interpolate_linear(greymap_t *gm, int s, int bilevel, double c) {
+ int p00, p01, p10, p11;
+ int i, j, x, y;
+ double xx, yy, av;
+ double c1 = 0;
+ int w, h;
+ double p0, p1;
+ greymap_t *gm_out = NULL;
+ potrace_bitmap_t *bm_out = NULL;
+
+ w = gm->w;
+ h = gm->h;
+
+ /* allocate output bitmap/greymap */
+ if (bilevel) {
+ bm_out = bm_new(w*s, h*s);
+ if (!bm_out) {
+ return NULL;
+ }
+ c1 = c * 255;
+ } else {
+ gm_out = gm_new(w*s, h*s);
+ if (!gm_out) {
+ return NULL;
+ }
+ }
+
+ /* interpolate */
+ for (i=0; i<w; i++) {
+ for (j=0; j<h; j++) {
+ p00 = GM_BGET(gm, i, j);
+ p01 = GM_BGET(gm, i, j+1);
+ p10 = GM_BGET(gm, i+1, j);
+ p11 = GM_BGET(gm, i+1, j+1);
+
+ if (bilevel) {
+ /* treat two special cases which are very common */
+ if (p00 < c1 && p01 < c1 && p10 < c1 && p11 < c1) {
+ for (x=0; x<s; x++) {
+ for (y=0; y<s; y++) {
+ BM_UPUT(bm_out, i*s+x, j*s+y, 1);
+ }
+ }
+ continue;
+ }
+ if (p00 >= c1 && p01 >= c1 && p10 >= c1 && p11 >= c1) {
+ continue;
+ }
+ }
+
+ /* the general case */
+ for (x=0; x<s; x++) {
+ xx = x/(double)s;
+ p0 = p00*(1-xx) + p10*xx;
+ p1 = p01*(1-xx) + p11*xx;
+ for (y=0; y<s; y++) {
+ yy = y/(double)s;
+ av = p0*(1-yy) + p1*yy;
+ if (bilevel) {
+ BM_UPUT(bm_out, i*s+x, j*s+y, av < c1);
+ } else {
+ GM_UPUT(gm_out, i*s+x, j*s+y, av);
+ }
+ }
+ }
+ }
+ }
+ if (bilevel) {
+ return (void *)bm_out;
+ } else {
+ return (void *)gm_out;
+ }
+}
+
+/* same as interpolate_linear, except use cubic interpolation (slower
+ and better). */
+
+/* we need this typedef so that the SAFE_CALLOC macro will work */
+typedef double double4[4];
+
+static void *interpolate_cubic(greymap_t *gm, int s, int bilevel, double c) {
+ int w, h;
+ double4 *poly = NULL; /* poly[s][4]: fixed interpolation polynomials */
+ double p[4]; /* four current points */
+ double4 *window = NULL; /* window[s][4]: current state */
+ double t, v;
+ int k, l, i, j, x, y;
+ double c1 = 0;
+ greymap_t *gm_out = NULL;
+ potrace_bitmap_t *bm_out = NULL;
+
+ SAFE_CALLOC(poly, s, double4);
+ SAFE_CALLOC(window, s, double4);
+
+ w = gm->w;
+ h = gm->h;
+
+ /* allocate output bitmap/greymap */
+ if (bilevel) {
+ bm_out = bm_new(w*s, h*s);
+ if (!bm_out) {
+ goto calloc_error;
+ }
+ c1 = c * 255;
+ } else {
+ gm_out = gm_new(w*s, h*s);
+ if (!gm_out) {
+ goto calloc_error;
+ }
+ }
+
+ /* pre-calculate interpolation polynomials */
+ for (k=0; k<s; k++) {
+ t = k/(double)s;
+ poly[k][0] = 0.5 * t * (t-1) * (1-t);
+ poly[k][1] = -(t+1) * (t-1) * (1-t) + 0.5 * (t-1) * (t-2) * t;
+ poly[k][2] = 0.5 * (t+1) * t * (1-t) - t * (t-2) * t;
+ poly[k][3] = 0.5 * t * (t-1) * t;
+ }
+
+ /* interpolate */
+ for (y=0; y<h; y++) {
+ x=0;
+ for (i=0; i<4; i++) {
+ for (j=0; j<4; j++) {
+ p[j] = GM_BGET(gm, x+i-1, y+j-1);
+ }
+ for (k=0; k<s; k++) {
+ window[k][i] = 0.0;
+ for (j=0; j<4; j++) {
+ window[k][i] += poly[k][j] * p[j];
+ }
+ }
+ }
+ while (1) {
+ for (l=0; l<s; l++) {
+ for (k=0; k<s; k++) {
+ v = 0.0;
+ for (i=0; i<4; i++) {
+ v += window[k][i] * poly[l][i];
+ }
+ if (bilevel) {
+ BM_PUT(bm_out, x*s+l, y*s+k, v < c1);
+ } else {
+ GM_PUT(gm_out, x*s+l, y*s+k, v);
+ }
+ }
+ }
+ x++;
+ if (x>=w) {
+ break;
+ }
+ for (i=0; i<3; i++) {
+ for (k=0; k<s; k++) {
+ window[k][i] = window[k][i+1];
+ }
+ }
+ i=3;
+ for (j=0; j<4; j++) {
+ p[j] = GM_BGET(gm, x+i-1, y+j-1);
+ }
+ for (k=0; k<s; k++) {
+ window[k][i] = 0.0;
+ for (j=0; j<4; j++) {
+ window[k][i] += poly[k][j] * p[j];
+ }
+ }
+ }
+ }
+
+ free(poly);
+ free(window);
+
+ if (bilevel) {
+ return (void *)bm_out;
+ } else {
+ return (void *)gm_out;
+ }
+
+ calloc_error:
+ free(poly);
+ free(window);
+ return NULL;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/* process a single file, containing one or more images. On error,
+ print error message to stderr and exit with code 2. On warning,
+ print warning message to stderr. */
+
+static void process_file(FILE *fin, FILE *fout, const char *infile, const char *outfile) {
+ int r;
+ greymap_t *gm;
+ potrace_bitmap_t *bm;
+ void *sm;
+ int x, y;
+ int count;
+
+ for (count=0; ; count++) {
+ r = gm_read(fin, &gm);
+ switch (r) {
+ case -1: /* system error */
+ fprintf(stderr, "" MKBITMAP ": %s: %s\n", infile, strerror(errno));
+ exit(2);
+ case -2: /* corrupt file format */
+ fprintf(stderr, "" MKBITMAP ": %s: file format error: %s\n", infile, gm_read_error);
+ exit(2);
+ case -3: /* empty file */
+ if (count>0) { /* end of file */
+ return;
+ }
+ fprintf(stderr, "" MKBITMAP ": %s: empty file\n", infile);
+ exit(2);
+ case -4: /* wrong magic */
+ if (count>0) {
+ fprintf(stderr, "" MKBITMAP ": %s: warning: junk at end of file\n", infile);
+ return;
+ }
+ fprintf(stderr, "" MKBITMAP ": %s: file format not recognized\n", infile);
+ fprintf(stderr, "Possible input file formats are: pnm (pbm, pgm, ppm), bmp.\n");
+ exit(2);
+ case 1: /* unexpected end of file */
+ fprintf(stderr, "" MKBITMAP ": %s: warning: premature end of file\n", infile);
+ break;
+ }
+
+ if (info.invert) {
+ for (y=0; y<gm->h; y++) {
+ for (x=0; x<gm->w; x++) {
+ GM_UPUT(gm, x, y, 255-GM_UGET(gm, x, y));
+ }
+ }
+ }
+
+ if (info.highpass) {
+ r = highpass(gm, info.lambda);
+ if (r) {
+ fprintf(stderr, "" MKBITMAP ": %s: %s\n", infile, strerror(errno));
+ exit(2);
+ }
+ }
+
+ if (info.lowpass) {
+ lowpass(gm, info.lambda1);
+ }
+
+ if (info.scale == 1 && info.bilevel) { /* no interpolation necessary */
+ sm = threshold(gm, info.level);
+ gm_free(gm);
+ } else if (info.scale == 1) {
+ sm = gm;
+ } else if (info.linear) { /* linear interpolation */
+ sm = interpolate_linear(gm, info.scale, info.bilevel, info.level);
+ gm_free(gm);
+ } else { /* cubic interpolation */
+ sm = interpolate_cubic(gm, info.scale, info.bilevel, info.level);
+ gm_free(gm);
+ }
+ if (!sm) {
+ fprintf(stderr, "" MKBITMAP ": %s: %s\n", infile, strerror(errno));
+ exit(2);
+ }
+
+ if (info.bilevel) {
+ bm = (potrace_bitmap_t *)sm;
+ bm_writepbm(fout, bm);
+ bm_free(bm);
+ } else {
+ gm = (greymap_t *)sm;
+ gm_writepgm(fout, gm, NULL, 1, GM_MODE_POSITIVE, 1.0);
+ gm_free(gm);
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* some info functions and option processing */
+
+static int license(FILE *f) {
+ fprintf(f,
+ "This program is free software; you can redistribute it and/or modify\n"
+ "it under the terms of the GNU General Public License as published by\n"
+ "the Free Software Foundation; either version 2 of the License, or\n"
+ "(at your option) any later version.\n"
+ "\n"
+ "This program is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+ "GNU General Public License for more details.\n"
+ "\n"
+ "You should have received a copy of the GNU General Public License\n"
+ "along with this program; if not, write to the Free Software Foundation\n"
+ "Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\n"
+ );
+ return 0;
+}
+
+static int usage(FILE *f) {
+ fprintf(f, "Usage: " MKBITMAP " [options] [file...]\n");
+ fprintf(f, "Options:\n");
+ fprintf(f, " -h, --help - print this help message and exit\n");
+ fprintf(f, " -v, --version - print version info and exit\n");
+ fprintf(f, " -l, --license - print license info and exit\n");
+ fprintf(f, " -o, --output <file> - output to file\n");
+ fprintf(f, " -x, --nodefaults - turn off default options\n");
+ fprintf(f, "Inversion:\n");
+ fprintf(f, " -i, --invert - invert the input (undo 'blackboard' effect)\n");
+ fprintf(f, "Highpass filtering:\n");
+ fprintf(f, " -f, --filter <n> - apply highpass filter with radius n (default 4)\n");
+ fprintf(f, " -n, --nofilter - no highpass filtering\n");
+ fprintf(f, " -b, --blur <n> - apply lowpass filter with radius n (default: none)\n");
+ fprintf(f, "Scaling:\n");
+ fprintf(f, " -s, --scale <n> - scale by integer factor n (default 2)\n");
+ fprintf(f, " -1, --linear - use linear interpolation\n");
+ fprintf(f, " -3, --cubic - use cubic interpolation (default)\n");
+ fprintf(f, "Thresholding:\n");
+ fprintf(f, " -t, --threshold <n> - set threshold for bilevel conversion (default 0.45)\n");
+ fprintf(f, " -g, --grey - no bilevel conversion, output a greymap\n");
+
+ fprintf(f, "\n");
+ fprintf(f, "Possible input file formats are: pnm (pbm, pgm, ppm), bmp.\n");
+ fprintf(f, "The default options are: -f 4 -s 2 -3 -t 0.45\n");
+
+ return 0;
+}
+
+static struct option longopts[] = {
+ {"help", 0, 0, 'h'},
+ {"version", 0, 0, 'v'},
+ {"license", 0, 0, 'l'},
+ {"output", 1, 0, 'o'},
+ {"reset", 0, 0, 'x'},
+ {"invert", 0, 0, 'i'},
+ {"filter", 1, 0, 'f'},
+ {"nofilter", 0, 0, 'n'},
+ {"blur", 1, 0, 'b'},
+ {"scale", 1, 0, 's'},
+ {"linear", 0, 0, '1'},
+ {"cubic", 0, 0, '3'},
+ {"grey", 0, 0, 'g'},
+ {"threshold", 1, 0, 't'},
+ {0, 0, 0, 0}
+};
+
+static const char *shortopts = "hvlo:xif:nb:s:13gt:";
+
+/* process options. On error, print error message to stderr and exit
+ with code 1 */
+static void dopts(int ac, char *av[]) {
+ int c;
+ char *p;
+
+ /* set defaults for command line parameters */
+ info.outfile = NULL; /* output file */
+ info.infiles = NULL; /* input files */
+ info.infilecount = 0; /* how many input files? */
+ info.invert = 0; /* invert input? */
+ info.highpass = 1; /* use highpass filter? */
+ info.lambda = 4; /* highpass filter radius */
+ info.lowpass = 0; /* use lowpass filter? */
+ info.lambda1 = 0; /* lowpass filter radius */
+ info.scale = 2; /* scaling factor */
+ info.linear = 0; /* linear scaling? */
+ info.bilevel = 1; /* convert to bilevel? */
+ info.level = 0.45; /* cutoff grey level */
+ info.outext = ".pbm"; /* output file extension */
+
+ while ((c = getopt_long(ac, av, shortopts, longopts, NULL)) != -1) {
+ switch (c) {
+ case 'h':
+ fprintf(stdout, "" MKBITMAP " " VERSION ". Transforms images into bitmaps with scaling and filtering.\n\n");
+ usage(stdout);
+ exit(0);
+ break;
+ case 'v':
+ fprintf(stdout, "" MKBITMAP " " VERSION ". Copyright (C) 2001-2019 Peter Selinger.\n");
+ exit(0);
+ break;
+ case 'l':
+ fprintf(stdout, "" MKBITMAP " " VERSION ". Copyright (C) 2001-2019 Peter Selinger.\n\n");
+ license(stdout);
+ exit(0);
+ break;
+ case 'o':
+ free(info.outfile);
+ info.outfile = strdup(optarg);
+ if (!info.outfile) {
+ fprintf(stderr, "" MKBITMAP ": %s\n", strerror(errno));
+ exit(2);
+ }
+ break;
+ case 'x':
+ info.invert = 0;
+ info.highpass = 0;
+ info.scale = 1;
+ info.bilevel = 0;
+ info.outext = ".pgm";
+ break;
+ case 'i':
+ info.invert = 1;
+ break;
+ case 'f':
+ info.highpass = 1;
+ info.lambda = strtod(optarg, &p);
+ if (*p || info.lambda<0) {
+ fprintf(stderr, "" MKBITMAP ": invalid filter radius -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 'n':
+ info.highpass = 0;
+ break;
+ case 'b':
+ info.lowpass = 1;
+ info.lambda1 = strtod(optarg, &p);
+ if (*p || info.lambda1<0) {
+ fprintf(stderr, "" MKBITMAP ": invalid filter radius -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case 's':
+ info.scale = strtol(optarg, &p, 0);
+ if (*p || info.scale<=0) {
+ fprintf(stderr, "" MKBITMAP ": invalid scaling factor -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case '1':
+ info.linear = 1;
+ break;
+ case '3':
+ info.linear = 0;
+ break;
+ case 'g':
+ info.bilevel = 0;
+ info.outext = ".pgm";
+ break;
+ case 't':
+ info.bilevel = 1;
+ info.outext = ".pbm";
+ info.level = strtod(optarg, &p);
+ if (*p || info.level<0) {
+ fprintf(stderr, "" MKBITMAP ": invalid threshold -- %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case '?':
+ fprintf(stderr, "Try --help for more info\n");
+ exit(1);
+ break;
+ default:
+ fprintf(stderr, "" MKBITMAP ": Unimplemented option -- %c\n", c);
+ exit(1);
+ }
+ }
+ info.infiles = &av[optind];
+ info.infilecount = ac-optind;
+ return;
+}
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary functions for file handling */
+
+/* open a file for reading. Return stdin if filename is NULL or "-" */
+static FILE *my_fopen_read(const char *filename) {
+ if (filename == NULL || strcmp(filename, "-") == 0) {
+ return stdin;
+ }
+ return fopen(filename, "rb");
+}
+
+/* open a file for writing. Return stdout if filename is NULL or "-" */
+static FILE *my_fopen_write(const char *filename) {
+ if (filename == NULL || strcmp(filename, "-") == 0) {
+ return stdout;
+ }
+ return fopen(filename, "wb");
+}
+
+/* close a file, but do nothing is filename is NULL or "-" */
+static void my_fclose(FILE *f, const char *filename) {
+ if (filename == NULL || strcmp(filename, "-") == 0) {
+ return;
+ }
+ fclose(f);
+}
+
+/* make output filename from input filename. Return an allocated value. */
+static char *make_outfilename(const char *infile, const char *ext) {
+ char *outfile;
+ char *p;
+
+ if (strcmp(infile, "-") == 0) {
+ return strdup("-");
+ }
+
+ outfile = (char *) malloc(strlen(infile)+strlen(ext)+5);
+ if (!outfile) {
+ return NULL;
+ }
+ strcpy(outfile, infile);
+ p = strrchr(outfile, '.');
+ if (p) {
+ *p = 0;
+ }
+ strcat(outfile, ext);
+
+ /* check that input and output filenames are different */
+ if (strcmp(infile, outfile) == 0) {
+ strcpy(outfile, infile);
+ strcat(outfile, "-out");
+ }
+
+ return outfile;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Main function */
+
+int main(int ac, char *av[]) {
+ FILE *fin, *fout;
+ int i;
+ char *outfile;
+
+ /* platform-specific initializations, e.g., set file i/o to binary */
+ platform_init();
+
+ /* process options */
+ dopts(ac, av);
+
+ /* there are several ways to call us:
+ mkbitmap -- stdin to stdout
+ mkbitmap -o outfile -- stdin to outfile
+ mkbitmap file... -- encode each file and generate outfile names
+ mkbitmap file... -o outfile -- concatenate files and write to outfile
+ */
+
+ if (info.infilecount == 0 && info.outfile == NULL) { /* stdin to stdout */
+
+ process_file(stdin, stdout, "stdin", "stdout");
+ return 0;
+
+ } else if (info.infilecount == 0) { /* stdin to outfile */
+
+ fout = my_fopen_write(info.outfile);
+ if (!fout) {
+ fprintf(stderr, "" MKBITMAP ": %s: %s\n", info.outfile, strerror(errno));
+ exit(2);
+ }
+ process_file(stdin, fout, "stdin", info.outfile);
+ my_fclose(fout, info.outfile);
+ free(info.outfile);
+ return 0;
+
+ } else if (info.outfile == NULL) { /* infiles -> multiple outfiles */
+
+ for (i=0; i<info.infilecount; i++) {
+ outfile = make_outfilename(info.infiles[i], info.outext);
+ if (!outfile) {
+ fprintf(stderr, "" MKBITMAP ": %s\n", strerror(errno));
+ exit(2);
+ }
+ fin = my_fopen_read(info.infiles[i]);
+ if (!fin) {
+ fprintf(stderr, "" MKBITMAP ": %s: %s\n", info.infiles[i], strerror(errno));
+ exit(2);
+ }
+ fout = my_fopen_write(outfile);
+ if (!fout) {
+ fprintf(stderr, "" MKBITMAP ": %s: %s\n", outfile, strerror(errno));
+ exit(2);
+ }
+ process_file(fin, fout, info.infiles[i], outfile);
+ my_fclose(fin, info.infiles[i]);
+ my_fclose(fout, outfile);
+ free(outfile);
+ }
+ return 0;
+
+ } else { /* infiles to single outfile */
+
+ fout = my_fopen_write(info.outfile);
+ if (!fout) {
+ fprintf(stderr, "" MKBITMAP ": %s: %s\n", info.outfile, strerror(errno));
+ exit(2);
+ }
+ for (i=0; i<info.infilecount; i++) {
+ fin = my_fopen_read(info.infiles[i]);
+ if (!fin) {
+ fprintf(stderr, "" MKBITMAP ": %s: %s\n", info.infiles[i], strerror(errno));
+ exit(2);
+ }
+ process_file(fin, fout, info.infiles[i], info.outfile);
+ my_fclose(fin, info.infiles[i]);
+ }
+ my_fclose(fout, info.outfile);
+ free(info.outfile);
+ return 0;
+
+ }
+
+ /* not reached */
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/platform.h b/Build/source/libs/potrace/potrace-src/src/platform.h
new file mode 100644
index 00000000000..f58bcc0d7ec
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/platform.h
@@ -0,0 +1,48 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* this header file contains some platform dependent stuff */
+
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/* in Windows and OS/2, set all file i/o to binary */
+#ifdef __MINGW32__
+#include <fcntl.h>
+unsigned int _CRT_fmode = _O_BINARY;
+static inline void platform_init(void) {
+ _setmode(_fileno(stdin), _O_BINARY);
+ _setmode(_fileno(stdout), _O_BINARY);
+}
+#else
+
+#ifdef __CYGWIN__
+#include <fcntl.h>
+#include <io.h>
+static inline void platform_init(void) {
+ setmode(0, O_BINARY);
+ setmode(1, O_BINARY);
+}
+#else
+
+#ifdef __OS2__
+#include <fcntl.h>
+static inline void platform_init(void) {
+ setmode(fileno(stdin), O_BINARY);
+ setmode(fileno(stdout), O_BINARY);
+}
+#else
+
+static inline void platform_init(void) {
+ /* NOP */
+}
+#endif
+#endif
+#endif
+
+#endif /* PLATFORM_H */
diff --git a/Build/source/libs/potrace/potrace-src/src/potracelib.c b/Build/source/libs/potrace/potrace-src/src/potracelib.c
new file mode 100644
index 00000000000..bf16e3f1747
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/potracelib.c
@@ -0,0 +1,114 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "potracelib.h"
+#include "curve.h"
+#include "decompose.h"
+#include "trace.h"
+#include "progress.h"
+
+/* default parameters */
+static const potrace_param_t param_default = {
+ 2, /* turdsize */
+ POTRACE_TURNPOLICY_MINORITY, /* turnpolicy */
+ 1.0, /* alphamax */
+ 1, /* opticurve */
+ 0.2, /* opttolerance */
+ {
+ NULL, /* callback function */
+ NULL, /* callback data */
+ 0.0, 1.0, /* progress range */
+ 0.0, /* granularity */
+ },
+};
+
+/* Return a fresh copy of the set of default parameters, or NULL on
+ failure with errno set. */
+potrace_param_t *potrace_param_default(void) {
+ potrace_param_t *p;
+
+ p = (potrace_param_t *) malloc(sizeof(potrace_param_t));
+ if (!p) {
+ return NULL;
+ }
+ memcpy(p, &param_default, sizeof(potrace_param_t));
+ return p;
+}
+
+/* On success, returns a Potrace state st with st->status ==
+ POTRACE_STATUS_OK. On failure, returns NULL if no Potrace state
+ could be created (with errno set), or returns an incomplete Potrace
+ state (with st->status == POTRACE_STATUS_INCOMPLETE, and with errno
+ set). Complete or incomplete Potrace state can be freed with
+ potrace_state_free(). */
+potrace_state_t *potrace_trace(const potrace_param_t *param, const potrace_bitmap_t *bm) {
+ int r;
+ path_t *plist = NULL;
+ potrace_state_t *st;
+ progress_t prog;
+ progress_t subprog;
+
+ /* prepare private progress bar state */
+ prog.callback = param->progress.callback;
+ prog.data = param->progress.data;
+ prog.min = param->progress.min;
+ prog.max = param->progress.max;
+ prog.epsilon = param->progress.epsilon;
+ prog.d_prev = param->progress.min;
+
+ /* allocate state object */
+ st = (potrace_state_t *)malloc(sizeof(potrace_state_t));
+ if (!st) {
+ return NULL;
+ }
+
+ progress_subrange_start(0.0, 0.1, &prog, &subprog);
+
+ /* process the image */
+ r = bm_to_pathlist(bm, &plist, param, &subprog);
+ if (r) {
+ free(st);
+ return NULL;
+ }
+
+ st->status = POTRACE_STATUS_OK;
+ st->plist = plist;
+ st->priv = NULL; /* private state currently unused */
+
+ progress_subrange_end(&prog, &subprog);
+
+ progress_subrange_start(0.1, 1.0, &prog, &subprog);
+
+ /* partial success. */
+ r = process_path(plist, param, &subprog);
+ if (r) {
+ st->status = POTRACE_STATUS_INCOMPLETE;
+ }
+
+ progress_subrange_end(&prog, &subprog);
+
+ return st;
+}
+
+/* free a Potrace state, without disturbing errno. */
+void potrace_state_free(potrace_state_t *st) {
+ pathlist_free(st->plist);
+ free(st);
+}
+
+/* free a parameter list, without disturbing errno. */
+void potrace_param_free(potrace_param_t *p) {
+ free(p);
+}
+
+const char *potrace_version(void) {
+ return "potracelib " VERSION "";
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/potracelib.h b/Build/source/libs/potrace/potrace-src/src/potracelib.h
new file mode 100644
index 00000000000..ae2f18c7ebc
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/potracelib.h
@@ -0,0 +1,139 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+#ifndef POTRACELIB_H
+#define POTRACELIB_H
+
+/* this file defines the API for the core Potrace library. For a more
+ detailed description of the API, see potracelib.pdf */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* ---------------------------------------------------------------------- */
+/* tracing parameters */
+
+/* turn policies */
+#define POTRACE_TURNPOLICY_BLACK 0
+#define POTRACE_TURNPOLICY_WHITE 1
+#define POTRACE_TURNPOLICY_LEFT 2
+#define POTRACE_TURNPOLICY_RIGHT 3
+#define POTRACE_TURNPOLICY_MINORITY 4
+#define POTRACE_TURNPOLICY_MAJORITY 5
+#define POTRACE_TURNPOLICY_RANDOM 6
+
+/* structure to hold progress bar callback data */
+struct potrace_progress_s {
+ void (*callback)(double progress, void *privdata); /* callback fn */
+ void *data; /* callback function's private data */
+ double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
+ double epsilon; /* granularity: can skip smaller increments */
+};
+typedef struct potrace_progress_s potrace_progress_t;
+
+/* structure to hold tracing parameters */
+struct potrace_param_s {
+ int turdsize; /* area of largest path to be ignored */
+ int turnpolicy; /* resolves ambiguous turns in path decomposition */
+ double alphamax; /* corner threshold */
+ int opticurve; /* use curve optimization? */
+ double opttolerance; /* curve optimization tolerance */
+ potrace_progress_t progress; /* progress callback function */
+};
+typedef struct potrace_param_s potrace_param_t;
+
+/* ---------------------------------------------------------------------- */
+/* bitmaps */
+
+/* native word size */
+typedef unsigned long potrace_word;
+
+/* Internal bitmap format. The n-th scanline starts at scanline(n) =
+ (map + n*dy). Raster data is stored as a sequence of potrace_words
+ (NOT bytes). The leftmost bit of scanline n is the most significant
+ bit of scanline(n)[0]. */
+struct potrace_bitmap_s {
+ int w, h; /* width and height, in pixels */
+ int dy; /* words per scanline (not bytes) */
+ potrace_word *map; /* raw data, dy*h words */
+};
+typedef struct potrace_bitmap_s potrace_bitmap_t;
+
+/* ---------------------------------------------------------------------- */
+/* curves */
+
+/* point */
+struct potrace_dpoint_s {
+ double x, y;
+};
+typedef struct potrace_dpoint_s potrace_dpoint_t;
+
+/* segment tags */
+#define POTRACE_CURVETO 1
+#define POTRACE_CORNER 2
+
+/* closed curve segment */
+struct potrace_curve_s {
+ int n; /* number of segments */
+ int *tag; /* tag[n]: POTRACE_CURVETO or POTRACE_CORNER */
+ potrace_dpoint_t (*c)[3]; /* c[n][3]: control points.
+ c[n][0] is unused for tag[n]=POTRACE_CORNER */
+};
+typedef struct potrace_curve_s potrace_curve_t;
+
+/* Linked list of signed curve segments. Also carries a tree structure. */
+struct potrace_path_s {
+ int area; /* area of the bitmap path */
+ int sign; /* '+' or '-', depending on orientation */
+ potrace_curve_t curve; /* this path's vector data */
+
+ struct potrace_path_s *next; /* linked list structure */
+
+ struct potrace_path_s *childlist; /* tree structure */
+ struct potrace_path_s *sibling; /* tree structure */
+
+ struct potrace_privpath_s *priv; /* private state */
+};
+typedef struct potrace_path_s potrace_path_t;
+
+/* ---------------------------------------------------------------------- */
+/* Potrace state */
+
+#define POTRACE_STATUS_OK 0
+#define POTRACE_STATUS_INCOMPLETE 1
+
+struct potrace_state_s {
+ int status;
+ potrace_path_t *plist; /* vector data */
+
+ struct potrace_privstate_s *priv; /* private state */
+};
+typedef struct potrace_state_s potrace_state_t;
+
+/* ---------------------------------------------------------------------- */
+/* API functions */
+
+/* get default parameters */
+potrace_param_t *potrace_param_default(void);
+
+/* free parameter set */
+void potrace_param_free(potrace_param_t *p);
+
+/* trace a bitmap */
+potrace_state_t *potrace_trace(const potrace_param_t *param,
+ const potrace_bitmap_t *bm);
+
+/* free a Potrace state */
+void potrace_state_free(potrace_state_t *st);
+
+/* return a static plain text version string identifying this version
+ of potracelib */
+const char *potrace_version(void);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* POTRACELIB_H */
diff --git a/Build/source/libs/potrace/potrace-src/src/potracelib_demo.c b/Build/source/libs/potrace/potrace-src/src/potracelib_demo.c
new file mode 100644
index 00000000000..295c6ee1c6c
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/potracelib_demo.c
@@ -0,0 +1,148 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* A simple and self-contained demo of the potracelib API */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "potracelib.h"
+
+#define WIDTH 250
+#define HEIGHT 250
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary bitmap functions */
+
+/* macros for writing individual bitmap pixels */
+#define BM_WORDSIZE ((int)sizeof(potrace_word))
+#define BM_WORDBITS (8*BM_WORDSIZE)
+#define BM_HIBIT (((potrace_word)1)<<(BM_WORDBITS-1))
+#define bm_scanline(bm, y) ((bm)->map + (y)*(bm)->dy)
+#define bm_index(bm, x, y) (&bm_scanline(bm, y)[(x)/BM_WORDBITS])
+#define bm_mask(x) (BM_HIBIT >> ((x) & (BM_WORDBITS-1)))
+#define bm_range(x, a) ((int)(x) >= 0 && (int)(x) < (a))
+#define bm_safe(bm, x, y) (bm_range(x, (bm)->w) && bm_range(y, (bm)->h))
+#define BM_USET(bm, x, y) (*bm_index(bm, x, y) |= bm_mask(x))
+#define BM_UCLR(bm, x, y) (*bm_index(bm, x, y) &= ~bm_mask(x))
+#define BM_UPUT(bm, x, y, b) ((b) ? BM_USET(bm, x, y) : BM_UCLR(bm, x, y))
+#define BM_PUT(bm, x, y, b) (bm_safe(bm, x, y) ? BM_UPUT(bm, x, y, b) : 0)
+
+/* return new un-initialized bitmap. NULL with errno on error */
+static potrace_bitmap_t *bm_new(int w, int h) {
+ potrace_bitmap_t *bm;
+ int dy = (w + BM_WORDBITS - 1) / BM_WORDBITS;
+
+ bm = (potrace_bitmap_t *) malloc(sizeof(potrace_bitmap_t));
+ if (!bm) {
+ return NULL;
+ }
+ bm->w = w;
+ bm->h = h;
+ bm->dy = dy;
+ bm->map = (potrace_word *) calloc(h, dy * BM_WORDSIZE);
+ if (!bm->map) {
+ free(bm);
+ return NULL;
+ }
+ return bm;
+}
+
+/* free a bitmap */
+static void bm_free(potrace_bitmap_t *bm) {
+ if (bm != NULL) {
+ free(bm->map);
+ }
+ free(bm);
+}
+
+/* ---------------------------------------------------------------------- */
+/* demo */
+
+int main() {
+ int x, y, i;
+ potrace_bitmap_t *bm;
+ potrace_param_t *param;
+ potrace_path_t *p;
+ potrace_state_t *st;
+ int n, *tag;
+ potrace_dpoint_t (*c)[3];
+
+ /* create a bitmap */
+ bm = bm_new(WIDTH, HEIGHT);
+ if (!bm) {
+ fprintf(stderr, "Error allocating bitmap: %s\n", strerror(errno));
+ return 1;
+ }
+
+ /* fill the bitmap with some pattern */
+ for (y=0; y<HEIGHT; y++) {
+ for (x=0; x<WIDTH; x++) {
+ BM_PUT(bm, x, y, ((x*x + y*y*y) % 10000 < 5000) ? 1 : 0);
+ }
+ }
+
+ /* set tracing parameters, starting from defaults */
+ param = potrace_param_default();
+ if (!param) {
+ fprintf(stderr, "Error allocating parameters: %s\n", strerror(errno));
+ return 1;
+ }
+ param->turdsize = 0;
+
+ /* trace the bitmap */
+ st = potrace_trace(param, bm);
+ if (!st || st->status != POTRACE_STATUS_OK) {
+ fprintf(stderr, "Error tracing bitmap: %s\n", strerror(errno));
+ return 1;
+ }
+ bm_free(bm);
+
+ /* output vector data, e.g. as a rudimentary EPS file */
+ printf("%%!PS-Adobe-3.0 EPSF-3.0\n");
+ printf("%%%%BoundingBox: 0 0 %d %d\n", WIDTH, HEIGHT);
+ printf("gsave\n");
+
+ /* draw each curve */
+ p = st->plist;
+ while (p != NULL) {
+ n = p->curve.n;
+ tag = p->curve.tag;
+ c = p->curve.c;
+ printf("%f %f moveto\n", c[n-1][2].x, c[n-1][2].y);
+ for (i=0; i<n; i++) {
+ switch (tag[i]) {
+ case POTRACE_CORNER:
+ printf("%f %f lineto\n", c[i][1].x, c[i][1].y);
+ printf("%f %f lineto\n", c[i][2].x, c[i][2].y);
+ break;
+ case POTRACE_CURVETO:
+ printf("%f %f %f %f %f %f curveto\n",
+ c[i][0].x, c[i][0].y,
+ c[i][1].x, c[i][1].y,
+ c[i][2].x, c[i][2].y);
+ break;
+ }
+ }
+ /* at the end of a group of a positive path and its negative
+ children, fill. */
+ if (p->next == NULL || p->next->sign == '+') {
+ printf("0 setgray fill\n");
+ }
+ p = p->next;
+ }
+ printf("grestore\n");
+ printf("%%EOF\n");
+
+ potrace_state_free(st);
+ potrace_param_free(param);
+
+ return 0;
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/progress.h b/Build/source/libs/potrace/potrace-src/src/progress.h
new file mode 100644
index 00000000000..5123368a7e8
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/progress.h
@@ -0,0 +1,79 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* operations on potrace_progress_t objects, which are defined in
+ potracelib.h. Note: the code attempts to minimize runtime overhead
+ when no progress monitoring was requested. It also tries to
+ minimize excessive progress calculations beneath the "epsilon"
+ threshold. */
+
+#ifndef PROGRESS_H
+#define PROGRESS_H
+
+/* structure to hold progress bar callback data */
+struct progress_s {
+ void (*callback)(double progress, void *privdata); /* callback fn */
+ void *data; /* callback function's private data */
+ double min, max; /* desired range of progress, e.g. 0.0 to 1.0 */
+ double epsilon; /* granularity: can skip smaller increments */
+ double b; /* upper limit of subrange in superrange units */
+ double d_prev; /* previous value of d */
+};
+typedef struct progress_s progress_t;
+
+/* notify given progress object of current progress. Note that d is
+ given in the 0.0-1.0 range, which will be scaled and translated to
+ the progress object's range. */
+static inline void progress_update(double d, progress_t *prog) {
+ double d_scaled;
+
+ if (prog != NULL && prog->callback != NULL) {
+ d_scaled = prog->min * (1-d) + prog->max * d;
+ if (d == 1.0 || d_scaled >= prog->d_prev + prog->epsilon) {
+ prog->callback(prog->min * (1-d) + prog->max * d, prog->data);
+ prog->d_prev = d_scaled;
+ }
+ }
+}
+
+/* start a subrange of the given progress object. The range is
+ narrowed to [a..b], relative to 0.0-1.0 coordinates. If new range
+ is below granularity threshold, disable further subdivisions. */
+static inline void progress_subrange_start(double a, double b, const progress_t *prog, progress_t *sub) {
+ double min, max;
+
+ if (prog == NULL || prog->callback == NULL) {
+ sub->callback = NULL;
+ return;
+ }
+
+ min = prog->min * (1-a) + prog->max * a;
+ max = prog->min * (1-b) + prog->max * b;
+
+ if (max - min < prog->epsilon) {
+ sub->callback = NULL; /* no further progress info in subrange */
+ sub->b = b;
+ return;
+ }
+ sub->callback = prog->callback;
+ sub->data = prog->data;
+ sub->epsilon = prog->epsilon;
+ sub->min = min;
+ sub->max = max;
+ sub->d_prev = prog->d_prev;
+ return;
+}
+
+static inline void progress_subrange_end(progress_t *prog, progress_t *sub) {
+ if (prog != NULL && prog->callback != NULL) {
+ if (sub->callback == NULL) {
+ progress_update(sub->b, prog);
+ } else {
+ prog->d_prev = sub->d_prev;
+ }
+ }
+}
+
+#endif /* PROGRESS_H */
+
diff --git a/Build/source/libs/potrace/potrace-src/src/progress_bar.c b/Build/source/libs/potrace/potrace-src/src/progress_bar.c
new file mode 100644
index 00000000000..4307f08234c
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/progress_bar.c
@@ -0,0 +1,207 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* functions to render a progress bar for main.c. We provide a
+ standard and a simplified progress bar. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "potracelib.h"
+#include "progress_bar.h"
+
+/* ---------------------------------------------------------------------- */
+/* vt100 progress bar */
+
+#define COL0 "\033[G" /* reset cursor to column 0 */
+
+struct vt100_progress_s {
+ char name[22]; /* filename for status bar */
+ double dnext; /* threshold value for next tick */
+};
+typedef struct vt100_progress_s vt100_progress_t;
+
+/* print a progress bar using vt100 control characters. This is a
+ callback function that is potentially called often; thus, it has
+ been optimized for the typical case, which is when the progress bar
+ does not need updating. */
+static void vt100_progress(double d, void *data) {
+ vt100_progress_t *p = (vt100_progress_t *)data;
+ static char b[] = "========================================";
+ int tick; /* number of visible tickmarks, 0..40 */
+ int perc; /* visible percentage, 0..100 */
+
+ /* note: the 0.01 and 0.025 ensure that we always end on 40
+ tickmarks and 100%, despite any rounding errors. The 0.995
+ ensures that tick always increases when d >= p->dnext. */
+ if (d >= p->dnext) {
+ tick = (int) floor(d*40+0.01);
+ perc = (int) floor(d*100+0.025);
+ fprintf(stderr, "%-21s |%-40s| %d%% " COL0 "", p->name, b+40-tick, perc);
+ fflush(stderr);
+ p->dnext = (tick+0.995) / 40.0;
+ }
+}
+
+/* Initialize progress bar. Return 0 on success or 1 on failure with
+ errno set. */
+static int init_vt100_progress(potrace_progress_t *prog, const char *filename, int count) {
+ vt100_progress_t *p;
+ const char *q, *s;
+ int len;
+
+ p = (vt100_progress_t *) malloc(sizeof(vt100_progress_t));
+ if (!p) {
+ return 1;
+ }
+
+ /* initialize callback function's data */
+ p->dnext = 0;
+
+ if (count != 0) {
+ sprintf(p->name, " (p.%d):", count+1);
+ } else {
+ s = filename;
+ if ((q = strrchr(s, '/')) != NULL) {
+ s = q+1;
+ }
+ len = strlen(s);
+ strncpy(p->name, s, 21);
+ p->name[20] = 0;
+ if (len > 20) {
+ p->name[17] = '.';
+ p->name[18] = '.';
+ p->name[19] = '.';
+ }
+ strcat(p->name, ":");
+ }
+
+ /* initialize progress parameters */
+ prog->callback = &vt100_progress;
+ prog->data = (void *)p;
+ prog->min = 0.0;
+ prog->max = 1.0;
+ prog->epsilon = 0.0;
+
+ /* draw first progress bar */
+ vt100_progress(0.0, prog->data);
+ return 0;
+}
+
+/* Finalize the progress bar. */
+static void term_vt100_progress(potrace_progress_t *prog) {
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ free(prog->data);
+ return;
+}
+
+/* progress bar interface structure */
+static progress_bar_t progress_bar_vt100_struct = {
+ init_vt100_progress,
+ term_vt100_progress,
+};
+progress_bar_t *progress_bar_vt100 = &progress_bar_vt100_struct;
+
+/* ---------------------------------------------------------------------- */
+/* another progress bar for dumb terminals */
+
+struct simplified_progress_s {
+ int n; /* number of ticks displayed so far */
+ double dnext; /* threshold value for next tick */
+};
+typedef struct simplified_progress_s simplified_progress_t;
+
+/* print a simplified progress bar, not using any special tty control
+ codes. Optimized for frequent calling. */
+static void simplified_progress(double d, void *data) {
+ simplified_progress_t *p = (simplified_progress_t *)data;
+ int tick; /* number of visible tickmarks, 0..40 */
+
+ /* note: the 0.01 and 0.025 ensure that we always end on 40
+ tickmarks and 100%, despite any rounding errors. The 0.995
+ ensures that tick always increases when d >= p->dnext. */
+ if (d >= p->dnext) {
+ tick = (int) floor(d*40+0.01);
+ while (p->n < tick) {
+ fputc('=', stderr);
+ p->n++;
+ }
+ fflush(stderr);
+ p->dnext = (tick+0.995) / 40.0;
+ }
+}
+
+/* Initialize parameters for simplified progress bar. Return 0 on
+ success or 1 on error with errno set. */
+static int init_simplified_progress(potrace_progress_t *prog, const char *filename, int count) {
+ simplified_progress_t *p;
+ const char *q, *s;
+ int len;
+ char buf[22];
+
+ p = (simplified_progress_t *) malloc(sizeof(simplified_progress_t));
+ if (!p) {
+ return 1;
+ }
+
+ /* initialize callback function's data */
+ p->n = 0;
+ p->dnext = 0;
+
+ if (count != 0) {
+ sprintf(buf, " (p.%d):", count+1);
+ } else {
+ s = filename;
+ if ((q = strrchr(s, '/')) != NULL) {
+ s = q+1;
+ }
+ len = strlen(s);
+ strncpy(buf, s, 21);
+ buf[20] = 0;
+ if (len > 20) {
+ buf[17] = '.';
+ buf[18] = '.';
+ buf[19] = '.';
+ }
+ strcat(buf, ":");
+ }
+
+ fprintf(stderr, "%-21s |", buf);
+
+ /* initialize progress parameters */
+ prog->callback = &simplified_progress;
+ prog->data = (void *)p;
+ prog->min = 0.0;
+ prog->max = 1.0;
+ prog->epsilon = 0.0;
+
+ /* draw first progress bar */
+ simplified_progress(0.0, prog->data);
+ return 0;
+}
+
+static void term_simplified_progress(potrace_progress_t *prog) {
+ simplified_progress_t *p = (simplified_progress_t *)prog->data;
+
+ simplified_progress(1.0, (void *)p);
+ fprintf(stderr, "| 100%%\n");
+ fflush(stderr);
+ free(p);
+ return;
+}
+
+/* progress bar interface structure */
+static progress_bar_t progress_bar_simplified_struct = {
+ init_simplified_progress,
+ term_simplified_progress,
+};
+progress_bar_t *progress_bar_simplified = &progress_bar_simplified_struct;
+
diff --git a/Build/source/libs/potrace/potrace-src/src/progress_bar.h b/Build/source/libs/potrace/potrace-src/src/progress_bar.h
new file mode 100644
index 00000000000..e98af14c388
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/progress_bar.h
@@ -0,0 +1,26 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* functions to render a progress bar for main.c. We provide a
+ standard and a simplified progress bar. */
+
+#ifndef PROGRESS_BAR_H
+#define PROGRESS_BAR_H
+
+#include "potracelib.h"
+
+/* structure to hold a progress bar interface */
+struct progress_bar_s {
+ int (*init)(potrace_progress_t *prog, const char *filename, int count);
+ void (*term)(potrace_progress_t *prog);
+};
+typedef struct progress_bar_s progress_bar_t;
+
+extern progress_bar_t *progress_bar_vt100;
+extern progress_bar_t *progress_bar_simplified;
+
+
+
+#endif /* PROGRESS_BAR_H */
+
diff --git a/Build/source/libs/potrace/potrace-src/src/render.c b/Build/source/libs/potrace/potrace-src/src/render.c
new file mode 100644
index 00000000000..7bf9b8a8e89
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/render.c
@@ -0,0 +1,245 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#include "render.h"
+#include "greymap.h"
+#include "auxiliary.h"
+
+/* ---------------------------------------------------------------------- */
+/* routines for anti-aliased rendering of curves */
+
+/* we use the following method. Given a point (x,y) (with real-valued
+ coordinates) in the plane, let (xi,yi) be the integer part of the
+ coordinates, i.e., xi=floor(x), yi=floor(y). Define a path from
+ (x,y) to infinity as follows: path(x,y) =
+ (x,y)--(xi+1,y)--(xi+1,yi)--(+infty,yi). Now as the point (x,y)
+ moves smoothly across the plane, the path path(x,y) sweeps
+ (non-smoothly) across a certain area. We proportionately blacken
+ the area as the path moves "downward", and we whiten the area as
+ the path moves "upward". This way, after the point has traversed a
+ closed curve, the interior of the curve has been darkened
+ (counterclockwise movement) or lightened (clockwise movement). (The
+ "grey shift" is actually proportional to the winding number). By
+ choosing the above path with mostly integer coordinates, we achieve
+ that only pixels close to (x,y) receive grey values and are subject
+ to round-off errors. The grey value of pixels far away from (x,y)
+ is always in "integer" (where 0=black, 1=white). As a special
+ trick, we keep an accumulator rm->a1, which holds a double value to
+ be added to the grey value to be added to the current pixel
+ (xi,yi). Only when changing "current" pixels, we convert this
+ double value to an integer. This way we avoid round-off errors at
+ the meeting points of line segments. Another speedup measure is
+ that we sometimes use the rm->incrow_buf array to postpone
+ incrementing or decrementing an entire row. If incrow_buf[y]=x+1!=0,
+ then all the pixels (x,y),(x+1,y),(x+2,y),... are scheduled to be
+ incremented/decremented (which one is the case will be clear from
+ context). This keeps the greymap operations reasonably local. */
+
+/* allocate a new rendering state */
+render_t *render_new(greymap_t *gm) {
+ render_t *rm;
+
+ rm = (render_t *) malloc(sizeof(render_t));
+ if (!rm) {
+ return NULL;
+ }
+ memset(rm, 0, sizeof(render_t));
+ rm->gm = gm;
+ rm->incrow_buf = (int *) calloc(gm->h, sizeof(int));
+ if (!rm->incrow_buf) {
+ free(rm);
+ return NULL;
+ }
+ return rm;
+}
+
+/* free a given rendering state. Note: this does not free the
+ underlying greymap. */
+void render_free(render_t *rm) {
+ free(rm->incrow_buf);
+ free(rm);
+}
+
+/* close path */
+void render_close(render_t *rm) {
+ if (rm->x0 != rm->x1 || rm->y0 != rm->y1) {
+ render_lineto(rm, rm->x0, rm->y0);
+ }
+ GM_INC(rm->gm, rm->x0i, rm->y0i, (rm->a0+rm->a1)*255);
+
+ /* assert (rm->x0i != rm->x1i || rm->y0i != rm->y1i); */
+
+ /* the persistent state is now undefined */
+}
+
+/* move point */
+void render_moveto(render_t *rm, double x, double y) {
+ /* close the previous path */
+ render_close(rm);
+
+ rm->x0 = rm->x1 = x;
+ rm->y0 = rm->y1 = y;
+ rm->x0i = (int)floor(rm->x0);
+ rm->x1i = (int)floor(rm->x1);
+ rm->y0i = (int)floor(rm->y0);
+ rm->y1i = (int)floor(rm->y1);
+ rm->a0 = rm->a1 = 0;
+}
+
+/* add b to pixels (x,y) and all pixels to the right of it. However,
+ use rm->incrow_buf as a buffer to economize on multiple calls */
+static void incrow(render_t *rm, int x, int y, int b) {
+ int i, x0;
+
+ if (y < 0 || y >= rm->gm->h) {
+ return;
+ }
+
+ if (x < 0) {
+ x = 0;
+ } else if (x > rm->gm->w) {
+ x = rm->gm->w;
+ }
+ if (rm->incrow_buf[y] == 0) {
+ rm->incrow_buf[y] = x+1; /* store x+1 so that we can use 0 for "vacant" */
+ return;
+ }
+ x0 = rm->incrow_buf[y]-1;
+ rm->incrow_buf[y] = 0;
+ if (x0 < x) {
+ for (i=x0; i<x; i++) {
+ GM_INC(rm->gm, i, y, -b);
+ }
+ } else {
+ for (i=x; i<x0; i++) {
+ GM_INC(rm->gm, i, y, b);
+ }
+ }
+}
+
+/* render a straight line */
+void render_lineto(render_t *rm, double x2, double y2) {
+ int x2i, y2i;
+ double t0=2, s0=2;
+ int sn, tn;
+ double ss=2, ts=2;
+ double r0, r1;
+ int i, j;
+ int rxi, ryi;
+ int s;
+
+ x2i = (int)floor(x2);
+ y2i = (int)floor(y2);
+
+ sn = abs(x2i - rm->x1i);
+ tn = abs(y2i - rm->y1i);
+
+ if (sn) {
+ s0 = ((x2>rm->x1 ? rm->x1i+1 : rm->x1i) - rm->x1)/(x2-rm->x1);
+ ss = fabs(1.0/(x2-rm->x1));
+ }
+ if (tn) {
+ t0 = ((y2>rm->y1 ? rm->y1i+1 : rm->y1i) - rm->y1)/(y2-rm->y1);
+ ts = fabs(1.0/(y2-rm->y1));
+ }
+
+ r0 = 0;
+
+ i = 0;
+ j = 0;
+
+ rxi = rm->x1i;
+ ryi = rm->y1i;
+
+ while (i<sn || j<tn) {
+ if (j>=tn || (i<sn && s0+i*ss < t0+j*ts)) {
+ r1 = s0+i*ss;
+ i++;
+ s = 1;
+ } else {
+ r1 = t0+j*ts;
+ j++;
+ s = 0;
+ }
+ /* render line from r0 to r1 segment of (rm->x1,rm->y1)..(x2,y2) */
+
+ /* move point to r1 */
+ rm->a1 += (r1-r0)*(y2-rm->y1)*(rxi+1-((r0+r1)/2.0*(x2-rm->x1)+rm->x1));
+
+ /* move point across pixel boundary */
+ if (s && x2>rm->x1) {
+ GM_INC(rm->gm, rxi, ryi, rm->a1*255);
+ rm->a1 = 0;
+ rxi++;
+ rm->a1 += rm->y1+r1*(y2-rm->y1)-ryi;
+ } else if (!s && y2>rm->y1) {
+ GM_INC(rm->gm, rxi, ryi, rm->a1*255);
+ rm->a1 = 0;
+ incrow(rm, rxi+1, ryi, 255);
+ ryi++;
+ } else if (s && x2<=rm->x1) {
+ rm->a1 -= rm->y1+r1*(y2-rm->y1)-ryi;
+ GM_INC(rm->gm, rxi, ryi, rm->a1*255);
+ rm->a1 = 0;
+ rxi--;
+ } else if (!s && y2<=rm->y1) {
+ GM_INC(rm->gm, rxi, ryi, rm->a1*255);
+ rm->a1 = 0;
+ ryi--;
+ incrow(rm, rxi+1, ryi, -255);
+ }
+
+ r0 = r1;
+ }
+
+ /* move point to (x2,y2) */
+
+ r1 = 1;
+ rm->a1 += (r1-r0)*(y2-rm->y1)*(rxi+1-((r0+r1)/2.0*(x2-rm->x1)+rm->x1));
+
+ rm->x1i = x2i;
+ rm->y1i = y2i;
+ rm->x1 = x2;
+ rm->y1 = y2;
+
+ /* assert (rxi != rm->x1i || ryi != rm->y1i); */
+}
+
+/* render a Bezier curve. */
+void render_curveto(render_t *rm, double x2, double y2, double x3, double y3, double x4, double y4) {
+ double x1, y1, dd0, dd1, dd, delta, e2, epsilon, t;
+
+ x1 = rm->x1; /* starting point */
+ y1 = rm->y1;
+
+ /* we approximate the curve by small line segments. The interval
+ size, epsilon, is determined on the fly so that the distance
+ between the true curve and its approximation does not exceed the
+ desired accuracy delta. */
+
+ delta = .1; /* desired accuracy, in pixels */
+
+ /* let dd = maximal value of 2nd derivative over curve - this must
+ occur at an endpoint. */
+ dd0 = sq(x1-2*x2+x3) + sq(y1-2*y2+y3);
+ dd1 = sq(x2-2*x3+x4) + sq(y2-2*y3+y4);
+ dd = 6*sqrt(max(dd0, dd1));
+ e2 = 8*delta <= dd ? 8*delta/dd : 1;
+ epsilon = sqrt(e2); /* necessary interval size */
+
+ for (t=epsilon; t<1; t+=epsilon) {
+ render_lineto(rm, x1*cu(1-t)+3*x2*sq(1-t)*t+3*x3*(1-t)*sq(t)+x4*cu(t),
+ y1*cu(1-t)+3*y2*sq(1-t)*t+3*y3*(1-t)*sq(t)+y4*cu(t));
+ }
+ render_lineto(rm, x4, y4);
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/render.h b/Build/source/libs/potrace/potrace-src/src/render.h
new file mode 100644
index 00000000000..3168eb39cfa
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/render.h
@@ -0,0 +1,27 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef RENDER_H
+#define RENDER_H
+
+#include "greymap.h"
+
+struct render_s {
+ greymap_t *gm;
+ double x0, y0, x1, y1;
+ int x0i, y0i, x1i, y1i;
+ double a0, a1;
+ int *incrow_buf;
+};
+typedef struct render_s render_t;
+
+render_t *render_new(greymap_t *gm);
+void render_free(render_t *rm);
+void render_close(render_t *rm);
+void render_moveto(render_t *rm, double x, double y);
+void render_lineto(render_t *rm, double x, double y);
+void render_curveto(render_t *rm, double x2, double y2, double x3, double y3, double x4, double y4);
+
+#endif /* RENDER_H */
diff --git a/Build/source/libs/potrace/potrace-src/src/trace.c b/Build/source/libs/potrace/potrace-src/src/trace.c
new file mode 100644
index 00000000000..b830764447b
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/trace.c
@@ -0,0 +1,1249 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* transform jaggy paths into smooth curves */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "potracelib.h"
+#include "curve.h"
+#include "lists.h"
+#include "auxiliary.h"
+#include "trace.h"
+#include "progress.h"
+
+#define INFTY 10000000 /* it suffices that this is longer than any
+ path; it need not be really infinite */
+#define COS179 -0.999847695156 /* the cosine of 179 degrees */
+
+/* ---------------------------------------------------------------------- */
+#define SAFE_CALLOC(var, n, typ) \
+ if ((var = (typ *)calloc(n, sizeof(typ))) == NULL) goto calloc_error
+
+/* ---------------------------------------------------------------------- */
+/* auxiliary functions */
+
+/* return a direction that is 90 degrees counterclockwise from p2-p0,
+ but then restricted to one of the major wind directions (n, nw, w, etc) */
+static inline point_t dorth_infty(dpoint_t p0, dpoint_t p2) {
+ point_t r;
+
+ r.y = sign(p2.x-p0.x);
+ r.x = -sign(p2.y-p0.y);
+
+ return r;
+}
+
+/* return (p1-p0)x(p2-p0), the area of the parallelogram */
+static inline double dpara(dpoint_t p0, dpoint_t p1, dpoint_t p2) {
+ double x1, y1, x2, y2;
+
+ x1 = p1.x-p0.x;
+ y1 = p1.y-p0.y;
+ x2 = p2.x-p0.x;
+ y2 = p2.y-p0.y;
+
+ return x1*y2 - x2*y1;
+}
+
+/* ddenom/dpara have the property that the square of radius 1 centered
+ at p1 intersects the line p0p2 iff |dpara(p0,p1,p2)| <= ddenom(p0,p2) */
+static inline double ddenom(dpoint_t p0, dpoint_t p2) {
+ point_t r = dorth_infty(p0, p2);
+
+ return r.y*(p2.x-p0.x) - r.x*(p2.y-p0.y);
+}
+
+/* return 1 if a <= b < c < a, in a cyclic sense (mod n) */
+static inline int cyclic(int a, int b, int c) {
+ if (a<=c) {
+ return (a<=b && b<c);
+ } else {
+ return (a<=b || b<c);
+ }
+}
+
+/* determine the center and slope of the line i..j. Assume i<j. Needs
+ "sum" components of p to be set. */
+static void pointslope(privpath_t *pp, int i, int j, dpoint_t *ctr, dpoint_t *dir) {
+ /* assume i<j */
+
+ int n = pp->len;
+ sums_t *sums = pp->sums;
+
+ double x, y, x2, xy, y2;
+ double k;
+ double a, b, c, lambda2, l;
+ int r=0; /* rotations from i to j */
+
+ while (j>=n) {
+ j-=n;
+ r+=1;
+ }
+ while (i>=n) {
+ i-=n;
+ r-=1;
+ }
+ while (j<0) {
+ j+=n;
+ r-=1;
+ }
+ while (i<0) {
+ i+=n;
+ r+=1;
+ }
+
+ x = sums[j+1].x-sums[i].x+r*sums[n].x;
+ y = sums[j+1].y-sums[i].y+r*sums[n].y;
+ x2 = sums[j+1].x2-sums[i].x2+r*sums[n].x2;
+ xy = sums[j+1].xy-sums[i].xy+r*sums[n].xy;
+ y2 = sums[j+1].y2-sums[i].y2+r*sums[n].y2;
+ k = j+1-i+r*n;
+
+ ctr->x = x/k;
+ ctr->y = y/k;
+
+ a = (x2-(double)x*x/k)/k;
+ b = (xy-(double)x*y/k)/k;
+ c = (y2-(double)y*y/k)/k;
+
+ lambda2 = (a+c+sqrt((a-c)*(a-c)+4*b*b))/2; /* larger e.value */
+
+ /* now find e.vector for lambda2 */
+ a -= lambda2;
+ c -= lambda2;
+
+ if (fabs(a) >= fabs(c)) {
+ l = sqrt(a*a+b*b);
+ if (l!=0) {
+ dir->x = -b/l;
+ dir->y = a/l;
+ }
+ } else {
+ l = sqrt(c*c+b*b);
+ if (l!=0) {
+ dir->x = -c/l;
+ dir->y = b/l;
+ }
+ }
+ if (l==0) {
+ dir->x = dir->y = 0; /* sometimes this can happen when k=4:
+ the two eigenvalues coincide */
+ }
+}
+
+/* the type of (affine) quadratic forms, represented as symmetric 3x3
+ matrices. The value of the quadratic form at a vector (x,y) is v^t
+ Q v, where v = (x,y,1)^t. */
+typedef double quadform_t[3][3];
+
+/* Apply quadratic form Q to vector w = (w.x,w.y) */
+static inline double quadform(quadform_t Q, dpoint_t w) {
+ double v[3];
+ int i, j;
+ double sum;
+
+ v[0] = w.x;
+ v[1] = w.y;
+ v[2] = 1;
+ sum = 0.0;
+
+ for (i=0; i<3; i++) {
+ for (j=0; j<3; j++) {
+ sum += v[i] * Q[i][j] * v[j];
+ }
+ }
+ return sum;
+}
+
+/* calculate p1 x p2 */
+static inline int xprod(point_t p1, point_t p2) {
+ return p1.x*p2.y - p1.y*p2.x;
+}
+
+/* calculate (p1-p0)x(p3-p2) */
+static inline double cprod(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+ double x1, y1, x2, y2;
+
+ x1 = p1.x - p0.x;
+ y1 = p1.y - p0.y;
+ x2 = p3.x - p2.x;
+ y2 = p3.y - p2.y;
+
+ return x1*y2 - x2*y1;
+}
+
+/* calculate (p1-p0)*(p2-p0) */
+static inline double iprod(dpoint_t p0, dpoint_t p1, dpoint_t p2) {
+ double x1, y1, x2, y2;
+
+ x1 = p1.x - p0.x;
+ y1 = p1.y - p0.y;
+ x2 = p2.x - p0.x;
+ y2 = p2.y - p0.y;
+
+ return x1*x2 + y1*y2;
+}
+
+/* calculate (p1-p0)*(p3-p2) */
+static inline double iprod1(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+ double x1, y1, x2, y2;
+
+ x1 = p1.x - p0.x;
+ y1 = p1.y - p0.y;
+ x2 = p3.x - p2.x;
+ y2 = p3.y - p2.y;
+
+ return x1*x2 + y1*y2;
+}
+
+/* calculate distance between two points */
+static inline double ddist(dpoint_t p, dpoint_t q) {
+ return sqrt(sq(p.x-q.x)+sq(p.y-q.y));
+}
+
+/* calculate point of a bezier curve */
+static inline dpoint_t bezier(double t, dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3) {
+ double s = 1-t;
+ dpoint_t res;
+
+ /* Note: a good optimizing compiler (such as gcc-3) reduces the
+ following to 16 multiplications, using common subexpression
+ elimination. */
+
+ res.x = s*s*s*p0.x + 3*(s*s*t)*p1.x + 3*(t*t*s)*p2.x + t*t*t*p3.x;
+ res.y = s*s*s*p0.y + 3*(s*s*t)*p1.y + 3*(t*t*s)*p2.y + t*t*t*p3.y;
+
+ return res;
+}
+
+/* calculate the point t in [0..1] on the (convex) bezier curve
+ (p0,p1,p2,p3) which is tangent to q1-q0. Return -1.0 if there is no
+ solution in [0..1]. */
+static double tangent(dpoint_t p0, dpoint_t p1, dpoint_t p2, dpoint_t p3, dpoint_t q0, dpoint_t q1) {
+ double A, B, C; /* (1-t)^2 A + 2(1-t)t B + t^2 C = 0 */
+ double a, b, c; /* a t^2 + b t + c = 0 */
+ double d, s, r1, r2;
+
+ A = cprod(p0, p1, q0, q1);
+ B = cprod(p1, p2, q0, q1);
+ C = cprod(p2, p3, q0, q1);
+
+ a = A - 2*B + C;
+ b = -2*A + 2*B;
+ c = A;
+
+ d = b*b - 4*a*c;
+
+ if (a==0 || d<0) {
+ return -1.0;
+ }
+
+ s = sqrt(d);
+
+ r1 = (-b + s) / (2 * a);
+ r2 = (-b - s) / (2 * a);
+
+ if (r1 >= 0 && r1 <= 1) {
+ return r1;
+ } else if (r2 >= 0 && r2 <= 1) {
+ return r2;
+ } else {
+ return -1.0;
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* Preparation: fill in the sum* fields of a path (used for later
+ rapid summing). Return 0 on success, 1 with errno set on
+ failure. */
+static int calc_sums(privpath_t *pp) {
+ int i, x, y;
+ int n = pp->len;
+
+ SAFE_CALLOC(pp->sums, pp->len+1, sums_t);
+
+ /* origin */
+ pp->x0 = pp->pt[0].x;
+ pp->y0 = pp->pt[0].y;
+
+ /* preparatory computation for later fast summing */
+ pp->sums[0].x2 = pp->sums[0].xy = pp->sums[0].y2 = pp->sums[0].x = pp->sums[0].y = 0;
+ for (i=0; i<n; i++) {
+ x = pp->pt[i].x - pp->x0;
+ y = pp->pt[i].y - pp->y0;
+ pp->sums[i+1].x = pp->sums[i].x + x;
+ pp->sums[i+1].y = pp->sums[i].y + y;
+ pp->sums[i+1].x2 = pp->sums[i].x2 + (double)x*x;
+ pp->sums[i+1].xy = pp->sums[i].xy + (double)x*y;
+ pp->sums[i+1].y2 = pp->sums[i].y2 + (double)y*y;
+ }
+ return 0;
+
+ calloc_error:
+ return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Stage 1: determine the straight subpaths (Sec. 2.2.1). Fill in the
+ "lon" component of a path object (based on pt/len). For each i,
+ lon[i] is the furthest index such that a straight line can be drawn
+ from i to lon[i]. Return 1 on error with errno set, else 0. */
+
+/* this algorithm depends on the fact that the existence of straight
+ subpaths is a triplewise property. I.e., there exists a straight
+ line through squares i0,...,in iff there exists a straight line
+ through i,j,k, for all i0<=i<j<k<=in. (Proof?) */
+
+/* this implementation of calc_lon is O(n^2). It replaces an older
+ O(n^3) version. A "constraint" means that future points must
+ satisfy xprod(constraint[0], cur) >= 0 and xprod(constraint[1],
+ cur) <= 0. */
+
+/* Remark for Potrace 1.1: the current implementation of calc_lon is
+ more complex than the implementation found in Potrace 1.0, but it
+ is considerably faster. The introduction of the "nc" data structure
+ means that we only have to test the constraints for "corner"
+ points. On a typical input file, this speeds up the calc_lon
+ function by a factor of 31.2, thereby decreasing its time share
+ within the overall Potrace algorithm from 72.6% to 7.82%, and
+ speeding up the overall algorithm by a factor of 3.36. On another
+ input file, calc_lon was sped up by a factor of 6.7, decreasing its
+ time share from 51.4% to 13.61%, and speeding up the overall
+ algorithm by a factor of 1.78. In any case, the savings are
+ substantial. */
+
+/* returns 0 on success, 1 on error with errno set */
+static int calc_lon(privpath_t *pp) {
+ point_t *pt = pp->pt;
+ int n = pp->len;
+ int i, j, k, k1;
+ int ct[4], dir;
+ point_t constraint[2];
+ point_t cur;
+ point_t off;
+ int *pivk = NULL; /* pivk[n] */
+ int *nc = NULL; /* nc[n]: next corner */
+ point_t dk; /* direction of k-k1 */
+ int a, b, c, d;
+
+ SAFE_CALLOC(pivk, n, int);
+ SAFE_CALLOC(nc, n, int);
+
+ /* initialize the nc data structure. Point from each point to the
+ furthest future point to which it is connected by a vertical or
+ horizontal segment. We take advantage of the fact that there is
+ always a direction change at 0 (due to the path decomposition
+ algorithm). But even if this were not so, there is no harm, as
+ in practice, correctness does not depend on the word "furthest"
+ above. */
+ k = 0;
+ for (i=n-1; i>=0; i--) {
+ if (pt[i].x != pt[k].x && pt[i].y != pt[k].y) {
+ k = i+1; /* necessarily i<n-1 in this case */
+ }
+ nc[i] = k;
+ }
+
+ SAFE_CALLOC(pp->lon, n, int);
+
+ /* determine pivot points: for each i, let pivk[i] be the furthest k
+ such that all j with i<j<k lie on a line connecting i,k. */
+
+ for (i=n-1; i>=0; i--) {
+ ct[0] = ct[1] = ct[2] = ct[3] = 0;
+
+ /* keep track of "directions" that have occurred */
+ dir = (3+3*(pt[mod(i+1,n)].x-pt[i].x)+(pt[mod(i+1,n)].y-pt[i].y))/2;
+ ct[dir]++;
+
+ constraint[0].x = 0;
+ constraint[0].y = 0;
+ constraint[1].x = 0;
+ constraint[1].y = 0;
+
+ /* find the next k such that no straight line from i to k */
+ k = nc[i];
+ k1 = i;
+ while (1) {
+
+ dir = (3+3*sign(pt[k].x-pt[k1].x)+sign(pt[k].y-pt[k1].y))/2;
+ ct[dir]++;
+
+ /* if all four "directions" have occurred, cut this path */
+ if (ct[0] && ct[1] && ct[2] && ct[3]) {
+ pivk[i] = k1;
+ goto foundk;
+ }
+
+ cur.x = pt[k].x - pt[i].x;
+ cur.y = pt[k].y - pt[i].y;
+
+ /* see if current constraint is violated */
+ if (xprod(constraint[0], cur) < 0 || xprod(constraint[1], cur) > 0) {
+ goto constraint_viol;
+ }
+
+ /* else, update constraint */
+ if (abs(cur.x) <= 1 && abs(cur.y) <= 1) {
+ /* no constraint */
+ } else {
+ off.x = cur.x + ((cur.y>=0 && (cur.y>0 || cur.x<0)) ? 1 : -1);
+ off.y = cur.y + ((cur.x<=0 && (cur.x<0 || cur.y<0)) ? 1 : -1);
+ if (xprod(constraint[0], off) >= 0) {
+ constraint[0] = off;
+ }
+ off.x = cur.x + ((cur.y<=0 && (cur.y<0 || cur.x<0)) ? 1 : -1);
+ off.y = cur.y + ((cur.x>=0 && (cur.x>0 || cur.y<0)) ? 1 : -1);
+ if (xprod(constraint[1], off) <= 0) {
+ constraint[1] = off;
+ }
+ }
+ k1 = k;
+ k = nc[k1];
+ if (!cyclic(k,i,k1)) {
+ break;
+ }
+ }
+ constraint_viol:
+ /* k1 was the last "corner" satisfying the current constraint, and
+ k is the first one violating it. We now need to find the last
+ point along k1..k which satisfied the constraint. */
+ dk.x = sign(pt[k].x-pt[k1].x);
+ dk.y = sign(pt[k].y-pt[k1].y);
+ cur.x = pt[k1].x - pt[i].x;
+ cur.y = pt[k1].y - pt[i].y;
+ /* find largest integer j such that xprod(constraint[0], cur+j*dk)
+ >= 0 and xprod(constraint[1], cur+j*dk) <= 0. Use bilinearity
+ of xprod. */
+ a = xprod(constraint[0], cur);
+ b = xprod(constraint[0], dk);
+ c = xprod(constraint[1], cur);
+ d = xprod(constraint[1], dk);
+ /* find largest integer j such that a+j*b>=0 and c+j*d<=0. This
+ can be solved with integer arithmetic. */
+ j = INFTY;
+ if (b<0) {
+ j = floordiv(a,-b);
+ }
+ if (d>0) {
+ j = min(j, floordiv(-c,d));
+ }
+ pivk[i] = mod(k1+j,n);
+ foundk:
+ ;
+ } /* for i */
+
+ /* clean up: for each i, let lon[i] be the largest k such that for
+ all i' with i<=i'<k, i'<k<=pivk[i']. */
+
+ j=pivk[n-1];
+ pp->lon[n-1]=j;
+ for (i=n-2; i>=0; i--) {
+ if (cyclic(i+1,pivk[i],j)) {
+ j=pivk[i];
+ }
+ pp->lon[i]=j;
+ }
+
+ for (i=n-1; cyclic(mod(i+1,n),j,pp->lon[i]); i--) {
+ pp->lon[i] = j;
+ }
+
+ free(pivk);
+ free(nc);
+ return 0;
+
+ calloc_error:
+ free(pivk);
+ free(nc);
+ return 1;
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* Stage 2: calculate the optimal polygon (Sec. 2.2.2-2.2.4). */
+
+/* Auxiliary function: calculate the penalty of an edge from i to j in
+ the given path. This needs the "lon" and "sum*" data. */
+
+static double penalty3(privpath_t *pp, int i, int j) {
+ int n = pp->len;
+ point_t *pt = pp->pt;
+ sums_t *sums = pp->sums;
+
+ /* assume 0<=i<j<=n */
+ double x, y, x2, xy, y2;
+ double k;
+ double a, b, c, s;
+ double px, py, ex, ey;
+
+ int r = 0; /* rotations from i to j */
+
+ if (j>=n) {
+ j -= n;
+ r = 1;
+ }
+
+ /* critical inner loop: the "if" gives a 4.6 percent speedup */
+ if (r == 0) {
+ x = sums[j+1].x - sums[i].x;
+ y = sums[j+1].y - sums[i].y;
+ x2 = sums[j+1].x2 - sums[i].x2;
+ xy = sums[j+1].xy - sums[i].xy;
+ y2 = sums[j+1].y2 - sums[i].y2;
+ k = j+1 - i;
+ } else {
+ x = sums[j+1].x - sums[i].x + sums[n].x;
+ y = sums[j+1].y - sums[i].y + sums[n].y;
+ x2 = sums[j+1].x2 - sums[i].x2 + sums[n].x2;
+ xy = sums[j+1].xy - sums[i].xy + sums[n].xy;
+ y2 = sums[j+1].y2 - sums[i].y2 + sums[n].y2;
+ k = j+1 - i + n;
+ }
+
+ px = (pt[i].x + pt[j].x) / 2.0 - pt[0].x;
+ py = (pt[i].y + pt[j].y) / 2.0 - pt[0].y;
+ ey = (pt[j].x - pt[i].x);
+ ex = -(pt[j].y - pt[i].y);
+
+ a = ((x2 - 2*x*px) / k + px*px);
+ b = ((xy - x*py - y*px) / k + px*py);
+ c = ((y2 - 2*y*py) / k + py*py);
+
+ s = ex*ex*a + 2*ex*ey*b + ey*ey*c;
+
+ return sqrt(s);
+}
+
+/* find the optimal polygon. Fill in the m and po components. Return 1
+ on failure with errno set, else 0. Non-cyclic version: assumes i=0
+ is in the polygon. Fixme: implement cyclic version. */
+static int bestpolygon(privpath_t *pp)
+{
+ int i, j, m, k;
+ int n = pp->len;
+ double *pen = NULL; /* pen[n+1]: penalty vector */
+ int *prev = NULL; /* prev[n+1]: best path pointer vector */
+ int *clip0 = NULL; /* clip0[n]: longest segment pointer, non-cyclic */
+ int *clip1 = NULL; /* clip1[n+1]: backwards segment pointer, non-cyclic */
+ int *seg0 = NULL; /* seg0[m+1]: forward segment bounds, m<=n */
+ int *seg1 = NULL; /* seg1[m+1]: backward segment bounds, m<=n */
+ double thispen;
+ double best;
+ int c;
+
+ SAFE_CALLOC(pen, n+1, double);
+ SAFE_CALLOC(prev, n+1, int);
+ SAFE_CALLOC(clip0, n, int);
+ SAFE_CALLOC(clip1, n+1, int);
+ SAFE_CALLOC(seg0, n+1, int);
+ SAFE_CALLOC(seg1, n+1, int);
+
+ /* calculate clipped paths */
+ for (i=0; i<n; i++) {
+ c = mod(pp->lon[mod(i-1,n)]-1,n);
+ if (c == i) {
+ c = mod(i+1,n);
+ }
+ if (c < i) {
+ clip0[i] = n;
+ } else {
+ clip0[i] = c;
+ }
+ }
+
+ /* calculate backwards path clipping, non-cyclic. j <= clip0[i] iff
+ clip1[j] <= i, for i,j=0..n. */
+ j = 1;
+ for (i=0; i<n; i++) {
+ while (j <= clip0[i]) {
+ clip1[j] = i;
+ j++;
+ }
+ }
+
+ /* calculate seg0[j] = longest path from 0 with j segments */
+ i = 0;
+ for (j=0; i<n; j++) {
+ seg0[j] = i;
+ i = clip0[i];
+ }
+ seg0[j] = n;
+ m = j;
+
+ /* calculate seg1[j] = longest path to n with m-j segments */
+ i = n;
+ for (j=m; j>0; j--) {
+ seg1[j] = i;
+ i = clip1[i];
+ }
+ seg1[0] = 0;
+
+ /* now find the shortest path with m segments, based on penalty3 */
+ /* note: the outer 2 loops jointly have at most n iterations, thus
+ the worst-case behavior here is quadratic. In practice, it is
+ close to linear since the inner loop tends to be short. */
+ pen[0]=0;
+ for (j=1; j<=m; j++) {
+ for (i=seg1[j]; i<=seg0[j]; i++) {
+ best = -1;
+ for (k=seg0[j-1]; k>=clip1[i]; k--) {
+ thispen = penalty3(pp, k, i) + pen[k];
+ if (best < 0 || thispen < best) {
+ prev[i] = k;
+ best = thispen;
+ }
+ }
+ pen[i] = best;
+ }
+ }
+
+ pp->m = m;
+ SAFE_CALLOC(pp->po, m, int);
+
+ /* read off shortest path */
+ for (i=n, j=m-1; i>0; j--) {
+ i = prev[i];
+ pp->po[j] = i;
+ }
+
+ free(pen);
+ free(prev);
+ free(clip0);
+ free(clip1);
+ free(seg0);
+ free(seg1);
+ return 0;
+
+ calloc_error:
+ free(pen);
+ free(prev);
+ free(clip0);
+ free(clip1);
+ free(seg0);
+ free(seg1);
+ return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Stage 3: vertex adjustment (Sec. 2.3.1). */
+
+/* Adjust vertices of optimal polygon: calculate the intersection of
+ the two "optimal" line segments, then move it into the unit square
+ if it lies outside. Return 1 with errno set on error; 0 on
+ success. */
+
+static int adjust_vertices(privpath_t *pp) {
+ int m = pp->m;
+ int *po = pp->po;
+ int n = pp->len;
+ point_t *pt = pp->pt;
+ int x0 = pp->x0;
+ int y0 = pp->y0;
+
+ dpoint_t *ctr = NULL; /* ctr[m] */
+ dpoint_t *dir = NULL; /* dir[m] */
+ quadform_t *q = NULL; /* q[m] */
+ double v[3];
+ double d;
+ int i, j, k, l;
+ dpoint_t s;
+ int r;
+
+ SAFE_CALLOC(ctr, m, dpoint_t);
+ SAFE_CALLOC(dir, m, dpoint_t);
+ SAFE_CALLOC(q, m, quadform_t);
+
+ r = privcurve_init(&pp->curve, m);
+ if (r) {
+ goto calloc_error;
+ }
+
+ /* calculate "optimal" point-slope representation for each line
+ segment */
+ for (i=0; i<m; i++) {
+ j = po[mod(i+1,m)];
+ j = mod(j-po[i],n)+po[i];
+ pointslope(pp, po[i], j, &ctr[i], &dir[i]);
+ }
+
+ /* represent each line segment as a singular quadratic form; the
+ distance of a point (x,y) from the line segment will be
+ (x,y,1)Q(x,y,1)^t, where Q=q[i]. */
+ for (i=0; i<m; i++) {
+ d = sq(dir[i].x) + sq(dir[i].y);
+ if (d == 0.0) {
+ for (j=0; j<3; j++) {
+ for (k=0; k<3; k++) {
+ q[i][j][k] = 0;
+ }
+ }
+ } else {
+ v[0] = dir[i].y;
+ v[1] = -dir[i].x;
+ v[2] = - v[1] * ctr[i].y - v[0] * ctr[i].x;
+ for (l=0; l<3; l++) {
+ for (k=0; k<3; k++) {
+ q[i][l][k] = v[l] * v[k] / d;
+ }
+ }
+ }
+ }
+
+ /* now calculate the "intersections" of consecutive segments.
+ Instead of using the actual intersection, we find the point
+ within a given unit square which minimizes the square distance to
+ the two lines. */
+ for (i=0; i<m; i++) {
+ quadform_t Q;
+ dpoint_t w;
+ double dx, dy;
+ double det;
+ double min, cand; /* minimum and candidate for minimum of quad. form */
+ double xmin, ymin; /* coordinates of minimum */
+ int z;
+
+ /* let s be the vertex, in coordinates relative to x0/y0 */
+ s.x = pt[po[i]].x-x0;
+ s.y = pt[po[i]].y-y0;
+
+ /* intersect segments i-1 and i */
+
+ j = mod(i-1,m);
+
+ /* add quadratic forms */
+ for (l=0; l<3; l++) {
+ for (k=0; k<3; k++) {
+ Q[l][k] = q[j][l][k] + q[i][l][k];
+ }
+ }
+
+ while(1) {
+ /* minimize the quadratic form Q on the unit square */
+ /* find intersection */
+
+#ifdef HAVE_GCC_LOOP_BUG
+ /* work around gcc bug #12243 */
+ free(NULL);
+#endif
+
+ det = Q[0][0]*Q[1][1] - Q[0][1]*Q[1][0];
+ if (det != 0.0) {
+ w.x = (-Q[0][2]*Q[1][1] + Q[1][2]*Q[0][1]) / det;
+ w.y = ( Q[0][2]*Q[1][0] - Q[1][2]*Q[0][0]) / det;
+ break;
+ }
+
+ /* matrix is singular - lines are parallel. Add another,
+ orthogonal axis, through the center of the unit square */
+ if (Q[0][0]>Q[1][1]) {
+ v[0] = -Q[0][1];
+ v[1] = Q[0][0];
+ } else if (Q[1][1]) {
+ v[0] = -Q[1][1];
+ v[1] = Q[1][0];
+ } else {
+ v[0] = 1;
+ v[1] = 0;
+ }
+ d = sq(v[0]) + sq(v[1]);
+ v[2] = - v[1] * s.y - v[0] * s.x;
+ for (l=0; l<3; l++) {
+ for (k=0; k<3; k++) {
+ Q[l][k] += v[l] * v[k] / d;
+ }
+ }
+ }
+ dx = fabs(w.x-s.x);
+ dy = fabs(w.y-s.y);
+ if (dx <= .5 && dy <= .5) {
+ pp->curve.vertex[i].x = w.x+x0;
+ pp->curve.vertex[i].y = w.y+y0;
+ continue;
+ }
+
+ /* the minimum was not in the unit square; now minimize quadratic
+ on boundary of square */
+ min = quadform(Q, s);
+ xmin = s.x;
+ ymin = s.y;
+
+ if (Q[0][0] == 0.0) {
+ goto fixx;
+ }
+ for (z=0; z<2; z++) { /* value of the y-coordinate */
+ w.y = s.y-0.5+z;
+ w.x = - (Q[0][1] * w.y + Q[0][2]) / Q[0][0];
+ dx = fabs(w.x-s.x);
+ cand = quadform(Q, w);
+ if (dx <= .5 && cand < min) {
+ min = cand;
+ xmin = w.x;
+ ymin = w.y;
+ }
+ }
+ fixx:
+ if (Q[1][1] == 0.0) {
+ goto corners;
+ }
+ for (z=0; z<2; z++) { /* value of the x-coordinate */
+ w.x = s.x-0.5+z;
+ w.y = - (Q[1][0] * w.x + Q[1][2]) / Q[1][1];
+ dy = fabs(w.y-s.y);
+ cand = quadform(Q, w);
+ if (dy <= .5 && cand < min) {
+ min = cand;
+ xmin = w.x;
+ ymin = w.y;
+ }
+ }
+ corners:
+ /* check four corners */
+ for (l=0; l<2; l++) {
+ for (k=0; k<2; k++) {
+ w.x = s.x-0.5+l;
+ w.y = s.y-0.5+k;
+ cand = quadform(Q, w);
+ if (cand < min) {
+ min = cand;
+ xmin = w.x;
+ ymin = w.y;
+ }
+ }
+ }
+
+ pp->curve.vertex[i].x = xmin + x0;
+ pp->curve.vertex[i].y = ymin + y0;
+ continue;
+ }
+
+ free(ctr);
+ free(dir);
+ free(q);
+ return 0;
+
+ calloc_error:
+ free(ctr);
+ free(dir);
+ free(q);
+ return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Stage 4: smoothing and corner analysis (Sec. 2.3.3) */
+
+/* reverse orientation of a path */
+static void reverse(privcurve_t *curve) {
+ int m = curve->n;
+ int i, j;
+ dpoint_t tmp;
+
+ for (i=0, j=m-1; i<j; i++, j--) {
+ tmp = curve->vertex[i];
+ curve->vertex[i] = curve->vertex[j];
+ curve->vertex[j] = tmp;
+ }
+}
+
+/* Always succeeds */
+static void smooth(privcurve_t *curve, double alphamax) {
+ int m = curve->n;
+
+ int i, j, k;
+ double dd, denom, alpha;
+ dpoint_t p2, p3, p4;
+
+ /* examine each vertex and find its best fit */
+ for (i=0; i<m; i++) {
+ j = mod(i+1, m);
+ k = mod(i+2, m);
+ p4 = interval(1/2.0, curve->vertex[k], curve->vertex[j]);
+
+ denom = ddenom(curve->vertex[i], curve->vertex[k]);
+ if (denom != 0.0) {
+ dd = dpara(curve->vertex[i], curve->vertex[j], curve->vertex[k]) / denom;
+ dd = fabs(dd);
+ alpha = dd>1 ? (1 - 1.0/dd) : 0;
+ alpha = alpha / 0.75;
+ } else {
+ alpha = 4/3.0;
+ }
+ curve->alpha0[j] = alpha; /* remember "original" value of alpha */
+
+ if (alpha >= alphamax) { /* pointed corner */
+ curve->tag[j] = POTRACE_CORNER;
+ curve->c[j][1] = curve->vertex[j];
+ curve->c[j][2] = p4;
+ } else {
+ if (alpha < 0.55) {
+ alpha = 0.55;
+ } else if (alpha > 1) {
+ alpha = 1;
+ }
+ p2 = interval(.5+.5*alpha, curve->vertex[i], curve->vertex[j]);
+ p3 = interval(.5+.5*alpha, curve->vertex[k], curve->vertex[j]);
+ curve->tag[j] = POTRACE_CURVETO;
+ curve->c[j][0] = p2;
+ curve->c[j][1] = p3;
+ curve->c[j][2] = p4;
+ }
+ curve->alpha[j] = alpha; /* store the "cropped" value of alpha */
+ curve->beta[j] = 0.5;
+ }
+ curve->alphacurve = 1;
+
+ return;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Stage 5: Curve optimization (Sec. 2.4) */
+
+/* a private type for the result of opti_penalty */
+struct opti_s {
+ double pen; /* penalty */
+ dpoint_t c[2]; /* curve parameters */
+ double t, s; /* curve parameters */
+ double alpha; /* curve parameter */
+};
+typedef struct opti_s opti_t;
+
+/* calculate best fit from i+.5 to j+.5. Assume i<j (cyclically).
+ Return 0 and set badness and parameters (alpha, beta), if
+ possible. Return 1 if impossible. */
+static int opti_penalty(privpath_t *pp, int i, int j, opti_t *res, double opttolerance, int *convc, double *areac) {
+ int m = pp->curve.n;
+ int k, k1, k2, conv, i1;
+ double area, alpha, d, d1, d2;
+ dpoint_t p0, p1, p2, p3, pt;
+ double A, R, A1, A2, A3, A4;
+ double s, t;
+
+ /* check convexity, corner-freeness, and maximum bend < 179 degrees */
+
+ if (i==j) { /* sanity - a full loop can never be an opticurve */
+ return 1;
+ }
+
+ k = i;
+ i1 = mod(i+1, m);
+ k1 = mod(k+1, m);
+ conv = convc[k1];
+ if (conv == 0) {
+ return 1;
+ }
+ d = ddist(pp->curve.vertex[i], pp->curve.vertex[i1]);
+ for (k=k1; k!=j; k=k1) {
+ k1 = mod(k+1, m);
+ k2 = mod(k+2, m);
+ if (convc[k1] != conv) {
+ return 1;
+ }
+ if (sign(cprod(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2])) != conv) {
+ return 1;
+ }
+ if (iprod1(pp->curve.vertex[i], pp->curve.vertex[i1], pp->curve.vertex[k1], pp->curve.vertex[k2]) < d * ddist(pp->curve.vertex[k1], pp->curve.vertex[k2]) * COS179) {
+ return 1;
+ }
+ }
+
+ /* the curve we're working in: */
+ p0 = pp->curve.c[mod(i,m)][2];
+ p1 = pp->curve.vertex[mod(i+1,m)];
+ p2 = pp->curve.vertex[mod(j,m)];
+ p3 = pp->curve.c[mod(j,m)][2];
+
+ /* determine its area */
+ area = areac[j] - areac[i];
+ area -= dpara(pp->curve.vertex[0], pp->curve.c[i][2], pp->curve.c[j][2])/2;
+ if (i>=j) {
+ area += areac[m];
+ }
+
+ /* find intersection o of p0p1 and p2p3. Let t,s such that o =
+ interval(t,p0,p1) = interval(s,p3,p2). Let A be the area of the
+ triangle (p0,o,p3). */
+
+ A1 = dpara(p0, p1, p2);
+ A2 = dpara(p0, p1, p3);
+ A3 = dpara(p0, p2, p3);
+ /* A4 = dpara(p1, p2, p3); */
+ A4 = A1+A3-A2;
+
+ if (A2 == A1) { /* this should never happen */
+ return 1;
+ }
+
+ t = A3/(A3-A4);
+ s = A2/(A2-A1);
+ A = A2 * t / 2.0;
+
+ if (A == 0.0) { /* this should never happen */
+ return 1;
+ }
+
+ R = area / A; /* relative area */
+ alpha = 2 - sqrt(4 - R / 0.3); /* overall alpha for p0-o-p3 curve */
+
+ res->c[0] = interval(t * alpha, p0, p1);
+ res->c[1] = interval(s * alpha, p3, p2);
+ res->alpha = alpha;
+ res->t = t;
+ res->s = s;
+
+ p1 = res->c[0];
+ p2 = res->c[1]; /* the proposed curve is now (p0,p1,p2,p3) */
+
+ res->pen = 0;
+
+ /* calculate penalty */
+ /* check tangency with edges */
+ for (k=mod(i+1,m); k!=j; k=k1) {
+ k1 = mod(k+1,m);
+ t = tangent(p0, p1, p2, p3, pp->curve.vertex[k], pp->curve.vertex[k1]);
+ if (t<-.5) {
+ return 1;
+ }
+ pt = bezier(t, p0, p1, p2, p3);
+ d = ddist(pp->curve.vertex[k], pp->curve.vertex[k1]);
+ if (d == 0.0) { /* this should never happen */
+ return 1;
+ }
+ d1 = dpara(pp->curve.vertex[k], pp->curve.vertex[k1], pt) / d;
+ if (fabs(d1) > opttolerance) {
+ return 1;
+ }
+ if (iprod(pp->curve.vertex[k], pp->curve.vertex[k1], pt) < 0 || iprod(pp->curve.vertex[k1], pp->curve.vertex[k], pt) < 0) {
+ return 1;
+ }
+ res->pen += sq(d1);
+ }
+
+ /* check corners */
+ for (k=i; k!=j; k=k1) {
+ k1 = mod(k+1,m);
+ t = tangent(p0, p1, p2, p3, pp->curve.c[k][2], pp->curve.c[k1][2]);
+ if (t<-.5) {
+ return 1;
+ }
+ pt = bezier(t, p0, p1, p2, p3);
+ d = ddist(pp->curve.c[k][2], pp->curve.c[k1][2]);
+ if (d == 0.0) { /* this should never happen */
+ return 1;
+ }
+ d1 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pt) / d;
+ d2 = dpara(pp->curve.c[k][2], pp->curve.c[k1][2], pp->curve.vertex[k1]) / d;
+ d2 *= 0.75 * pp->curve.alpha[k1];
+ if (d2 < 0) {
+ d1 = -d1;
+ d2 = -d2;
+ }
+ if (d1 < d2 - opttolerance) {
+ return 1;
+ }
+ if (d1 < d2) {
+ res->pen += sq(d1 - d2);
+ }
+ }
+
+ return 0;
+}
+
+/* optimize the path p, replacing sequences of Bezier segments by a
+ single segment when possible. Return 0 on success, 1 with errno set
+ on failure. */
+static int opticurve(privpath_t *pp, double opttolerance) {
+ int m = pp->curve.n;
+ int *pt = NULL; /* pt[m+1] */
+ double *pen = NULL; /* pen[m+1] */
+ int *len = NULL; /* len[m+1] */
+ opti_t *opt = NULL; /* opt[m+1] */
+ int om;
+ int i,j,r;
+ opti_t o;
+ dpoint_t p0;
+ int i1;
+ double area;
+ double alpha;
+ double *s = NULL;
+ double *t = NULL;
+
+ int *convc = NULL; /* conv[m]: pre-computed convexities */
+ double *areac = NULL; /* cumarea[m+1]: cache for fast area computation */
+
+ SAFE_CALLOC(pt, m+1, int);
+ SAFE_CALLOC(pen, m+1, double);
+ SAFE_CALLOC(len, m+1, int);
+ SAFE_CALLOC(opt, m+1, opti_t);
+ SAFE_CALLOC(convc, m, int);
+ SAFE_CALLOC(areac, m+1, double);
+
+ /* pre-calculate convexity: +1 = right turn, -1 = left turn, 0 = corner */
+ for (i=0; i<m; i++) {
+ if (pp->curve.tag[i] == POTRACE_CURVETO) {
+ convc[i] = sign(dpara(pp->curve.vertex[mod(i-1,m)], pp->curve.vertex[i], pp->curve.vertex[mod(i+1,m)]));
+ } else {
+ convc[i] = 0;
+ }
+ }
+
+ /* pre-calculate areas */
+ area = 0.0;
+ areac[0] = 0.0;
+ p0 = pp->curve.vertex[0];
+ for (i=0; i<m; i++) {
+ i1 = mod(i+1, m);
+ if (pp->curve.tag[i1] == POTRACE_CURVETO) {
+ alpha = pp->curve.alpha[i1];
+ area += 0.3*alpha*(4-alpha)*dpara(pp->curve.c[i][2], pp->curve.vertex[i1], pp->curve.c[i1][2])/2;
+ area += dpara(p0, pp->curve.c[i][2], pp->curve.c[i1][2])/2;
+ }
+ areac[i+1] = area;
+ }
+
+ pt[0] = -1;
+ pen[0] = 0;
+ len[0] = 0;
+
+ /* Fixme: we always start from a fixed point -- should find the best
+ curve cyclically */
+
+ for (j=1; j<=m; j++) {
+ /* calculate best path from 0 to j */
+ pt[j] = j-1;
+ pen[j] = pen[j-1];
+ len[j] = len[j-1]+1;
+
+ for (i=j-2; i>=0; i--) {
+ r = opti_penalty(pp, i, mod(j,m), &o, opttolerance, convc, areac);
+ if (r) {
+ break;
+ }
+ if (len[j] > len[i]+1 || (len[j] == len[i]+1 && pen[j] > pen[i] + o.pen)) {
+ pt[j] = i;
+ pen[j] = pen[i] + o.pen;
+ len[j] = len[i] + 1;
+ opt[j] = o;
+ }
+ }
+ }
+ om = len[m];
+ r = privcurve_init(&pp->ocurve, om);
+ if (r) {
+ goto calloc_error;
+ }
+ SAFE_CALLOC(s, om, double);
+ SAFE_CALLOC(t, om, double);
+
+ j = m;
+ for (i=om-1; i>=0; i--) {
+ if (pt[j]==j-1) {
+ pp->ocurve.tag[i] = pp->curve.tag[mod(j,m)];
+ pp->ocurve.c[i][0] = pp->curve.c[mod(j,m)][0];
+ pp->ocurve.c[i][1] = pp->curve.c[mod(j,m)][1];
+ pp->ocurve.c[i][2] = pp->curve.c[mod(j,m)][2];
+ pp->ocurve.vertex[i] = pp->curve.vertex[mod(j,m)];
+ pp->ocurve.alpha[i] = pp->curve.alpha[mod(j,m)];
+ pp->ocurve.alpha0[i] = pp->curve.alpha0[mod(j,m)];
+ pp->ocurve.beta[i] = pp->curve.beta[mod(j,m)];
+ s[i] = t[i] = 1.0;
+ } else {
+ pp->ocurve.tag[i] = POTRACE_CURVETO;
+ pp->ocurve.c[i][0] = opt[j].c[0];
+ pp->ocurve.c[i][1] = opt[j].c[1];
+ pp->ocurve.c[i][2] = pp->curve.c[mod(j,m)][2];
+ pp->ocurve.vertex[i] = interval(opt[j].s, pp->curve.c[mod(j,m)][2], pp->curve.vertex[mod(j,m)]);
+ pp->ocurve.alpha[i] = opt[j].alpha;
+ pp->ocurve.alpha0[i] = opt[j].alpha;
+ s[i] = opt[j].s;
+ t[i] = opt[j].t;
+ }
+ j = pt[j];
+ }
+
+ /* calculate beta parameters */
+ for (i=0; i<om; i++) {
+ i1 = mod(i+1,om);
+ pp->ocurve.beta[i] = s[i] / (s[i] + t[i1]);
+ }
+ pp->ocurve.alphacurve = 1;
+
+ free(pt);
+ free(pen);
+ free(len);
+ free(opt);
+ free(s);
+ free(t);
+ free(convc);
+ free(areac);
+ return 0;
+
+ calloc_error:
+ free(pt);
+ free(pen);
+ free(len);
+ free(opt);
+ free(s);
+ free(t);
+ free(convc);
+ free(areac);
+ return 1;
+}
+
+/* ---------------------------------------------------------------------- */
+
+#define TRY(x) if (x) goto try_error
+
+/* return 0 on success, 1 on error with errno set. */
+int process_path(path_t *plist, const potrace_param_t *param, progress_t *progress) {
+ path_t *p;
+ double nn = 0, cn = 0;
+
+ if (progress->callback) {
+ /* precompute task size for progress estimates */
+ nn = 0;
+ list_forall (p, plist) {
+ nn += p->priv->len;
+ }
+ cn = 0;
+ }
+
+ /* call downstream function with each path */
+ list_forall (p, plist) {
+ TRY(calc_sums(p->priv));
+ TRY(calc_lon(p->priv));
+ TRY(bestpolygon(p->priv));
+ TRY(adjust_vertices(p->priv));
+ if (p->sign == '-') { /* reverse orientation of negative paths */
+ reverse(&p->priv->curve);
+ }
+ smooth(&p->priv->curve, param->alphamax);
+ if (param->opticurve) {
+ TRY(opticurve(p->priv, param->opttolerance));
+ p->priv->fcurve = &p->priv->ocurve;
+ } else {
+ p->priv->fcurve = &p->priv->curve;
+ }
+ privcurve_to_curve(p->priv->fcurve, &p->curve);
+
+ if (progress->callback) {
+ cn += p->priv->len;
+ progress_update(cn/nn, progress);
+ }
+ }
+
+ progress_update(1.0, progress);
+
+ return 0;
+
+ try_error:
+ return 1;
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/trace.h b/Build/source/libs/potrace/potrace-src/src/trace.h
new file mode 100644
index 00000000000..7ddcb89c7bc
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/trace.h
@@ -0,0 +1,15 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef TRACE_H
+#define TRACE_H
+
+#include "potracelib.h"
+#include "progress.h"
+#include "curve.h"
+
+int process_path(path_t *plist, const potrace_param_t *param, progress_t *progress);
+
+#endif /* TRACE_H */
diff --git a/Build/source/libs/potrace/potrace-src/src/trans.c b/Build/source/libs/potrace/potrace-src/src/trans.c
new file mode 100644
index 00000000000..779feb55cd6
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/trans.c
@@ -0,0 +1,127 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+/* calculations with coordinate transformations and bounding boxes */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include <string.h>
+
+#include "trans.h"
+#include "bbox.h"
+
+/* rotate the coordinate system counterclockwise by alpha degrees. The
+ new bounding box will be the smallest box containing the rotated
+ old bounding box */
+void trans_rotate(trans_t *r, double alpha) {
+ double s, c, x0, x1, y0, y1, o0, o1;
+ trans_t t_struct;
+ trans_t *t = &t_struct;
+
+ memcpy(t, r, sizeof(trans_t));
+
+ s = sin(alpha/180*M_PI);
+ c = cos(alpha/180*M_PI);
+
+ /* apply the transformation matrix to the sides of the bounding box */
+ x0 = c * t->bb[0];
+ x1 = s * t->bb[0];
+ y0 = -s * t->bb[1];
+ y1 = c * t->bb[1];
+
+ /* determine new bounding box, and origin of old bb within new bb */
+ r->bb[0] = fabs(x0) + fabs(y0);
+ r->bb[1] = fabs(x1) + fabs(y1);
+ o0 = - min(x0,0) - min(y0,0);
+ o1 = - min(x1,0) - min(y1,0);
+
+ r->orig[0] = o0 + c * t->orig[0] - s * t->orig[1];
+ r->orig[1] = o1 + s * t->orig[0] + c * t->orig[1];
+ r->x[0] = c * t->x[0] - s * t->x[1];
+ r->x[1] = s * t->x[0] + c * t->x[1];
+ r->y[0] = c * t->y[0] - s * t->y[1];
+ r->y[1] = s * t->y[0] + c * t->y[1];
+}
+
+/* return the standard cartesian coordinate system for an w x h rectangle. */
+void trans_from_rect(trans_t *r, double w, double h) {
+ r->bb[0] = w;
+ r->bb[1] = h;
+ r->orig[0] = 0.0;
+ r->orig[1] = 0.0;
+ r->x[0] = 1.0;
+ r->x[1] = 0.0;
+ r->y[0] = 0.0;
+ r->y[1] = 1.0;
+ r->scalex = 1.0;
+ r->scaley = 1.0;
+}
+
+/* rescale the coordinate system r by factor sc >= 0. */
+void trans_rescale(trans_t *r, double sc) {
+ r->bb[0] *= sc;
+ r->bb[1] *= sc;
+ r->orig[0] *= sc;
+ r->orig[1] *= sc;
+ r->x[0] *= sc;
+ r->x[1] *= sc;
+ r->y[0] *= sc;
+ r->y[1] *= sc;
+ r->scalex *= sc;
+ r->scaley *= sc;
+}
+
+/* rescale the coordinate system to size w x h */
+void trans_scale_to_size(trans_t *r, double w, double h) {
+ double xsc = w/r->bb[0];
+ double ysc = h/r->bb[1];
+
+ r->bb[0] = w;
+ r->bb[1] = h;
+ r->orig[0] *= xsc;
+ r->orig[1] *= ysc;
+ r->x[0] *= xsc;
+ r->x[1] *= ysc;
+ r->y[0] *= xsc;
+ r->y[1] *= ysc;
+ r->scalex *= xsc;
+ r->scaley *= ysc;
+
+ if (w<0) {
+ r->orig[0] -= w;
+ r->bb[0] = -w;
+ }
+ if (h<0) {
+ r->orig[1] -= h;
+ r->bb[1] = -h;
+ }
+}
+
+/* adjust the bounding box to the actual vector outline */
+void trans_tighten(trans_t *r, potrace_path_t *plist) {
+ interval_t i;
+ dpoint_t dir;
+ int j;
+
+ /* if pathlist is empty, do nothing */
+ if (!plist) {
+ return;
+ }
+
+ for (j=0; j<2; j++) {
+ dir.x = r->x[j];
+ dir.y = r->y[j];
+ path_limits(plist, dir, &i);
+ if (i.min == i.max) {
+ /* make the extent non-zero to avoid later division by zero errors */
+ i.max = i.min+0.5;
+ i.min = i.min-0.5;
+ }
+ r->bb[j] = i.max - i.min;
+ r->orig[j] = -i.min;
+ }
+}
diff --git a/Build/source/libs/potrace/potrace-src/src/trans.h b/Build/source/libs/potrace/potrace-src/src/trans.h
new file mode 100644
index 00000000000..1d4cd073005
--- /dev/null
+++ b/Build/source/libs/potrace/potrace-src/src/trans.h
@@ -0,0 +1,36 @@
+/* Copyright (C) 2001-2019 Peter Selinger.
+ This file is part of Potrace. It is free software and it is covered
+ by the GNU General Public License. See the file COPYING for details. */
+
+
+#ifndef TRANS_H
+#define TRANS_H
+
+#include "auxiliary.h"
+
+/* structure to hold a coordinate transformation */
+struct trans_s {
+ double bb[2]; /* dimensions of bounding box */
+ double orig[2]; /* origin relative to bounding box */
+ double x[2]; /* basis vector for the "x" direction */
+ double y[2]; /* basis vector for the "y" direction */
+ double scalex, scaley; /* redundant info for some backends' benefit */
+};
+typedef struct trans_s trans_t;
+
+/* apply a coordinate transformation to a point */
+static inline dpoint_t trans(dpoint_t p, trans_t t) {
+ dpoint_t res;
+
+ res.x = t.orig[0] + p.x * t.x[0] + p.y * t.y[0];
+ res.y = t.orig[1] + p.x * t.x[1] + p.y * t.y[1];
+ return res;
+}
+
+void trans_rotate(trans_t *r, double alpha);
+void trans_from_rect(trans_t *r, double w, double h);
+void trans_rescale(trans_t *r, double sc);
+void trans_scale_to_size(trans_t *r, double w, double h);
+void trans_tighten(trans_t *r, potrace_path_t *plist);
+
+#endif /* TRANS_H */