git: 79e5fba255ef - main - cad/PrusaSlicer: update to 2.6.0

From: Fernando Apesteguía <fernape_at_FreeBSD.org>
Date: Fri, 28 Jul 2023 12:48:14 UTC
The branch main has been updated by fernape:

URL: https://cgit.FreeBSD.org/ports/commit/?id=79e5fba255ef2620dd872e21bdd7dc667fea3c19

commit 79e5fba255ef2620dd872e21bdd7dc667fea3c19
Author:     zielonka michal <michal.zielonka.8001@gmail.com>
AuthorDate: 2023-07-27 06:38:24 +0000
Commit:     Fernando Apesteguía <fernape@FreeBSD.org>
CommitDate: 2023-07-28 12:47:57 +0000

    cad/PrusaSlicer: update to 2.6.0
    
    PR:             272730
    Reported by:    michal.zielonka.8001@gmail.com
    Approved by:    teodorsigaev@gmail.com (maintainer)
---
 cad/PrusaSlicer/Makefile                           |   14 +-
 cad/PrusaSlicer/distinfo                           |    6 +-
 cad/PrusaSlicer/files/patch-CMakeLists.txt         |   19 +-
 cad/PrusaSlicer/files/patch-src_CMakeLists.txt     |   15 +-
 cad/PrusaSlicer/files/patch-src_avrdude_arduino.c  |   10 +
 .../files/patch-src_libnanosvg_nanosvg.h           | 3109 ++++++++++++++++++++
 .../files/patch-src_libnanosvg_nanosvgrast.h       | 1485 ++++++++++
 .../files/patch-src_libslic3r_CMakeLists.txt       |    6 +-
 .../files/patch-src_libslic3r_Format_SL1__SVG.cpp  |   12 +
 .../files/patch-src_libslic3r_GCodeSender.cpp      |   20 +
 .../files/patch-src_libslic3r_NSVGUtils.hpp        |   11 +
 .../patch-src_libslic3r_SupportSpotsGenerator.cpp  |   11 +
 .../files/patch-src_occt__wrapper_CMakeLists.txt   |    6 +-
 .../files/patch-src_qhull_CMakeLists.txt           |   29 -
 .../files/patch-src_slic3r_CMakeLists.txt          |   18 +-
 .../files/patch-src_slic3r_GUI_BitmapCache.cpp     |   32 +
 .../files/patch-src_slic3r_GUI_ConfigWizard.cpp    |   56 +
 .../files/patch-src_slic3r_GUI_ConfigWizard.hpp    |   20 +
 ...tch-src_slic3r_GUI_DesktopIntegrationDialog.cpp |    8 +
 ...tch-src_slic3r_GUI_DesktopIntegrationDialog.hpp |   15 +
 .../files/patch-src_slic3r_GUI_ExtraRenderers.cpp  |   11 +
 .../files/patch-src_slic3r_GUI_Field.cpp           |   11 +
 .../files/patch-src_slic3r_GUI_GLCanvas3D.cpp      |   11 +
 .../files/patch-src_slic3r_GUI_GLTexture.cpp       |   13 +
 cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI.cpp |   20 +
 cad/PrusaSlicer/files/patch-src_slic3r_GUI_GUI.hpp |   11 +
 .../files/patch-src_slic3r_GUI_GUI__App.cpp        |  155 +-
 .../files/patch-src_slic3r_GUI_GUI__Factories.cpp  |   11 +
 .../patch-src_slic3r_GUI_GUI__ObjectLayers.cpp     |   20 +
 ...atch-src_slic3r_GUI_GUI__ObjectManipulation.cpp |   12 +
 .../files/patch-src_slic3r_GUI_GUI__Preview.cpp    |   28 +
 .../files/patch-src_slic3r_GUI_GUI__Preview.hpp    |   11 +
 .../files/patch-src_slic3r_GUI_GUI__Utils.cpp      |   20 +
 .../patch-src_slic3r_GUI_Gizmos_GLGizmoEmboss.cpp  |   11 +
 .../files/patch-src_slic3r_GUI_ImGuiWrapper.cpp    |   13 +
 .../files/patch-src_slic3r_GUI_InstanceCheck.cpp   |   11 +-
 .../files/patch-src_slic3r_GUI_InstanceCheck.hpp   |   20 +
 .../patch-src_slic3r_GUI_KBShortcutsDialog.cpp     |   11 +
 .../patch-src_slic3r_GUI_Mouse3DController.cpp     |   20 +
 .../files/patch-src_slic3r_GUI_OpenGLManager.cpp   |   19 +-
 .../files/patch-src_slic3r_GUI_OptionsGroup.cpp    |   20 +
 .../files/patch-src_slic3r_GUI_Plater.cpp          |   29 +
 .../files/patch-src_slic3r_GUI_Preferences.cpp     |   20 +
 .../patch-src_slic3r_GUI_PresetComboBoxes.cpp      |   11 +
 .../patch-src_slic3r_GUI_PresetComboBoxes.hpp      |   11 +
 .../patch-src_slic3r_GUI_PrintHostDialogs.cpp      |   58 +
 .../patch-src_slic3r_GUI_RemovableDriveManager.cpp |   11 +
 cad/PrusaSlicer/files/patch-src_slic3r_GUI_Tab.cpp |   56 +
 .../patch-src_slic3r_GUI_UnsavedChangesDialog.cpp  |   65 +
 .../patch-src_slic3r_GUI_UnsavedChangesDialog.hpp  |   20 +
 .../files/patch-src_slic3r_GUI_UpdateDialogs.cpp   |   20 +
 .../files/patch-src_slic3r_GUI_wxExtensions.cpp    |   41 +
 .../files/patch-src_slic3r_GUI_wxExtensions.hpp    |   11 +
 .../patch-src_slic3r_Utils_FontConfigHelp.hpp      |   11 +
 .../files/patch-src_slic3r_Utils_Serial.cpp        |   20 +
 .../files/patch-src_slic3r_Utils_WxFontUtils.cpp   |   45 +
 .../files/patch-tests_fff__print_test__data.cpp    |   21 +-
 .../files/patch-tests_libslic3r_test__emboss.cpp   |   11 +
 58 files changed, 5705 insertions(+), 117 deletions(-)

diff --git a/cad/PrusaSlicer/Makefile b/cad/PrusaSlicer/Makefile
index c01ff53595eb..03f557a5919c 100644
--- a/cad/PrusaSlicer/Makefile
+++ b/cad/PrusaSlicer/Makefile
@@ -1,8 +1,9 @@
 PORTNAME=	PrusaSlicer
 DISTVERSIONPREFIX=version_
-DISTVERSION=	2.5.1
-PORTREVISION=	7
+DISTVERSION=	2.6.0
+PORTREVISION=	1
 CATEGORIES=	cad
+DIST_SUBDIR=	PrusaSlicer
 
 MAINTAINER=	teodorsigaev@gmail.com
 COMMENT=	Slicing application for 3D printers
@@ -14,12 +15,15 @@ LICENSE_FILE=	${WRKSRC}/LICENSE
 BUILD_DEPENDS=	cereal>=1.3.0.10:devel/cereal \
 		cgal>=5.0.2:math/cgal \
 		opencascade>=7.7.0:cad/opencascade
+
 LIB_DEPENDS=	libtbb.so:devel/onetbb \
 		libboost_log.so:devel/boost-libs \
 		libImath.so:math/Imath \
 		libnlopt.so:math/nlopt \
+		libqhull_r.so:math/qhull \
 		libcurl.so:ftp/curl \
 		libexpat.so:textproc/expat2 \
+		libiconv.so:converters/libiconv \
 		libopenvdb.so:misc/openvdb \
 		libgmp.so:math/gmp \
 		libmpfr.so:math/mpfr \
@@ -31,7 +35,8 @@ LIB_DEPENDS=	libtbb.so:devel/onetbb \
 		libfreeimage.so:graphics/freeimage \
 		libfreetype.so:print/freetype2 \
 		libavcodec.so:multimedia/ffmpeg \
-		libharfbuzz.so:print/harfbuzz
+		libharfbuzz.so:print/harfbuzz \
+		libwayland-egl.so:graphics/wayland
 
 USES=		cmake cpe desktop-file-utils eigen:3 gettext gl pkgconfig jpeg iconv gnome xorg
 CPE_VENDOR=	prusa3d
@@ -44,7 +49,8 @@ USE_XORG=	x11
 
 CMAKE_ARGS+=	-DwxWidgets_CONFIG_EXECUTABLE="${WX_CONFIG}" \
 		-DSLIC3R_GTK=3 \
-		-DSLIC3R_FHS=1
+		-DSLIC3R_FHS=1 \
+                -DSLIC3R_PCH=OFF
 
 PORTDATA=	*
 
diff --git a/cad/PrusaSlicer/distinfo b/cad/PrusaSlicer/distinfo
index 893c37013372..209b6b9fb7c8 100644
--- a/cad/PrusaSlicer/distinfo
+++ b/cad/PrusaSlicer/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1679421999
-SHA256 (prusa3d-PrusaSlicer-version_2.5.1_GH0.tar.gz) = 4fa14a4604ccf8042c3cbefe4c0a481d293e075030920799fe3f5e6247ef93ca
-SIZE (prusa3d-PrusaSlicer-version_2.5.1_GH0.tar.gz) = 48888707
+TIMESTAMP = 1690319127
+SHA256 (PrusaSlicer/prusa3d-PrusaSlicer-version_2.6.0_GH0.tar.gz) = a15f68e3b18a047c8c9a18a9d91629d2c777be1932087684cf6d2332d0888e77
+SIZE (PrusaSlicer/prusa3d-PrusaSlicer-version_2.6.0_GH0.tar.gz) = 56430180
diff --git a/cad/PrusaSlicer/files/patch-CMakeLists.txt b/cad/PrusaSlicer/files/patch-CMakeLists.txt
index ef5fab78c7e5..73daa6aa4e9b 100644
--- a/cad/PrusaSlicer/files/patch-CMakeLists.txt
+++ b/cad/PrusaSlicer/files/patch-CMakeLists.txt
@@ -1,6 +1,6 @@
---- CMakeLists.txt.orig	2022-09-06 07:09:19 UTC
+--- CMakeLists.txt.orig	2023-06-19 12:07:14 UTC
 +++ CMakeLists.txt
-@@ -4,6 +4,7 @@ project(PrusaSlicer)
+@@ -4,6 +4,7 @@ include(CMakeDependentOption)
  include("version.inc")
  include(GNUInstallDirs)
  include(CMakeDependentOption)
@@ -8,7 +8,7 @@
  
  set(SLIC3R_RESOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/resources")
  file(TO_NATIVE_PATH "${SLIC3R_RESOURCES_DIR}" SLIC3R_RESOURCES_DIR_WIN)
-@@ -197,7 +198,7 @@ if (APPLE)
+@@ -207,7 +208,7 @@ endif ()
      endif ()
  endif ()
  
@@ -17,7 +17,16 @@
      find_package(PkgConfig REQUIRED)
  
      if (CMAKE_VERSION VERSION_LESS "3.1")
-@@ -597,8 +598,8 @@ elseif (SLIC3R_FHS)
+@@ -446,7 +447,7 @@ find_package(EXPAT REQUIRED)
+ # no matter what.
+ find_package(EXPAT REQUIRED)
+ 
+-add_library(libexpat INTERFACE)
++# add_library(libexpat INTERFACE)
+ 
+ if (TARGET EXPAT::EXPAT )
+     target_link_libraries(libexpat INTERFACE EXPAT::EXPAT)
+@@ -627,8 +628,8 @@ elseif (SLIC3R_FHS)
      install(DIRECTORY ${SLIC3R_RESOURCES_DIR}/ DESTINATION ${SLIC3R_FHS_RESOURCES}
          PATTERN "*/udev" EXCLUDE
      )
@@ -28,7 +37,7 @@
      foreach(SIZE 32 128 192)
          install(FILES ${SLIC3R_RESOURCES_DIR}/icons/PrusaSlicer_${SIZE}px.png
              DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}x${SIZE}/apps RENAME PrusaSlicer.png
-@@ -607,7 +608,8 @@ elseif (SLIC3R_FHS)
+@@ -637,7 +638,8 @@ elseif (SLIC3R_FHS)
              DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/${SIZE}x${SIZE}/apps RENAME PrusaSlicer-gcodeviewer.png
          )
      endforeach()
diff --git a/cad/PrusaSlicer/files/patch-src_CMakeLists.txt b/cad/PrusaSlicer/files/patch-src_CMakeLists.txt
index 5072871d7f95..e084cdc3c97c 100644
--- a/cad/PrusaSlicer/files/patch-src_CMakeLists.txt
+++ b/cad/PrusaSlicer/files/patch-src_CMakeLists.txt
@@ -1,10 +1,19 @@
---- src/CMakeLists.txt.orig	2022-09-06 07:09:19 UTC
+--- src/CMakeLists.txt.orig	2023-06-19 12:07:14 UTC
 +++ src/CMakeLists.txt
-@@ -127,7 +127,7 @@ if (NOT WIN32 AND NOT APPLE)
+@@ -78,7 +78,7 @@ if (SLIC3R_GUI)
+ 
+     find_package(JPEG QUIET)
+     find_package(TIFF QUIET)
+-    find_package(NanoSVG REQUIRED)
++    # find_package(NanoSVG REQUIRED)
+ 
+     string(REGEX MATCH "wxpng" WX_PNG_BUILTIN ${wxWidgets_LIBRARIES})
+     if (PNG_FOUND AND NOT WX_PNG_BUILTIN)
+@@ -147,7 +147,7 @@ endif ()
      set_target_properties(PrusaSlicer PROPERTIES OUTPUT_NAME "prusa-slicer")
  endif ()
  
--target_link_libraries(PrusaSlicer libslic3r cereal)
+-target_link_libraries(PrusaSlicer libslic3r libcereal)
 +target_link_libraries(PrusaSlicer libslic3r)
  
  if (APPLE)
diff --git a/cad/PrusaSlicer/files/patch-src_avrdude_arduino.c b/cad/PrusaSlicer/files/patch-src_avrdude_arduino.c
new file mode 100644
index 000000000000..c7c282d53832
--- /dev/null
+++ b/cad/PrusaSlicer/files/patch-src_avrdude_arduino.c
@@ -0,0 +1,10 @@
+--- src/avrdude/arduino.c.orig	2023-07-25 13:23:52 UTC
++++ src/avrdude/arduino.c
+@@ -28,6 +28,7 @@
+ #include "ac_cfg.h"
+ 
+ #include <stdio.h>
++#include <stdlib.h>
+ #include <string.h>
+ #include <unistd.h>
+ 
diff --git a/cad/PrusaSlicer/files/patch-src_libnanosvg_nanosvg.h b/cad/PrusaSlicer/files/patch-src_libnanosvg_nanosvg.h
new file mode 100644
index 000000000000..08bf0beb1ef1
--- /dev/null
+++ b/cad/PrusaSlicer/files/patch-src_libnanosvg_nanosvg.h
@@ -0,0 +1,3109 @@
+--- src/libnanosvg/nanosvg.h.orig	1970-01-01 01:00:00.000000000 +0100
++++ src/libnanosvg/nanosvg.h	2022-12-22 00:42:08.000000000 +0100
+@@ -0,0 +1,3106 @@
++/*
++ * Copyright (c) 2013-14 Mikko Mononen memon@inside.org
++ *
++ * This software is provided 'as-is', without any express or implied
++ * warranty.  In no event will the authors be held liable for any damages
++ * arising from the use of this software.
++ *
++ * Permission is granted to anyone to use this software for any purpose,
++ * including commercial applications, and to alter it and redistribute it
++ * freely, subject to the following restrictions:
++ *
++ * 1. The origin of this software must not be misrepresented; you must not
++ * claim that you wrote the original software. If you use this software
++ * in a product, an acknowledgment in the product documentation would be
++ * appreciated but is not required.
++ * 2. Altered source versions must be plainly marked as such, and must not be
++ * misrepresented as being the original software.
++ * 3. This notice may not be removed or altered from any source distribution.
++ *
++ * The SVG parser is based on Anti-Grain Geometry 2.4 SVG example
++ * Copyright (C) 2002-2004 Maxim Shemanarev (McSeem) (http://www.antigrain.com/)
++ *
++ * Arc calculation code based on canvg (https://code.google.com/p/canvg/)
++ *
++ * Bounding box calculation based on http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
++ *
++ */
++
++#ifndef NANOSVG_H
++#define NANOSVG_H
++
++#ifndef NANOSVG_CPLUSPLUS
++#ifdef __cplusplus
++extern "C" {
++#endif
++#endif
++
++// NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes.
++//
++// The library suits well for anything from rendering scalable icons in your editor application to prototyping a game.
++//
++// NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request!
++//
++// The shapes in the SVG images are transformed by the viewBox and converted to specified units.
++// That is, you should get the same looking data as your designed in your favorite app.
++//
++// NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose
++// to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters.
++//
++// The units passed to NanoSVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'.
++// DPI (dots-per-inch) controls how the unit conversion is done.
++//
++// If you don't know or care about the units stuff, "px" and 96 should get you going.
++
++
++/* Example Usage:
++	// Load SVG
++	NSVGimage* image;
++	image = nsvgParseFromFile("test.svg", "px", 96);
++	printf("size: %f x %f\n", image->width, image->height);
++	// Use...
++	for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
++		for (NSVGpath *path = shape->paths; path != NULL; path = path->next) {
++			for (int i = 0; i < path->npts-1; i += 3) {
++				float* p = &path->pts[i*2];
++				drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
++			}
++		}
++	}
++	// Delete
++	nsvgDelete(image);
++*/
++
++enum NSVGpaintType {
++	NSVG_PAINT_UNDEF = -1,
++	NSVG_PAINT_NONE = 0,
++	NSVG_PAINT_COLOR = 1,
++	NSVG_PAINT_LINEAR_GRADIENT = 2,
++	NSVG_PAINT_RADIAL_GRADIENT = 3
++};
++
++enum NSVGspreadType {
++	NSVG_SPREAD_PAD = 0,
++	NSVG_SPREAD_REFLECT = 1,
++	NSVG_SPREAD_REPEAT = 2
++};
++
++enum NSVGlineJoin {
++	NSVG_JOIN_MITER = 0,
++	NSVG_JOIN_ROUND = 1,
++	NSVG_JOIN_BEVEL = 2
++};
++
++enum NSVGlineCap {
++	NSVG_CAP_BUTT = 0,
++	NSVG_CAP_ROUND = 1,
++	NSVG_CAP_SQUARE = 2
++};
++
++enum NSVGfillRule {
++	NSVG_FILLRULE_NONZERO = 0,
++	NSVG_FILLRULE_EVENODD = 1
++};
++
++enum NSVGflags {
++	NSVG_FLAGS_VISIBLE = 0x01
++};
++
++typedef struct NSVGgradientStop {
++	unsigned int color;
++	float offset;
++} NSVGgradientStop;
++
++typedef struct NSVGgradient {
++	float xform[6];
++	char spread;
++	float fx, fy;
++	int nstops;
++	NSVGgradientStop stops[1];
++} NSVGgradient;
++
++typedef struct NSVGpaint {
++	signed char type;
++	union {
++		unsigned int color;
++		NSVGgradient* gradient;
++	};
++} NSVGpaint;
++
++typedef struct NSVGpath
++{
++	float* pts;					// Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
++	int npts;					// Total number of bezier points.
++	char closed;				// Flag indicating if shapes should be treated as closed.
++	float bounds[4];			// Tight bounding box of the shape [minx,miny,maxx,maxy].
++	struct NSVGpath* next;		// Pointer to next path, or NULL if last element.
++} NSVGpath;
++
++typedef struct NSVGshape
++{
++	char id[64];				// Optional 'id' attr of the shape or its group
++	NSVGpaint fill;				// Fill paint
++	NSVGpaint stroke;			// Stroke paint
++	float opacity;				// Opacity of the shape.
++	float strokeWidth;			// Stroke width (scaled).
++	float strokeDashOffset;		// Stroke dash offset (scaled).
++	float strokeDashArray[8];	// Stroke dash array (scaled).
++	char strokeDashCount;		// Number of dash values in dash array.
++	char strokeLineJoin;		// Stroke join type.
++	char strokeLineCap;			// Stroke cap type.
++	float miterLimit;			// Miter limit
++	char fillRule;				// Fill rule, see NSVGfillRule.
++	unsigned char flags;		// Logical or of NSVG_FLAGS_* flags
++	float bounds[4];			// Tight bounding box of the shape [minx,miny,maxx,maxy].
++	char fillGradient[64];		// Optional 'id' of fill gradient
++	char strokeGradient[64];	// Optional 'id' of stroke gradient
++	float xform[6];				// Root transformation for fill/stroke gradient
++	NSVGpath* paths;			// Linked list of paths in the image.
++	struct NSVGshape* next;		// Pointer to next shape, or NULL if last element.
++} NSVGshape;
++
++typedef struct NSVGimage
++{
++	float width;				// Width of the image.
++	float height;				// Height of the image.
++	NSVGshape* shapes;			// Linked list of shapes in the image.
++} NSVGimage;
++
++// Parses SVG file from a file, returns SVG image as paths.
++NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi);
++
++// Parses SVG file from a null terminated string, returns SVG image as paths.
++// Important note: changes the string.
++NSVGimage* nsvgParse(char* input, const char* units, float dpi);
++
++// Duplicates a path.
++NSVGpath* nsvgDuplicatePath(NSVGpath* p);
++
++// Deletes an image.
++void nsvgDelete(NSVGimage* image);
++
++#ifndef NANOSVG_CPLUSPLUS
++#ifdef __cplusplus
++}
++#endif
++#endif
++
++#ifdef NANOSVG_IMPLEMENTATION
++
++#include <string.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <math.h>
++
++#define NSVG_PI (3.14159265358979323846264338327f)
++#define NSVG_KAPPA90 (0.5522847493f)	// Length proportional to radius of a cubic bezier handle for 90deg arcs.
++
++#define NSVG_ALIGN_MIN 0
++#define NSVG_ALIGN_MID 1
++#define NSVG_ALIGN_MAX 2
++#define NSVG_ALIGN_NONE 0
++#define NSVG_ALIGN_MEET 1
++#define NSVG_ALIGN_SLICE 2
++
++#define NSVG_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0)
++#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16))
++
++#ifdef _MSC_VER
++	#pragma warning (disable: 4996) // Switch off security warnings
++	#pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings
++	#ifdef __cplusplus
++	#define NSVG_INLINE inline
++	#else
++	#define NSVG_INLINE
++	#endif
++#else
++	#define NSVG_INLINE inline
++#endif
++
++
++static int nsvg__isspace(char c)
++{
++	return strchr(" \t\n\v\f\r", c) != 0;
++}
++
++static int nsvg__isdigit(char c)
++{
++	return c >= '0' && c <= '9';
++}
++
++static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; }
++static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; }
++
++
++// Simple XML parser
++
++#define NSVG_XML_TAG 1
++#define NSVG_XML_CONTENT 2
++#define NSVG_XML_MAX_ATTRIBS 256
++
++static void nsvg__parseContent(char* s,
++							   void (*contentCb)(void* ud, const char* s),
++							   void* ud)
++{
++	// Trim start white spaces
++	while (*s && nsvg__isspace(*s)) s++;
++	if (!*s) return;
++
++	if (contentCb)
++		(*contentCb)(ud, s);
++}
++
++static void nsvg__parseElement(char* s,
++							   void (*startelCb)(void* ud, const char* el, const char** attr),
++							   void (*endelCb)(void* ud, const char* el),
++							   void* ud)
++{
++	const char* attr[NSVG_XML_MAX_ATTRIBS];
++	int nattr = 0;
++	char* name;
++	int start = 0;
++	int end = 0;
++	char quote;
++
++	// Skip white space after the '<'
++	while (*s && nsvg__isspace(*s)) s++;
++
++	// Check if the tag is end tag
++	if (*s == '/') {
++		s++;
++		end = 1;
++	} else {
++		start = 1;
++	}
++
++	// Skip comments, data and preprocessor stuff.
++	if (!*s || *s == '?' || *s == '!')
++		return;
++
++	// Get tag name
++	name = s;
++	while (*s && !nsvg__isspace(*s)) s++;
++	if (*s) { *s++ = '\0'; }
++
++	// Get attribs
++	while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) {
++		char* name = NULL;
++		char* value = NULL;
++
++		// Skip white space before the attrib name
++		while (*s && nsvg__isspace(*s)) s++;
++		if (!*s) break;
++		if (*s == '/') {
++			end = 1;
++			break;
++		}
++		name = s;
++		// Find end of the attrib name.
++		while (*s && !nsvg__isspace(*s) && *s != '=') s++;
++		if (*s) { *s++ = '\0'; }
++		// Skip until the beginning of the value.
++		while (*s && *s != '\"' && *s != '\'') s++;
++		if (!*s) break;
++		quote = *s;
++		s++;
++		// Store value and find the end of it.
++		value = s;
++		while (*s && *s != quote) s++;
++		if (*s) { *s++ = '\0'; }
++
++		// Store only well formed attributes
++		if (name && value) {
++			attr[nattr++] = name;
++			attr[nattr++] = value;
++		}
++	}
++
++	// List terminator
++	attr[nattr++] = 0;
++	attr[nattr++] = 0;
++
++	// Call callbacks.
++	if (start && startelCb)
++		(*startelCb)(ud, name, attr);
++	if (end && endelCb)
++		(*endelCb)(ud, name);
++}
++
++int nsvg__parseXML(char* input,
++				   void (*startelCb)(void* ud, const char* el, const char** attr),
++				   void (*endelCb)(void* ud, const char* el),
++				   void (*contentCb)(void* ud, const char* s),
++				   void* ud)
++{
++	char* s = input;
++	char* mark = s;
++	int state = NSVG_XML_CONTENT;
++	while (*s) {
++		if (*s == '<' && state == NSVG_XML_CONTENT) {
++			// Start of a tag
++			*s++ = '\0';
++			nsvg__parseContent(mark, contentCb, ud);
++			mark = s;
++			state = NSVG_XML_TAG;
++		} else if (*s == '>' && state == NSVG_XML_TAG) {
++			// Start of a content or new tag.
++			*s++ = '\0';
++			nsvg__parseElement(mark, startelCb, endelCb, ud);
++			mark = s;
++			state = NSVG_XML_CONTENT;
++		} else {
++			s++;
++		}
++	}
++
++	return 1;
++}
++
++
++/* Simple SVG parser. */
++
++#define NSVG_MAX_ATTR 128
++
++enum NSVGgradientUnits {
++	NSVG_USER_SPACE = 0,
++	NSVG_OBJECT_SPACE = 1
++};
++
++#define NSVG_MAX_DASHES 8
++
++enum NSVGunits {
++	NSVG_UNITS_USER,
++	NSVG_UNITS_PX,
++	NSVG_UNITS_PT,
++	NSVG_UNITS_PC,
++	NSVG_UNITS_MM,
++	NSVG_UNITS_CM,
++	NSVG_UNITS_IN,
++	NSVG_UNITS_PERCENT,
++	NSVG_UNITS_EM,
++	NSVG_UNITS_EX
++};
++
++typedef struct NSVGcoordinate {
++	float value;
++	int units;
++} NSVGcoordinate;
++
++typedef struct NSVGlinearData {
++	NSVGcoordinate x1, y1, x2, y2;
++} NSVGlinearData;
++
++typedef struct NSVGradialData {
++	NSVGcoordinate cx, cy, r, fx, fy;
++} NSVGradialData;
++
++typedef struct NSVGgradientData
++{
++	char id[64];
++	char ref[64];
++	signed char type;
++	union {
++		NSVGlinearData linear;
++		NSVGradialData radial;
++	};
++	char spread;
++	char units;
++	float xform[6];
++	int nstops;
++	NSVGgradientStop* stops;
++	struct NSVGgradientData* next;
++} NSVGgradientData;
++
++typedef struct NSVGattrib
++{
++	char id[64];
++	float xform[6];
++	unsigned int fillColor;
++	unsigned int strokeColor;
++	float opacity;
++	float fillOpacity;
++	float strokeOpacity;
++	char fillGradient[64];
++	char strokeGradient[64];
++	float strokeWidth;
++	float strokeDashOffset;
++	float strokeDashArray[NSVG_MAX_DASHES];
++	int strokeDashCount;
++	char strokeLineJoin;
++	char strokeLineCap;
++	float miterLimit;
++	char fillRule;
++	float fontSize;
++	unsigned int stopColor;
++	float stopOpacity;
++	float stopOffset;
++	char hasFill;
++	char hasStroke;
++	char visible;
++} NSVGattrib;
++
++typedef struct NSVGparser
++{
++	NSVGattrib attr[NSVG_MAX_ATTR];
++	int attrHead;
++	float* pts;
++	int npts;
++	int cpts;
++	NSVGpath* plist;
++	NSVGimage* image;
++	NSVGgradientData* gradients;
++	NSVGshape* shapesTail;
++	float viewMinx, viewMiny, viewWidth, viewHeight;
++	int alignX, alignY, alignType;
++	float dpi;
++	char pathFlag;
++	char defsFlag;
++} NSVGparser;
++
++static void nsvg__xformIdentity(float* t)
++{
++	t[0] = 1.0f; t[1] = 0.0f;
++	t[2] = 0.0f; t[3] = 1.0f;
++	t[4] = 0.0f; t[5] = 0.0f;
++}
++
++static void nsvg__xformSetTranslation(float* t, float tx, float ty)
++{
++	t[0] = 1.0f; t[1] = 0.0f;
++	t[2] = 0.0f; t[3] = 1.0f;
++	t[4] = tx; t[5] = ty;
++}
++
++static void nsvg__xformSetScale(float* t, float sx, float sy)
++{
++	t[0] = sx; t[1] = 0.0f;
++	t[2] = 0.0f; t[3] = sy;
++	t[4] = 0.0f; t[5] = 0.0f;
++}
++
++static void nsvg__xformSetSkewX(float* t, float a)
++{
++	t[0] = 1.0f; t[1] = 0.0f;
++	t[2] = tanf(a); t[3] = 1.0f;
++	t[4] = 0.0f; t[5] = 0.0f;
++}
++
++static void nsvg__xformSetSkewY(float* t, float a)
++{
++	t[0] = 1.0f; t[1] = tanf(a);
++	t[2] = 0.0f; t[3] = 1.0f;
++	t[4] = 0.0f; t[5] = 0.0f;
++}
++
++static void nsvg__xformSetRotation(float* t, float a)
++{
++	float cs = cosf(a), sn = sinf(a);
++	t[0] = cs; t[1] = sn;
++	t[2] = -sn; t[3] = cs;
++	t[4] = 0.0f; t[5] = 0.0f;
++}
++
++static void nsvg__xformMultiply(float* t, float* s)
++{
++	float t0 = t[0] * s[0] + t[1] * s[2];
++	float t2 = t[2] * s[0] + t[3] * s[2];
++	float t4 = t[4] * s[0] + t[5] * s[2] + s[4];
++	t[1] = t[0] * s[1] + t[1] * s[3];
++	t[3] = t[2] * s[1] + t[3] * s[3];
++	t[5] = t[4] * s[1] + t[5] * s[3] + s[5];
++	t[0] = t0;
++	t[2] = t2;
++	t[4] = t4;
++}
++
++static void nsvg__xformInverse(float* inv, float* t)
++{
++	double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1];
++	if (det > -1e-6 && det < 1e-6) {
++		nsvg__xformIdentity(t);
++		return;
++	}
++	invdet = 1.0 / det;
++	inv[0] = (float)(t[3] * invdet);
++	inv[2] = (float)(-t[2] * invdet);
++	inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
++	inv[1] = (float)(-t[1] * invdet);
++	inv[3] = (float)(t[0] * invdet);
++	inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
++}
++
++static void nsvg__xformPremultiply(float* t, float* s)
++{
++	float s2[6];
++	memcpy(s2, s, sizeof(float)*6);
++	nsvg__xformMultiply(s2, t);
++	memcpy(t, s2, sizeof(float)*6);
++}
++
++static void nsvg__xformPoint(float* dx, float* dy, float x, float y, float* t)
++{
++	*dx = x*t[0] + y*t[2] + t[4];
++	*dy = x*t[1] + y*t[3] + t[5];
++}
++
++static void nsvg__xformVec(float* dx, float* dy, float x, float y, float* t)
++{
++	*dx = x*t[0] + y*t[2];
++	*dy = x*t[1] + y*t[3];
++}
++
++#define NSVG_EPSILON (1e-12)
++
++static int nsvg__ptInBounds(float* pt, float* bounds)
++{
++	return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3];
++}
++
++
++static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3)
++{
++	double it = 1.0-t;
++	return it*it*it*p0 + 3.0*it*it*t*p1 + 3.0*it*t*t*p2 + t*t*t*p3;
++}
++
++static void nsvg__curveBounds(float* bounds, float* curve)
++{
++	int i, j, count;
++	double roots[2], a, b, c, b2ac, t, v;
++	float* v0 = &curve[0];
++	float* v1 = &curve[2];
++	float* v2 = &curve[4];
++	float* v3 = &curve[6];
++
++	// Start the bounding box by end points
++	bounds[0] = nsvg__minf(v0[0], v3[0]);
++	bounds[1] = nsvg__minf(v0[1], v3[1]);
++	bounds[2] = nsvg__maxf(v0[0], v3[0]);
++	bounds[3] = nsvg__maxf(v0[1], v3[1]);
++
++	// Bezier curve fits inside the convex hull of it's control points.
++	// If control points are inside the bounds, we're done.
++	if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds))
++		return;
++
++	// Add bezier curve inflection points in X and Y.
++	for (i = 0; i < 2; i++) {
++		a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i];
++		b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i];
++		c = 3.0 * v1[i] - 3.0 * v0[i];
++		count = 0;
++		if (fabs(a) < NSVG_EPSILON) {
++			if (fabs(b) > NSVG_EPSILON) {
++				t = -c / b;
++				if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
++					roots[count++] = t;
++			}
++		} else {
++			b2ac = b*b - 4.0*c*a;
++			if (b2ac > NSVG_EPSILON) {
++				t = (-b + sqrt(b2ac)) / (2.0 * a);
++				if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
++					roots[count++] = t;
++				t = (-b - sqrt(b2ac)) / (2.0 * a);
++				if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
++					roots[count++] = t;
++			}
++		}
++		for (j = 0; j < count; j++) {
++			v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]);
++			bounds[0+i] = nsvg__minf(bounds[0+i], (float)v);
++			bounds[2+i] = nsvg__maxf(bounds[2+i], (float)v);
++		}
++	}
++}
++
++static NSVGparser* nsvg__createParser(void)
++{
++	NSVGparser* p;
++	p = (NSVGparser*)malloc(sizeof(NSVGparser));
++	if (p == NULL) goto error;
++	memset(p, 0, sizeof(NSVGparser));
++
++	p->image = (NSVGimage*)malloc(sizeof(NSVGimage));
++	if (p->image == NULL) goto error;
++	memset(p->image, 0, sizeof(NSVGimage));
++
++	// Init style
++	nsvg__xformIdentity(p->attr[0].xform);
++	memset(p->attr[0].id, 0, sizeof p->attr[0].id);
++	p->attr[0].fillColor = NSVG_RGB(0,0,0);
++	p->attr[0].strokeColor = NSVG_RGB(0,0,0);
++	p->attr[0].opacity = 1;
++	p->attr[0].fillOpacity = 1;
++	p->attr[0].strokeOpacity = 1;
++	p->attr[0].stopOpacity = 1;
++	p->attr[0].strokeWidth = 1;
++	p->attr[0].strokeLineJoin = NSVG_JOIN_MITER;
++	p->attr[0].strokeLineCap = NSVG_CAP_BUTT;
++	p->attr[0].miterLimit = 4;
++	p->attr[0].fillRule = NSVG_FILLRULE_NONZERO;
++	p->attr[0].hasFill = 1;
++	p->attr[0].visible = 1;
++
++	return p;
++
++error:
++	if (p) {
++		if (p->image) free(p->image);
++		free(p);
++	}
++	return NULL;
++}
++
++static void nsvg__deletePaths(NSVGpath* path)
++{
++	while (path) {
++		NSVGpath *next = path->next;
++		if (path->pts != NULL)
++			free(path->pts);
++		free(path);
++		path = next;
++	}
++}
++
++static void nsvg__deletePaint(NSVGpaint* paint)
++{
++	if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT)
++		free(paint->gradient);
++}
++
++static void nsvg__deleteGradientData(NSVGgradientData* grad)
++{
++	NSVGgradientData* next;
++	while (grad != NULL) {
++		next = grad->next;
++		free(grad->stops);
++		free(grad);
++		grad = next;
++	}
++}
++
++static void nsvg__deleteParser(NSVGparser* p)
++{
++	if (p != NULL) {
++		nsvg__deletePaths(p->plist);
++		nsvg__deleteGradientData(p->gradients);
++		nsvgDelete(p->image);
++		free(p->pts);
++		free(p);
++	}
++}
++
++static void nsvg__resetPath(NSVGparser* p)
++{
++	p->npts = 0;
++}
++
++static void nsvg__addPoint(NSVGparser* p, float x, float y)
++{
++	if (p->npts+1 > p->cpts) {
++		p->cpts = p->cpts ? p->cpts*2 : 8;
++		p->pts = (float*)realloc(p->pts, p->cpts*2*sizeof(float));
++		if (!p->pts) return;
++	}
++	p->pts[p->npts*2+0] = x;
++	p->pts[p->npts*2+1] = y;
++	p->npts++;
++}
++
++static void nsvg__moveTo(NSVGparser* p, float x, float y)
++{
++	if (p->npts > 0) {
++		p->pts[(p->npts-1)*2+0] = x;
++		p->pts[(p->npts-1)*2+1] = y;
++	} else {
++		nsvg__addPoint(p, x, y);
++	}
++}
++
++static void nsvg__lineTo(NSVGparser* p, float x, float y)
++{
++	float px,py, dx,dy;
++	if (p->npts > 0) {
++		px = p->pts[(p->npts-1)*2+0];
++		py = p->pts[(p->npts-1)*2+1];
++		dx = x - px;
++		dy = y - py;
++		nsvg__addPoint(p, px + dx/3.0f, py + dy/3.0f);
++		nsvg__addPoint(p, x - dx/3.0f, y - dy/3.0f);
++		nsvg__addPoint(p, x, y);
++	}
++}
++
++static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y)
++{
++	if (p->npts > 0) {
++		nsvg__addPoint(p, cpx1, cpy1);
++		nsvg__addPoint(p, cpx2, cpy2);
++		nsvg__addPoint(p, x, y);
++	}
++}
++
++static NSVGattrib* nsvg__getAttr(NSVGparser* p)
++{
++	return &p->attr[p->attrHead];
++}
*** 5361 LINES SKIPPED ***