Added simple SVG image support based on Nano SVG
authorSam Lantinga <slouken@libsdl.org>
Sun, 22 Oct 2017 00:36:06 -0700
changeset 524b4b49635cbd8
parent 523 dfe0320bc98b
child 525 fbc5ef52a0cd
Added simple SVG image support based on Nano SVG
SVG images with CSS styles are not supported yet.
Android.mk
CHANGES.txt
IMG.c
IMG_svg.c
Makefile.am
Makefile.in
README.txt
SDL_image.h
VisualC-WinRT/WinPhone80_VS2012/SDL_image-WinPhone80.sln
VisualC-WinRT/WinPhone80_VS2012/SDL_image-WinPhone80.vcxproj
VisualC-WinRT/WinPhone80_VS2012/SDL_image-WinPhone80.vcxproj.filters
VisualC-WinRT/WinPhone81_VS2013/SDL_image-WinPhone81.sln
VisualC-WinRT/WinPhone81_VS2013/SDL_image-WinPhone81.vcxproj
VisualC-WinRT/WinPhone81_VS2013/SDL_image-WinPhone81.vcxproj.filters
VisualC-WinRT/WinRT80_VS2012/SDL_image-WinRT80.sln
VisualC-WinRT/WinRT80_VS2012/SDL_image-WinRT80.vcxproj
VisualC-WinRT/WinRT80_VS2012/SDL_image-WinRT80.vcxproj.filters
VisualC-WinRT/WinRT81_VS2013/SDL_image-WinRT81.sln
VisualC-WinRT/WinRT81_VS2013/SDL_image-WinRT81.vcxproj
VisualC-WinRT/WinRT81_VS2013/SDL_image-WinRT81.vcxproj.filters
VisualC/SDL_image.vcxproj
VisualC/SDL_image.vcxproj.filters
Xcode-iOS/SDL_image.xcodeproj/project.pbxproj
Xcode/SDL_image.xcodeproj/project.pbxproj
aclocal.m4
configure
configure.in
nanosvg.h
nanosvgrast.h
     1.1 --- a/Android.mk	Sat Oct 21 22:14:52 2017 -0700
     1.2 +++ b/Android.mk	Sun Oct 22 00:36:06 2017 -0700
     1.3 @@ -24,7 +24,7 @@
     1.4  
     1.5  LOCAL_C_INCLUDES := $(LOCAL_PATH)
     1.6  LOCAL_CFLAGS := -DLOAD_BMP -DLOAD_GIF -DLOAD_LBM -DLOAD_PCX -DLOAD_PNM \
     1.7 -                -DLOAD_TGA -DLOAD_XCF -DLOAD_XPM -DLOAD_XV
     1.8 +                -DLOAD_SVG -DLOAD_TGA -DLOAD_XCF -DLOAD_XPM -DLOAD_XV
     1.9  LOCAL_CFLAGS += -O3 -fstrict-aliasing -fprefetch-loop-arrays
    1.10  
    1.11  LOCAL_SRC_FILES := $(notdir $(filter-out %/showimage.c, $(wildcard $(LOCAL_PATH)/*.c)))
     2.1 --- a/CHANGES.txt	Sat Oct 21 22:14:52 2017 -0700
     2.2 +++ b/CHANGES.txt	Sun Oct 22 00:36:06 2017 -0700
     2.3 @@ -1,4 +1,7 @@
     2.4  2.0.2:
     2.5 +Sam Lantinga - Sat Oct 21 23:42:28 PDT 2017
     2.6 + * Added simple SVG image support based on Nano SVG
     2.7 +   SVG images with CSS styles are not supported yet.
     2.8  Sam Lantinga - Sat Oct 21 22:14:34 PDT 2017
     2.9   * Updated external libraries jpeg-9b, libpng-1.6.32, libwebp-0.6.0, tiff-4.0.8 and zlib-1.2.11
    2.10  Yves Younan - Fri, Oct  6, 2017  3:38:38 PM
     3.1 --- a/IMG.c	Sat Oct 21 22:14:52 2017 -0700
     3.2 +++ b/IMG.c	Sun Oct 22 00:36:06 2017 -0700
     3.3 @@ -46,6 +46,7 @@
     3.4      { "PCX", IMG_isPCX, IMG_LoadPCX_RW },
     3.5      { "PNG", IMG_isPNG, IMG_LoadPNG_RW },
     3.6      { "PNM", IMG_isPNM, IMG_LoadPNM_RW }, /* P[BGP]M share code */
     3.7 +    { "SVG", IMG_isSVG, IMG_LoadSVG_RW },
     3.8      { "TIF", IMG_isTIF, IMG_LoadTIF_RW },
     3.9      { "XCF", IMG_isXCF, IMG_LoadXCF_RW },
    3.10      { "XPM", IMG_isXPM, IMG_LoadXPM_RW },
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/IMG_svg.c	Sun Oct 22 00:36:06 2017 -0700
     4.3 @@ -0,0 +1,126 @@
     4.4 +/*
     4.5 +  SDL_image:  An example image loading library for use with SDL
     4.6 +  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
     4.7 +
     4.8 +  This software is provided 'as-is', without any express or implied
     4.9 +  warranty.  In no event will the authors be held liable for any damages
    4.10 +  arising from the use of this software.
    4.11 +
    4.12 +  Permission is granted to anyone to use this software for any purpose,
    4.13 +  including commercial applications, and to alter it and redistribute it
    4.14 +  freely, subject to the following restrictions:
    4.15 +
    4.16 +  1. The origin of this software must not be misrepresented; you must not
    4.17 +     claim that you wrote the original software. If you use this software
    4.18 +     in a product, an acknowledgment in the product documentation would be
    4.19 +     appreciated but is not required.
    4.20 +  2. Altered source versions must be plainly marked as such, and must not be
    4.21 +     misrepresented as being the original software.
    4.22 +  3. This notice may not be removed or altered from any source distribution.
    4.23 +*/
    4.24 +
    4.25 +/* This is an SVG image file loading framework, based on Nano SVG:
    4.26 + * https://github.com/memononen/nanosvg
    4.27 + */
    4.28 +
    4.29 +#include "SDL_image.h"
    4.30 +
    4.31 +#ifdef LOAD_SVG
    4.32 +
    4.33 +#include <stdio.h>
    4.34 +#include <stdlib.h>
    4.35 +
    4.36 +/* Replace C runtime functions with SDL C runtime functions for building on Windows */
    4.37 +#define strtoll	SDL_strtoll
    4.38 +
    4.39 +#define NANOSVG_IMPLEMENTATION
    4.40 +#include "nanosvg.h"
    4.41 +#define NANOSVGRAST_IMPLEMENTATION
    4.42 +#include "nanosvgrast.h"
    4.43 +
    4.44 +/* See if an image is contained in a data source */
    4.45 +int IMG_isSVG(SDL_RWops *src)
    4.46 +{
    4.47 +    Sint64 start;
    4.48 +    int is_SVG;
    4.49 +    char magic[4096];
    4.50 +    size_t magic_len;
    4.51 +
    4.52 +    if ( !src )
    4.53 +        return 0;
    4.54 +    start = SDL_RWtell(src);
    4.55 +    is_SVG = 0;
    4.56 +    magic_len = SDL_RWread(src, magic, 1, sizeof(magic) - 1);
    4.57 +    magic[magic_len] = '\0';
    4.58 +    if ( SDL_strstr(magic, "<svg") ) {
    4.59 +        is_SVG = 1;
    4.60 +    }
    4.61 +    SDL_RWseek(src, start, RW_SEEK_SET);
    4.62 +    return(is_SVG);
    4.63 +}
    4.64 +
    4.65 +/* Load a SVG type image from an SDL datasource */
    4.66 +SDL_Surface *IMG_LoadSVG_RW(SDL_RWops *src)
    4.67 +{
    4.68 +    char *data;
    4.69 +    struct NSVGimage *image;
    4.70 +    struct NSVGrasterizer *rasterizer;
    4.71 +    SDL_Surface *surface = NULL;
    4.72 +    float scale = 3.0f;
    4.73 +
    4.74 +    data = (char *)SDL_LoadFile_RW(src, NULL, SDL_FALSE);
    4.75 +    if ( !data ) {
    4.76 +        return NULL;
    4.77 +    }
    4.78 +
    4.79 +    /* For now just use default units of pixels at 96 DPI */
    4.80 +    image = nsvgParse(data, "px", 96.0f);
    4.81 +    SDL_free(data);
    4.82 +    if ( !image ) {
    4.83 +        IMG_SetError("Couldn't parse SVG image");
    4.84 +        return NULL;
    4.85 +    }
    4.86 +
    4.87 +    rasterizer = nsvgCreateRasterizer();
    4.88 +    if ( !rasterizer ) {
    4.89 +        IMG_SetError("Couldn't create SVG rasterizer");
    4.90 +        nsvgDelete( image );
    4.91 +        return NULL;
    4.92 +    }
    4.93 +
    4.94 +    surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
    4.95 +                                   (int)(image->width * scale),
    4.96 +                                   (int)(image->height * scale),
    4.97 +                                   32,
    4.98 +                                   0x000000FF,
    4.99 +                                   0x0000FF00,
   4.100 +                                   0x00FF0000,
   4.101 +                                   0xFF000000);
   4.102 +    if ( !surface ) {
   4.103 +        nsvgDeleteRasterizer( rasterizer );
   4.104 +        nsvgDelete( image );
   4.105 +        return NULL;
   4.106 +    }
   4.107 +
   4.108 +    nsvgRasterize(rasterizer, image, 0.0f, 0.0f, scale, (unsigned char *)surface->pixels, surface->w, surface->h, surface->pitch);
   4.109 +    nsvgDeleteRasterizer( rasterizer );
   4.110 +    nsvgDelete( image );
   4.111 +
   4.112 +    return surface;
   4.113 +}
   4.114 +
   4.115 +#else
   4.116 +
   4.117 +/* See if an image is contained in a data source */
   4.118 +int IMG_isSVG(SDL_RWops *src)
   4.119 +{
   4.120 +    return(0);
   4.121 +}
   4.122 +
   4.123 +/* Load a SVG type image from an SDL datasource */
   4.124 +SDL_Surface *IMG_LoadSVG_RW(SDL_RWops *src)
   4.125 +{
   4.126 +    return(NULL);
   4.127 +}
   4.128 +
   4.129 +#endif /* LOAD_SVG */
     5.1 --- a/Makefile.am	Sat Oct 21 22:14:52 2017 -0700
     5.2 +++ b/Makefile.am	Sun Oct 22 00:36:06 2017 -0700
     5.3 @@ -19,6 +19,7 @@
     5.4  	IMG_pcx.c		\
     5.5  	IMG_png.c		\
     5.6  	IMG_pnm.c		\
     5.7 +	IMG_svg.c		\
     5.8  	IMG_tga.c		\
     5.9  	IMG_tif.c		\
    5.10  	IMG_xcf.c		\
     6.1 --- a/Makefile.in	Sat Oct 21 22:14:52 2017 -0700
     6.2 +++ b/Makefile.in	Sun Oct 22 00:36:06 2017 -0700
     6.3 @@ -1,7 +1,7 @@
     6.4 -# Makefile.in generated by automake 1.13.1 from Makefile.am.
     6.5 +# Makefile.in generated by automake 1.14 from Makefile.am.
     6.6  # @configure_input@
     6.7  
     6.8 -# Copyright (C) 1994-2012 Free Software Foundation, Inc.
     6.9 +# Copyright (C) 1994-2013 Free Software Foundation, Inc.
    6.10  
    6.11  # This Makefile.in is free software; the Free Software Foundation
    6.12  # gives unlimited permission to copy and/or distribute it,
    6.13 @@ -20,23 +20,51 @@
    6.14  
    6.15  
    6.16  VPATH = @srcdir@
    6.17 -am__make_dryrun = \
    6.18 -  { \
    6.19 -    am__dry=no; \
    6.20 +am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
    6.21 +am__make_running_with_option = \
    6.22 +  case $${target_option-} in \
    6.23 +      ?) ;; \
    6.24 +      *) echo "am__make_running_with_option: internal error: invalid" \
    6.25 +              "target option '$${target_option-}' specified" >&2; \
    6.26 +         exit 1;; \
    6.27 +  esac; \
    6.28 +  has_opt=no; \
    6.29 +  sane_makeflags=$$MAKEFLAGS; \
    6.30 +  if $(am__is_gnu_make); then \
    6.31 +    sane_makeflags=$$MFLAGS; \
    6.32 +  else \
    6.33      case $$MAKEFLAGS in \
    6.34        *\\[\ \	]*) \
    6.35 -        echo 'am--echo: ; @echo "AM"  OK' | $(MAKE) -f - 2>/dev/null \
    6.36 -          | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
    6.37 -      *) \
    6.38 -        for am__flg in $$MAKEFLAGS; do \
    6.39 -          case $$am__flg in \
    6.40 -            *=*|--*) ;; \
    6.41 -            *n*) am__dry=yes; break;; \
    6.42 -          esac; \
    6.43 -        done;; \
    6.44 +        bs=\\; \
    6.45 +        sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
    6.46 +          | sed "s/$$bs$$bs[$$bs $$bs	]*//g"`;; \
    6.47      esac; \
    6.48 -    test $$am__dry = yes; \
    6.49 -  }
    6.50 +  fi; \
    6.51 +  skip_next=no; \
    6.52 +  strip_trailopt () \
    6.53 +  { \
    6.54 +    flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
    6.55 +  }; \
    6.56 +  for flg in $$sane_makeflags; do \
    6.57 +    test $$skip_next = yes && { skip_next=no; continue; }; \
    6.58 +    case $$flg in \
    6.59 +      *=*|--*) continue;; \
    6.60 +        -*I) strip_trailopt 'I'; skip_next=yes;; \
    6.61 +      -*I?*) strip_trailopt 'I';; \
    6.62 +        -*O) strip_trailopt 'O'; skip_next=yes;; \
    6.63 +      -*O?*) strip_trailopt 'O';; \
    6.64 +        -*l) strip_trailopt 'l'; skip_next=yes;; \
    6.65 +      -*l?*) strip_trailopt 'l';; \
    6.66 +      -[dEDm]) skip_next=yes;; \
    6.67 +      -[JT]) skip_next=yes;; \
    6.68 +    esac; \
    6.69 +    case $$flg in \
    6.70 +      *$$target_option*) has_opt=yes; break;; \
    6.71 +    esac; \
    6.72 +  done; \
    6.73 +  test $$has_opt = yes
    6.74 +am__make_dryrun = (target_option=n; $(am__make_running_with_option))
    6.75 +am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
    6.76  pkgdatadir = $(datadir)/@PACKAGE@
    6.77  pkgincludedir = $(includedir)/@PACKAGE@
    6.78  pkglibdir = $(libdir)/@PACKAGE@
    6.79 @@ -62,7 +90,7 @@
    6.80  DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
    6.81  	$(top_srcdir)/configure $(am__configure_deps) \
    6.82  	$(srcdir)/SDL2_image.spec.in $(srcdir)/SDL2_image.pc.in \
    6.83 -	depcomp $(libSDL2_imageinclude_HEADERS) config.guess \
    6.84 +	depcomp $(libSDL2_imageinclude_HEADERS) compile config.guess \
    6.85  	config.sub install-sh missing ltmain.sh
    6.86  ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
    6.87  am__aclocal_m4_deps = $(top_srcdir)/acinclude/libtool.m4 \
    6.88 @@ -111,14 +139,14 @@
    6.89  LTLIBRARIES = $(lib_LTLIBRARIES)
    6.90  am__DEPENDENCIES_1 =
    6.91  am__libSDL2_image_la_SOURCES_DIST = IMG.c IMG_bmp.c IMG_gif.c \
    6.92 -	IMG_jpg.c IMG_lbm.c IMG_pcx.c IMG_png.c IMG_pnm.c IMG_tga.c \
    6.93 -	IMG_tif.c IMG_xcf.c IMG_xpm.c IMG_xv.c IMG_webp.c \
    6.94 +	IMG_jpg.c IMG_lbm.c IMG_pcx.c IMG_png.c IMG_pnm.c IMG_svg.c \
    6.95 +	IMG_tga.c IMG_tif.c IMG_xcf.c IMG_xpm.c IMG_xv.c IMG_webp.c \
    6.96  	IMG_ImageIO.m miniz.h
    6.97  @USE_IMAGEIO_TRUE@am__objects_1 = IMG_ImageIO.lo
    6.98  am_libSDL2_image_la_OBJECTS = IMG.lo IMG_bmp.lo IMG_gif.lo IMG_jpg.lo \
    6.99 -	IMG_lbm.lo IMG_pcx.lo IMG_png.lo IMG_pnm.lo IMG_tga.lo \
   6.100 -	IMG_tif.lo IMG_xcf.lo IMG_xpm.lo IMG_xv.lo IMG_webp.lo \
   6.101 -	$(am__objects_1)
   6.102 +	IMG_lbm.lo IMG_pcx.lo IMG_png.lo IMG_pnm.lo IMG_svg.lo \
   6.103 +	IMG_tga.lo IMG_tif.lo IMG_xcf.lo IMG_xpm.lo IMG_xv.lo \
   6.104 +	IMG_webp.lo $(am__objects_1)
   6.105  libSDL2_image_la_OBJECTS = $(am_libSDL2_image_la_OBJECTS)
   6.106  AM_V_lt = $(am__v_lt_@AM_V@)
   6.107  am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
   6.108 @@ -383,6 +411,7 @@
   6.109  	IMG_pcx.c		\
   6.110  	IMG_png.c		\
   6.111  	IMG_pnm.c		\
   6.112 +	IMG_svg.c		\
   6.113  	IMG_tga.c		\
   6.114  	IMG_tif.c		\
   6.115  	IMG_xcf.c		\
   6.116 @@ -501,6 +530,7 @@
   6.117  	  echo rm -f $${locs}; \
   6.118  	  rm -f $${locs}; \
   6.119  	}
   6.120 +
   6.121  libSDL2_image.la: $(libSDL2_image_la_OBJECTS) $(libSDL2_image_la_DEPENDENCIES) $(EXTRA_libSDL2_image_la_DEPENDENCIES) 
   6.122  	$(AM_V_OBJCLD)$(libSDL2_image_la_LINK) -rpath $(libdir) $(libSDL2_image_la_OBJECTS) $(libSDL2_image_la_LIBADD) $(LIBS)
   6.123  
   6.124 @@ -512,6 +542,7 @@
   6.125  	list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
   6.126  	echo " rm -f" $$list; \
   6.127  	rm -f $$list
   6.128 +
   6.129  showimage$(EXEEXT): $(showimage_OBJECTS) $(showimage_DEPENDENCIES) $(EXTRA_showimage_DEPENDENCIES) 
   6.130  	@rm -f showimage$(EXEEXT)
   6.131  	$(AM_V_CCLD)$(LINK) $(showimage_OBJECTS) $(showimage_LDADD) $(LIBS)
   6.132 @@ -531,6 +562,7 @@
   6.133  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG_pcx.Plo@am__quote@
   6.134  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG_png.Plo@am__quote@
   6.135  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG_pnm.Plo@am__quote@
   6.136 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG_svg.Plo@am__quote@
   6.137  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG_tga.Plo@am__quote@
   6.138  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG_tif.Plo@am__quote@
   6.139  @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IMG_webp.Plo@am__quote@
   6.140 @@ -544,14 +576,14 @@
   6.141  @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
   6.142  @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
   6.143  @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
   6.144 -@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c $<
   6.145 +@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
   6.146  
   6.147  .c.obj:
   6.148  @am__fastdepCC_TRUE@	$(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
   6.149  @am__fastdepCC_TRUE@	$(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
   6.150  @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
   6.151  @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
   6.152 -@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
   6.153 +@am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
   6.154  
   6.155  .c.lo:
   6.156  @am__fastdepCC_TRUE@	$(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
   6.157 @@ -747,10 +779,16 @@
   6.158  	$(am__post_remove_distdir)
   6.159  
   6.160  dist-tarZ: distdir
   6.161 +	@echo WARNING: "Support for shar distribution archives is" \
   6.162 +	               "deprecated." >&2
   6.163 +	@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
   6.164  	tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z
   6.165  	$(am__post_remove_distdir)
   6.166  
   6.167  dist-shar: distdir
   6.168 +	@echo WARNING: "Support for distribution archives compressed with" \
   6.169 +		       "legacy program 'compress' is deprecated." >&2
   6.170 +	@echo WARNING: "It will be removed altogether in Automake 2.0" >&2
   6.171  	shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz
   6.172  	$(am__post_remove_distdir)
   6.173  
     7.1 --- a/README.txt	Sat Oct 21 22:14:52 2017 -0700
     7.2 +++ b/README.txt	Sun Oct 22 00:36:06 2017 -0700
     7.3 @@ -6,7 +6,7 @@
     7.4  
     7.5  This is a simple library to load images of various formats as SDL surfaces.
     7.6  This library supports BMP, PNM (PPM/PGM/PBM), XPM, LBM, PCX, GIF, JPEG, PNG,
     7.7 -TGA, and TIFF formats.
     7.8 +TGA, TIFF, and simple SVG formats.
     7.9  
    7.10  API:
    7.11  #include "SDL_image.h"
     8.1 --- a/SDL_image.h	Sat Oct 21 22:14:52 2017 -0700
     8.2 +++ b/SDL_image.h	Sun Oct 22 00:36:06 2017 -0700
     8.3 @@ -115,6 +115,7 @@
     8.4  extern DECLSPEC int SDLCALL IMG_isPCX(SDL_RWops *src);
     8.5  extern DECLSPEC int SDLCALL IMG_isPNG(SDL_RWops *src);
     8.6  extern DECLSPEC int SDLCALL IMG_isPNM(SDL_RWops *src);
     8.7 +extern DECLSPEC int SDLCALL IMG_isSVG(SDL_RWops *src);
     8.8  extern DECLSPEC int SDLCALL IMG_isTIF(SDL_RWops *src);
     8.9  extern DECLSPEC int SDLCALL IMG_isXCF(SDL_RWops *src);
    8.10  extern DECLSPEC int SDLCALL IMG_isXPM(SDL_RWops *src);
    8.11 @@ -131,6 +132,7 @@
    8.12  extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPCX_RW(SDL_RWops *src);
    8.13  extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNG_RW(SDL_RWops *src);
    8.14  extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadPNM_RW(SDL_RWops *src);
    8.15 +extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadSVG_RW(SDL_RWops *src);
    8.16  extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTGA_RW(SDL_RWops *src);
    8.17  extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadTIF_RW(SDL_RWops *src);
    8.18  extern DECLSPEC SDL_Surface * SDLCALL IMG_LoadXCF_RW(SDL_RWops *src);
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/VisualC-WinRT/WinPhone80_VS2012/SDL_image-WinPhone80.sln	Sun Oct 22 00:36:06 2017 -0700
     9.3 @@ -0,0 +1,66 @@
     9.4 +
     9.5 +Microsoft Visual Studio Solution File, Format Version 12.00
     9.6 +# Visual Studio 2012
     9.7 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL2_image-WinPhone80", "SDL_image-WinPhone80.vcxproj", "{3E2A3587-B28C-4261-8E1C-EF9DCC742CC4}"
     9.8 +EndProject
     9.9 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jpeg-WinPhone80", "jpeg-WinPhone80.vcxproj", "{10CABD6E-BD1A-4705-BE35-A34CE1EDF6FB}"
    9.10 +EndProject
    9.11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng-WinPhone80", "libpng-WinPhone80.vcxproj", "{AF7120B3-ECF6-464D-A4A6-E56B91E81B50}"
    9.12 +EndProject
    9.13 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwebp-WinPhone80", "libwebp-WinPhone80.vcxproj", "{DD42165B-C5BE-43AB-9F7C-1C7D0F30ABF2}"
    9.14 +EndProject
    9.15 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib-WinPhone80", "zlib-WinPhone80.vcxproj", "{C9C04F20-60B6-42B7-A802-FA6EC1357E87}"
    9.16 +EndProject
    9.17 +Global
    9.18 +	GlobalSection(SolutionConfigurationPlatforms) = preSolution
    9.19 +		Debug|ARM = Debug|ARM
    9.20 +		Debug|Win32 = Debug|Win32
    9.21 +		Release|ARM = Release|ARM
    9.22 +		Release|Win32 = Release|Win32
    9.23 +	EndGlobalSection
    9.24 +	GlobalSection(ProjectConfigurationPlatforms) = postSolution
    9.25 +		{3E2A3587-B28C-4261-8E1C-EF9DCC742CC4}.Debug|ARM.ActiveCfg = Debug|ARM
    9.26 +		{3E2A3587-B28C-4261-8E1C-EF9DCC742CC4}.Debug|ARM.Build.0 = Debug|ARM
    9.27 +		{3E2A3587-B28C-4261-8E1C-EF9DCC742CC4}.Debug|Win32.ActiveCfg = Debug|Win32
    9.28 +		{3E2A3587-B28C-4261-8E1C-EF9DCC742CC4}.Debug|Win32.Build.0 = Debug|Win32
    9.29 +		{3E2A3587-B28C-4261-8E1C-EF9DCC742CC4}.Release|ARM.ActiveCfg = Release|ARM
    9.30 +		{3E2A3587-B28C-4261-8E1C-EF9DCC742CC4}.Release|ARM.Build.0 = Release|ARM
    9.31 +		{3E2A3587-B28C-4261-8E1C-EF9DCC742CC4}.Release|Win32.ActiveCfg = Release|Win32
    9.32 +		{3E2A3587-B28C-4261-8E1C-EF9DCC742CC4}.Release|Win32.Build.0 = Release|Win32
    9.33 +		{10CABD6E-BD1A-4705-BE35-A34CE1EDF6FB}.Debug|ARM.ActiveCfg = Debug|ARM
    9.34 +		{10CABD6E-BD1A-4705-BE35-A34CE1EDF6FB}.Debug|ARM.Build.0 = Debug|ARM
    9.35 +		{10CABD6E-BD1A-4705-BE35-A34CE1EDF6FB}.Debug|Win32.ActiveCfg = Debug|Win32
    9.36 +		{10CABD6E-BD1A-4705-BE35-A34CE1EDF6FB}.Debug|Win32.Build.0 = Debug|Win32
    9.37 +		{10CABD6E-BD1A-4705-BE35-A34CE1EDF6FB}.Release|ARM.ActiveCfg = Release|ARM
    9.38 +		{10CABD6E-BD1A-4705-BE35-A34CE1EDF6FB}.Release|ARM.Build.0 = Release|ARM
    9.39 +		{10CABD6E-BD1A-4705-BE35-A34CE1EDF6FB}.Release|Win32.ActiveCfg = Release|Win32
    9.40 +		{10CABD6E-BD1A-4705-BE35-A34CE1EDF6FB}.Release|Win32.Build.0 = Release|Win32
    9.41 +		{AF7120B3-ECF6-464D-A4A6-E56B91E81B50}.Debug|ARM.ActiveCfg = Debug|ARM
    9.42 +		{AF7120B3-ECF6-464D-A4A6-E56B91E81B50}.Debug|ARM.Build.0 = Debug|ARM
    9.43 +		{AF7120B3-ECF6-464D-A4A6-E56B91E81B50}.Debug|Win32.ActiveCfg = Debug|Win32
    9.44 +		{AF7120B3-ECF6-464D-A4A6-E56B91E81B50}.Debug|Win32.Build.0 = Debug|Win32
    9.45 +		{AF7120B3-ECF6-464D-A4A6-E56B91E81B50}.Release|ARM.ActiveCfg = Release|ARM
    9.46 +		{AF7120B3-ECF6-464D-A4A6-E56B91E81B50}.Release|ARM.Build.0 = Release|ARM
    9.47 +		{AF7120B3-ECF6-464D-A4A6-E56B91E81B50}.Release|Win32.ActiveCfg = Release|Win32
    9.48 +		{AF7120B3-ECF6-464D-A4A6-E56B91E81B50}.Release|Win32.Build.0 = Release|Win32
    9.49 +		{DD42165B-C5BE-43AB-9F7C-1C7D0F30ABF2}.Debug|ARM.ActiveCfg = Debug|ARM
    9.50 +		{DD42165B-C5BE-43AB-9F7C-1C7D0F30ABF2}.Debug|ARM.Build.0 = Debug|ARM
    9.51 +		{DD42165B-C5BE-43AB-9F7C-1C7D0F30ABF2}.Debug|Win32.ActiveCfg = Debug|Win32
    9.52 +		{DD42165B-C5BE-43AB-9F7C-1C7D0F30ABF2}.Debug|Win32.Build.0 = Debug|Win32
    9.53 +		{DD42165B-C5BE-43AB-9F7C-1C7D0F30ABF2}.Release|ARM.ActiveCfg = Release|ARM
    9.54 +		{DD42165B-C5BE-43AB-9F7C-1C7D0F30ABF2}.Release|ARM.Build.0 = Release|ARM
    9.55 +		{DD42165B-C5BE-43AB-9F7C-1C7D0F30ABF2}.Release|Win32.ActiveCfg = Release|Win32
    9.56 +		{DD42165B-C5BE-43AB-9F7C-1C7D0F30ABF2}.Release|Win32.Build.0 = Release|Win32
    9.57 +		{C9C04F20-60B6-42B7-A802-FA6EC1357E87}.Debug|ARM.ActiveCfg = Debug|ARM
    9.58 +		{C9C04F20-60B6-42B7-A802-FA6EC1357E87}.Debug|ARM.Build.0 = Debug|ARM
    9.59 +		{C9C04F20-60B6-42B7-A802-FA6EC1357E87}.Debug|Win32.ActiveCfg = Debug|Win32
    9.60 +		{C9C04F20-60B6-42B7-A802-FA6EC1357E87}.Debug|Win32.Build.0 = Debug|Win32
    9.61 +		{C9C04F20-60B6-42B7-A802-FA6EC1357E87}.Release|ARM.ActiveCfg = Release|ARM
    9.62 +		{C9C04F20-60B6-42B7-A802-FA6EC1357E87}.Release|ARM.Build.0 = Release|ARM
    9.63 +		{C9C04F20-60B6-42B7-A802-FA6EC1357E87}.Release|Win32.ActiveCfg = Release|Win32
    9.64 +		{C9C04F20-60B6-42B7-A802-FA6EC1357E87}.Release|Win32.Build.0 = Release|Win32
    9.65 +	EndGlobalSection
    9.66 +	GlobalSection(SolutionProperties) = preSolution
    9.67 +		HideSolutionNode = FALSE
    9.68 +	EndGlobalSection
    9.69 +EndGlobal
    10.1 --- a/VisualC-WinRT/WinPhone80_VS2012/SDL_image-WinPhone80.vcxproj	Sat Oct 21 22:14:52 2017 -0700
    10.2 +++ b/VisualC-WinRT/WinPhone80_VS2012/SDL_image-WinPhone80.vcxproj	Sun Oct 22 00:36:06 2017 -0700
    10.3 @@ -158,6 +158,7 @@
    10.4      <ClCompile Include="..\..\IMG_pcx.c" />
    10.5      <ClCompile Include="..\..\IMG_png.c" />
    10.6      <ClCompile Include="..\..\IMG_pnm.c" />
    10.7 +    <ClCompile Include="..\..\IMG_svg.c" />
    10.8      <ClCompile Include="..\..\IMG_tga.c" />
    10.9      <ClCompile Include="..\..\IMG_tif.c" />
   10.10      <ClCompile Include="..\..\IMG_webp.c" />
   10.11 @@ -184,4 +185,4 @@
   10.12    <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsPhone\v$(TargetPlatformVersion)\Microsoft.Cpp.WindowsPhone.$(TargetPlatformVersion).targets" />
   10.13    <ImportGroup Label="ExtensionTargets">
   10.14    </ImportGroup>
   10.15 -</Project>
   10.16 +</Project>
   10.17 \ No newline at end of file
    11.1 --- a/VisualC-WinRT/WinPhone80_VS2012/SDL_image-WinPhone80.vcxproj.filters	Sat Oct 21 22:14:52 2017 -0700
    11.2 +++ b/VisualC-WinRT/WinPhone80_VS2012/SDL_image-WinPhone80.vcxproj.filters	Sun Oct 22 00:36:06 2017 -0700
    11.3 @@ -16,5 +16,6 @@
    11.4      <ClCompile Include="..\..\IMG_xpm.c" />
    11.5      <ClCompile Include="..\..\IMG_xv.c" />
    11.6      <ClCompile Include="..\..\IMG_xxx.c" />
    11.7 +    <ClCompile Include="..\..\IMG_svg.c" />
    11.8    </ItemGroup>
    11.9  </Project>
   11.10 \ No newline at end of file
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/VisualC-WinRT/WinPhone81_VS2013/SDL_image-WinPhone81.sln	Sun Oct 22 00:36:06 2017 -0700
    12.3 @@ -0,0 +1,68 @@
    12.4 +
    12.5 +Microsoft Visual Studio Solution File, Format Version 12.00
    12.6 +# Visual Studio 2013
    12.7 +VisualStudioVersion = 12.0.40629.0
    12.8 +MinimumVisualStudioVersion = 10.0.40219.1
    12.9 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL2_image-WinPhone81", "SDL_image-WinPhone81.vcxproj", "{1444BB95-670B-4878-851B-7ED8DA0629A3}"
   12.10 +EndProject
   12.11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jpeg-WinPhone81", "jpeg-WinPhone81.vcxproj", "{4F241F1F-6636-47A9-AEB2-5B5157961B51}"
   12.12 +EndProject
   12.13 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng-WinPhone81", "libpng-WinPhone81.vcxproj", "{C396C32A-1A8D-4711-A3DB-206F188FC738}"
   12.14 +EndProject
   12.15 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwebp-WinPhone81", "libwebp-WinPhone81.vcxproj", "{9DC4D90A-0D6D-4150-9049-1F4358B59E06}"
   12.16 +EndProject
   12.17 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib-WinPhone81", "zlib-WinPhone81.vcxproj", "{183B6F21-DD86-49A1-BA70-C97D7C404469}"
   12.18 +EndProject
   12.19 +Global
   12.20 +	GlobalSection(SolutionConfigurationPlatforms) = preSolution
   12.21 +		Debug|ARM = Debug|ARM
   12.22 +		Debug|Win32 = Debug|Win32
   12.23 +		Release|ARM = Release|ARM
   12.24 +		Release|Win32 = Release|Win32
   12.25 +	EndGlobalSection
   12.26 +	GlobalSection(ProjectConfigurationPlatforms) = postSolution
   12.27 +		{1444BB95-670B-4878-851B-7ED8DA0629A3}.Debug|ARM.ActiveCfg = Debug|ARM
   12.28 +		{1444BB95-670B-4878-851B-7ED8DA0629A3}.Debug|ARM.Build.0 = Debug|ARM
   12.29 +		{1444BB95-670B-4878-851B-7ED8DA0629A3}.Debug|Win32.ActiveCfg = Debug|Win32
   12.30 +		{1444BB95-670B-4878-851B-7ED8DA0629A3}.Debug|Win32.Build.0 = Debug|Win32
   12.31 +		{1444BB95-670B-4878-851B-7ED8DA0629A3}.Release|ARM.ActiveCfg = Release|ARM
   12.32 +		{1444BB95-670B-4878-851B-7ED8DA0629A3}.Release|ARM.Build.0 = Release|ARM
   12.33 +		{1444BB95-670B-4878-851B-7ED8DA0629A3}.Release|Win32.ActiveCfg = Release|Win32
   12.34 +		{1444BB95-670B-4878-851B-7ED8DA0629A3}.Release|Win32.Build.0 = Release|Win32
   12.35 +		{4F241F1F-6636-47A9-AEB2-5B5157961B51}.Debug|ARM.ActiveCfg = Debug|ARM
   12.36 +		{4F241F1F-6636-47A9-AEB2-5B5157961B51}.Debug|ARM.Build.0 = Debug|ARM
   12.37 +		{4F241F1F-6636-47A9-AEB2-5B5157961B51}.Debug|Win32.ActiveCfg = Debug|Win32
   12.38 +		{4F241F1F-6636-47A9-AEB2-5B5157961B51}.Debug|Win32.Build.0 = Debug|Win32
   12.39 +		{4F241F1F-6636-47A9-AEB2-5B5157961B51}.Release|ARM.ActiveCfg = Release|ARM
   12.40 +		{4F241F1F-6636-47A9-AEB2-5B5157961B51}.Release|ARM.Build.0 = Release|ARM
   12.41 +		{4F241F1F-6636-47A9-AEB2-5B5157961B51}.Release|Win32.ActiveCfg = Release|Win32
   12.42 +		{4F241F1F-6636-47A9-AEB2-5B5157961B51}.Release|Win32.Build.0 = Release|Win32
   12.43 +		{C396C32A-1A8D-4711-A3DB-206F188FC738}.Debug|ARM.ActiveCfg = Debug|ARM
   12.44 +		{C396C32A-1A8D-4711-A3DB-206F188FC738}.Debug|ARM.Build.0 = Debug|ARM
   12.45 +		{C396C32A-1A8D-4711-A3DB-206F188FC738}.Debug|Win32.ActiveCfg = Debug|Win32
   12.46 +		{C396C32A-1A8D-4711-A3DB-206F188FC738}.Debug|Win32.Build.0 = Debug|Win32
   12.47 +		{C396C32A-1A8D-4711-A3DB-206F188FC738}.Release|ARM.ActiveCfg = Release|ARM
   12.48 +		{C396C32A-1A8D-4711-A3DB-206F188FC738}.Release|ARM.Build.0 = Release|ARM
   12.49 +		{C396C32A-1A8D-4711-A3DB-206F188FC738}.Release|Win32.ActiveCfg = Release|Win32
   12.50 +		{C396C32A-1A8D-4711-A3DB-206F188FC738}.Release|Win32.Build.0 = Release|Win32
   12.51 +		{9DC4D90A-0D6D-4150-9049-1F4358B59E06}.Debug|ARM.ActiveCfg = Debug|ARM
   12.52 +		{9DC4D90A-0D6D-4150-9049-1F4358B59E06}.Debug|ARM.Build.0 = Debug|ARM
   12.53 +		{9DC4D90A-0D6D-4150-9049-1F4358B59E06}.Debug|Win32.ActiveCfg = Debug|Win32
   12.54 +		{9DC4D90A-0D6D-4150-9049-1F4358B59E06}.Debug|Win32.Build.0 = Debug|Win32
   12.55 +		{9DC4D90A-0D6D-4150-9049-1F4358B59E06}.Release|ARM.ActiveCfg = Release|ARM
   12.56 +		{9DC4D90A-0D6D-4150-9049-1F4358B59E06}.Release|ARM.Build.0 = Release|ARM
   12.57 +		{9DC4D90A-0D6D-4150-9049-1F4358B59E06}.Release|Win32.ActiveCfg = Release|Win32
   12.58 +		{9DC4D90A-0D6D-4150-9049-1F4358B59E06}.Release|Win32.Build.0 = Release|Win32
   12.59 +		{183B6F21-DD86-49A1-BA70-C97D7C404469}.Debug|ARM.ActiveCfg = Debug|ARM
   12.60 +		{183B6F21-DD86-49A1-BA70-C97D7C404469}.Debug|ARM.Build.0 = Debug|ARM
   12.61 +		{183B6F21-DD86-49A1-BA70-C97D7C404469}.Debug|Win32.ActiveCfg = Debug|Win32
   12.62 +		{183B6F21-DD86-49A1-BA70-C97D7C404469}.Debug|Win32.Build.0 = Debug|Win32
   12.63 +		{183B6F21-DD86-49A1-BA70-C97D7C404469}.Release|ARM.ActiveCfg = Release|ARM
   12.64 +		{183B6F21-DD86-49A1-BA70-C97D7C404469}.Release|ARM.Build.0 = Release|ARM
   12.65 +		{183B6F21-DD86-49A1-BA70-C97D7C404469}.Release|Win32.ActiveCfg = Release|Win32
   12.66 +		{183B6F21-DD86-49A1-BA70-C97D7C404469}.Release|Win32.Build.0 = Release|Win32
   12.67 +	EndGlobalSection
   12.68 +	GlobalSection(SolutionProperties) = preSolution
   12.69 +		HideSolutionNode = FALSE
   12.70 +	EndGlobalSection
   12.71 +EndGlobal
    13.1 --- a/VisualC-WinRT/WinPhone81_VS2013/SDL_image-WinPhone81.vcxproj	Sat Oct 21 22:14:52 2017 -0700
    13.2 +++ b/VisualC-WinRT/WinPhone81_VS2013/SDL_image-WinPhone81.vcxproj	Sun Oct 22 00:36:06 2017 -0700
    13.3 @@ -27,6 +27,7 @@
    13.4      <ClCompile Include="..\..\IMG_pcx.c" />
    13.5      <ClCompile Include="..\..\IMG_png.c" />
    13.6      <ClCompile Include="..\..\IMG_pnm.c" />
    13.7 +    <ClCompile Include="..\..\IMG_svg.c" />
    13.8      <ClCompile Include="..\..\IMG_tga.c" />
    13.9      <ClCompile Include="..\..\IMG_tif.c" />
   13.10      <ClCompile Include="..\..\IMG_webp.c" />
   13.11 @@ -177,4 +178,4 @@
   13.12    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   13.13    <ImportGroup Label="ExtensionTargets">
   13.14    </ImportGroup>
   13.15 -</Project>
   13.16 +</Project>
   13.17 \ No newline at end of file
    14.1 --- a/VisualC-WinRT/WinPhone81_VS2013/SDL_image-WinPhone81.vcxproj.filters	Sat Oct 21 22:14:52 2017 -0700
    14.2 +++ b/VisualC-WinRT/WinPhone81_VS2013/SDL_image-WinPhone81.vcxproj.filters	Sun Oct 22 00:36:06 2017 -0700
    14.3 @@ -16,5 +16,6 @@
    14.4      <ClCompile Include="..\..\IMG_xpm.c" />
    14.5      <ClCompile Include="..\..\IMG_xv.c" />
    14.6      <ClCompile Include="..\..\IMG_xxx.c" />
    14.7 +    <ClCompile Include="..\..\IMG_svg.c" />
    14.8    </ItemGroup>
    14.9  </Project>
   14.10 \ No newline at end of file
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/VisualC-WinRT/WinRT80_VS2012/SDL_image-WinRT80.sln	Sun Oct 22 00:36:06 2017 -0700
    15.3 @@ -0,0 +1,88 @@
    15.4 +
    15.5 +Microsoft Visual Studio Solution File, Format Version 12.00
    15.6 +# Visual Studio 2012
    15.7 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL2_image-WinRT80", "SDL_image-WinRT80.vcxproj", "{9DC0B681-4702-4968-9C30-16112DAE4E9E}"
    15.8 +EndProject
    15.9 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jpeg-WinRT80", "jpeg-WinRT80.vcxproj", "{CC6CF4C7-BD07-4738-854C-A6C5BAE62EA9}"
   15.10 +EndProject
   15.11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib-WinRT80", "zlib-WinRT80.vcxproj", "{09AB7E08-81AA-460F-B50A-68FC839EF575}"
   15.12 +EndProject
   15.13 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng-WinRT80", "libpng-WinRT80.vcxproj", "{B43D3823-D0C0-4017-9153-C4CBC9A4F9D0}"
   15.14 +EndProject
   15.15 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwebp-WinRT80", "libwebp-WinRT80.vcxproj", "{22DDF547-8E6C-494D-B2FA-59DDEC9E48E2}"
   15.16 +EndProject
   15.17 +Global
   15.18 +	GlobalSection(SolutionConfigurationPlatforms) = preSolution
   15.19 +		Debug|ARM = Debug|ARM
   15.20 +		Debug|Win32 = Debug|Win32
   15.21 +		Debug|x64 = Debug|x64
   15.22 +		Release|ARM = Release|ARM
   15.23 +		Release|Win32 = Release|Win32
   15.24 +		Release|x64 = Release|x64
   15.25 +	EndGlobalSection
   15.26 +	GlobalSection(ProjectConfigurationPlatforms) = postSolution
   15.27 +		{9DC0B681-4702-4968-9C30-16112DAE4E9E}.Debug|ARM.ActiveCfg = Debug|ARM
   15.28 +		{9DC0B681-4702-4968-9C30-16112DAE4E9E}.Debug|ARM.Build.0 = Debug|ARM
   15.29 +		{9DC0B681-4702-4968-9C30-16112DAE4E9E}.Debug|Win32.ActiveCfg = Debug|Win32
   15.30 +		{9DC0B681-4702-4968-9C30-16112DAE4E9E}.Debug|Win32.Build.0 = Debug|Win32
   15.31 +		{9DC0B681-4702-4968-9C30-16112DAE4E9E}.Debug|x64.ActiveCfg = Debug|x64
   15.32 +		{9DC0B681-4702-4968-9C30-16112DAE4E9E}.Debug|x64.Build.0 = Debug|x64
   15.33 +		{9DC0B681-4702-4968-9C30-16112DAE4E9E}.Release|ARM.ActiveCfg = Release|ARM
   15.34 +		{9DC0B681-4702-4968-9C30-16112DAE4E9E}.Release|ARM.Build.0 = Release|ARM
   15.35 +		{9DC0B681-4702-4968-9C30-16112DAE4E9E}.Release|Win32.ActiveCfg = Release|Win32
   15.36 +		{9DC0B681-4702-4968-9C30-16112DAE4E9E}.Release|Win32.Build.0 = Release|Win32
   15.37 +		{9DC0B681-4702-4968-9C30-16112DAE4E9E}.Release|x64.ActiveCfg = Release|x64
   15.38 +		{9DC0B681-4702-4968-9C30-16112DAE4E9E}.Release|x64.Build.0 = Release|x64
   15.39 +		{CC6CF4C7-BD07-4738-854C-A6C5BAE62EA9}.Debug|ARM.ActiveCfg = Debug|ARM
   15.40 +		{CC6CF4C7-BD07-4738-854C-A6C5BAE62EA9}.Debug|ARM.Build.0 = Debug|ARM
   15.41 +		{CC6CF4C7-BD07-4738-854C-A6C5BAE62EA9}.Debug|Win32.ActiveCfg = Debug|Win32
   15.42 +		{CC6CF4C7-BD07-4738-854C-A6C5BAE62EA9}.Debug|Win32.Build.0 = Debug|Win32
   15.43 +		{CC6CF4C7-BD07-4738-854C-A6C5BAE62EA9}.Debug|x64.ActiveCfg = Debug|x64
   15.44 +		{CC6CF4C7-BD07-4738-854C-A6C5BAE62EA9}.Debug|x64.Build.0 = Debug|x64
   15.45 +		{CC6CF4C7-BD07-4738-854C-A6C5BAE62EA9}.Release|ARM.ActiveCfg = Release|ARM
   15.46 +		{CC6CF4C7-BD07-4738-854C-A6C5BAE62EA9}.Release|ARM.Build.0 = Release|ARM
   15.47 +		{CC6CF4C7-BD07-4738-854C-A6C5BAE62EA9}.Release|Win32.ActiveCfg = Release|Win32
   15.48 +		{CC6CF4C7-BD07-4738-854C-A6C5BAE62EA9}.Release|Win32.Build.0 = Release|Win32
   15.49 +		{CC6CF4C7-BD07-4738-854C-A6C5BAE62EA9}.Release|x64.ActiveCfg = Release|x64
   15.50 +		{CC6CF4C7-BD07-4738-854C-A6C5BAE62EA9}.Release|x64.Build.0 = Release|x64
   15.51 +		{09AB7E08-81AA-460F-B50A-68FC839EF575}.Debug|ARM.ActiveCfg = Debug|ARM
   15.52 +		{09AB7E08-81AA-460F-B50A-68FC839EF575}.Debug|ARM.Build.0 = Debug|ARM
   15.53 +		{09AB7E08-81AA-460F-B50A-68FC839EF575}.Debug|Win32.ActiveCfg = Debug|Win32
   15.54 +		{09AB7E08-81AA-460F-B50A-68FC839EF575}.Debug|Win32.Build.0 = Debug|Win32
   15.55 +		{09AB7E08-81AA-460F-B50A-68FC839EF575}.Debug|x64.ActiveCfg = Debug|x64
   15.56 +		{09AB7E08-81AA-460F-B50A-68FC839EF575}.Debug|x64.Build.0 = Debug|x64
   15.57 +		{09AB7E08-81AA-460F-B50A-68FC839EF575}.Release|ARM.ActiveCfg = Release|ARM
   15.58 +		{09AB7E08-81AA-460F-B50A-68FC839EF575}.Release|ARM.Build.0 = Release|ARM
   15.59 +		{09AB7E08-81AA-460F-B50A-68FC839EF575}.Release|Win32.ActiveCfg = Release|Win32
   15.60 +		{09AB7E08-81AA-460F-B50A-68FC839EF575}.Release|Win32.Build.0 = Release|Win32
   15.61 +		{09AB7E08-81AA-460F-B50A-68FC839EF575}.Release|x64.ActiveCfg = Release|x64
   15.62 +		{09AB7E08-81AA-460F-B50A-68FC839EF575}.Release|x64.Build.0 = Release|x64
   15.63 +		{B43D3823-D0C0-4017-9153-C4CBC9A4F9D0}.Debug|ARM.ActiveCfg = Debug|ARM
   15.64 +		{B43D3823-D0C0-4017-9153-C4CBC9A4F9D0}.Debug|ARM.Build.0 = Debug|ARM
   15.65 +		{B43D3823-D0C0-4017-9153-C4CBC9A4F9D0}.Debug|Win32.ActiveCfg = Debug|Win32
   15.66 +		{B43D3823-D0C0-4017-9153-C4CBC9A4F9D0}.Debug|Win32.Build.0 = Debug|Win32
   15.67 +		{B43D3823-D0C0-4017-9153-C4CBC9A4F9D0}.Debug|x64.ActiveCfg = Debug|x64
   15.68 +		{B43D3823-D0C0-4017-9153-C4CBC9A4F9D0}.Debug|x64.Build.0 = Debug|x64
   15.69 +		{B43D3823-D0C0-4017-9153-C4CBC9A4F9D0}.Release|ARM.ActiveCfg = Release|ARM
   15.70 +		{B43D3823-D0C0-4017-9153-C4CBC9A4F9D0}.Release|ARM.Build.0 = Release|ARM
   15.71 +		{B43D3823-D0C0-4017-9153-C4CBC9A4F9D0}.Release|Win32.ActiveCfg = Release|Win32
   15.72 +		{B43D3823-D0C0-4017-9153-C4CBC9A4F9D0}.Release|Win32.Build.0 = Release|Win32
   15.73 +		{B43D3823-D0C0-4017-9153-C4CBC9A4F9D0}.Release|x64.ActiveCfg = Release|x64
   15.74 +		{B43D3823-D0C0-4017-9153-C4CBC9A4F9D0}.Release|x64.Build.0 = Release|x64
   15.75 +		{22DDF547-8E6C-494D-B2FA-59DDEC9E48E2}.Debug|ARM.ActiveCfg = Debug|ARM
   15.76 +		{22DDF547-8E6C-494D-B2FA-59DDEC9E48E2}.Debug|ARM.Build.0 = Debug|ARM
   15.77 +		{22DDF547-8E6C-494D-B2FA-59DDEC9E48E2}.Debug|Win32.ActiveCfg = Debug|Win32
   15.78 +		{22DDF547-8E6C-494D-B2FA-59DDEC9E48E2}.Debug|Win32.Build.0 = Debug|Win32
   15.79 +		{22DDF547-8E6C-494D-B2FA-59DDEC9E48E2}.Debug|x64.ActiveCfg = Debug|x64
   15.80 +		{22DDF547-8E6C-494D-B2FA-59DDEC9E48E2}.Debug|x64.Build.0 = Debug|x64
   15.81 +		{22DDF547-8E6C-494D-B2FA-59DDEC9E48E2}.Release|ARM.ActiveCfg = Release|ARM
   15.82 +		{22DDF547-8E6C-494D-B2FA-59DDEC9E48E2}.Release|ARM.Build.0 = Release|ARM
   15.83 +		{22DDF547-8E6C-494D-B2FA-59DDEC9E48E2}.Release|Win32.ActiveCfg = Release|Win32
   15.84 +		{22DDF547-8E6C-494D-B2FA-59DDEC9E48E2}.Release|Win32.Build.0 = Release|Win32
   15.85 +		{22DDF547-8E6C-494D-B2FA-59DDEC9E48E2}.Release|x64.ActiveCfg = Release|x64
   15.86 +		{22DDF547-8E6C-494D-B2FA-59DDEC9E48E2}.Release|x64.Build.0 = Release|x64
   15.87 +	EndGlobalSection
   15.88 +	GlobalSection(SolutionProperties) = preSolution
   15.89 +		HideSolutionNode = FALSE
   15.90 +	EndGlobalSection
   15.91 +EndGlobal
    16.1 --- a/VisualC-WinRT/WinRT80_VS2012/SDL_image-WinRT80.vcxproj	Sat Oct 21 22:14:52 2017 -0700
    16.2 +++ b/VisualC-WinRT/WinRT80_VS2012/SDL_image-WinRT80.vcxproj	Sun Oct 22 00:36:06 2017 -0700
    16.3 @@ -35,6 +35,7 @@
    16.4      <ClCompile Include="..\..\IMG_pcx.c" />
    16.5      <ClCompile Include="..\..\IMG_png.c" />
    16.6      <ClCompile Include="..\..\IMG_pnm.c" />
    16.7 +    <ClCompile Include="..\..\IMG_svg.c" />
    16.8      <ClCompile Include="..\..\IMG_tga.c" />
    16.9      <ClCompile Include="..\..\IMG_tif.c" />
   16.10      <ClCompile Include="..\..\IMG_webp.c" />
   16.11 @@ -242,4 +243,4 @@
   16.12    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   16.13    <ImportGroup Label="ExtensionTargets">
   16.14    </ImportGroup>
   16.15 -</Project>
   16.16 +</Project>
   16.17 \ No newline at end of file
    17.1 --- a/VisualC-WinRT/WinRT80_VS2012/SDL_image-WinRT80.vcxproj.filters	Sat Oct 21 22:14:52 2017 -0700
    17.2 +++ b/VisualC-WinRT/WinRT80_VS2012/SDL_image-WinRT80.vcxproj.filters	Sun Oct 22 00:36:06 2017 -0700
    17.3 @@ -16,6 +16,7 @@
    17.4      <ClCompile Include="..\..\IMG_xpm.c" />
    17.5      <ClCompile Include="..\..\IMG_xv.c" />
    17.6      <ClCompile Include="..\..\IMG_xxx.c" />
    17.7 +    <ClCompile Include="..\..\IMG_svg.c" />
    17.8    </ItemGroup>
    17.9    <ItemGroup>
   17.10      <ClInclude Include="..\miniz.h" />
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/VisualC-WinRT/WinRT81_VS2013/SDL_image-WinRT81.sln	Sun Oct 22 00:36:06 2017 -0700
    18.3 @@ -0,0 +1,90 @@
    18.4 +
    18.5 +Microsoft Visual Studio Solution File, Format Version 12.00
    18.6 +# Visual Studio 2013
    18.7 +VisualStudioVersion = 12.0.40629.0
    18.8 +MinimumVisualStudioVersion = 10.0.40219.1
    18.9 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SDL2_image-WinRT81", "SDL_image-WinRT81.vcxproj", "{29B4D11F-59F3-4EBC-A769-3BABD140DB9A}"
   18.10 +EndProject
   18.11 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jpeg-WinRT81", "jpeg-WinRT81.vcxproj", "{2E908AD5-95E9-4B2D-BD6E-BA3EA4C1A2EE}"
   18.12 +EndProject
   18.13 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng-WinRT81", "libpng-WinRT81.vcxproj", "{5FBDC49A-7939-40F9-B78E-975F190ADBD3}"
   18.14 +EndProject
   18.15 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libwebp-WinRT81", "libwebp-WinRT81.vcxproj", "{1EB035A3-815A-4382-90D3-4510AB605AD9}"
   18.16 +EndProject
   18.17 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib-WinRT81", "zlib-WinRT81.vcxproj", "{ACEA4101-6F4A-44ED-9EC1-289821DAC711}"
   18.18 +EndProject
   18.19 +Global
   18.20 +	GlobalSection(SolutionConfigurationPlatforms) = preSolution
   18.21 +		Debug|ARM = Debug|ARM
   18.22 +		Debug|Win32 = Debug|Win32
   18.23 +		Debug|x64 = Debug|x64
   18.24 +		Release|ARM = Release|ARM
   18.25 +		Release|Win32 = Release|Win32
   18.26 +		Release|x64 = Release|x64
   18.27 +	EndGlobalSection
   18.28 +	GlobalSection(ProjectConfigurationPlatforms) = postSolution
   18.29 +		{29B4D11F-59F3-4EBC-A769-3BABD140DB9A}.Debug|ARM.ActiveCfg = Debug|ARM
   18.30 +		{29B4D11F-59F3-4EBC-A769-3BABD140DB9A}.Debug|ARM.Build.0 = Debug|ARM
   18.31 +		{29B4D11F-59F3-4EBC-A769-3BABD140DB9A}.Debug|Win32.ActiveCfg = Debug|Win32
   18.32 +		{29B4D11F-59F3-4EBC-A769-3BABD140DB9A}.Debug|Win32.Build.0 = Debug|Win32
   18.33 +		{29B4D11F-59F3-4EBC-A769-3BABD140DB9A}.Debug|x64.ActiveCfg = Debug|x64
   18.34 +		{29B4D11F-59F3-4EBC-A769-3BABD140DB9A}.Debug|x64.Build.0 = Debug|x64
   18.35 +		{29B4D11F-59F3-4EBC-A769-3BABD140DB9A}.Release|ARM.ActiveCfg = Release|ARM
   18.36 +		{29B4D11F-59F3-4EBC-A769-3BABD140DB9A}.Release|ARM.Build.0 = Release|ARM
   18.37 +		{29B4D11F-59F3-4EBC-A769-3BABD140DB9A}.Release|Win32.ActiveCfg = Release|Win32
   18.38 +		{29B4D11F-59F3-4EBC-A769-3BABD140DB9A}.Release|Win32.Build.0 = Release|Win32
   18.39 +		{29B4D11F-59F3-4EBC-A769-3BABD140DB9A}.Release|x64.ActiveCfg = Release|x64
   18.40 +		{29B4D11F-59F3-4EBC-A769-3BABD140DB9A}.Release|x64.Build.0 = Release|x64
   18.41 +		{2E908AD5-95E9-4B2D-BD6E-BA3EA4C1A2EE}.Debug|ARM.ActiveCfg = Debug|ARM
   18.42 +		{2E908AD5-95E9-4B2D-BD6E-BA3EA4C1A2EE}.Debug|ARM.Build.0 = Debug|ARM
   18.43 +		{2E908AD5-95E9-4B2D-BD6E-BA3EA4C1A2EE}.Debug|Win32.ActiveCfg = Debug|Win32
   18.44 +		{2E908AD5-95E9-4B2D-BD6E-BA3EA4C1A2EE}.Debug|Win32.Build.0 = Debug|Win32
   18.45 +		{2E908AD5-95E9-4B2D-BD6E-BA3EA4C1A2EE}.Debug|x64.ActiveCfg = Debug|x64
   18.46 +		{2E908AD5-95E9-4B2D-BD6E-BA3EA4C1A2EE}.Debug|x64.Build.0 = Debug|x64
   18.47 +		{2E908AD5-95E9-4B2D-BD6E-BA3EA4C1A2EE}.Release|ARM.ActiveCfg = Release|ARM
   18.48 +		{2E908AD5-95E9-4B2D-BD6E-BA3EA4C1A2EE}.Release|ARM.Build.0 = Release|ARM
   18.49 +		{2E908AD5-95E9-4B2D-BD6E-BA3EA4C1A2EE}.Release|Win32.ActiveCfg = Release|Win32
   18.50 +		{2E908AD5-95E9-4B2D-BD6E-BA3EA4C1A2EE}.Release|Win32.Build.0 = Release|Win32
   18.51 +		{2E908AD5-95E9-4B2D-BD6E-BA3EA4C1A2EE}.Release|x64.ActiveCfg = Release|x64
   18.52 +		{2E908AD5-95E9-4B2D-BD6E-BA3EA4C1A2EE}.Release|x64.Build.0 = Release|x64
   18.53 +		{5FBDC49A-7939-40F9-B78E-975F190ADBD3}.Debug|ARM.ActiveCfg = Debug|ARM
   18.54 +		{5FBDC49A-7939-40F9-B78E-975F190ADBD3}.Debug|ARM.Build.0 = Debug|ARM
   18.55 +		{5FBDC49A-7939-40F9-B78E-975F190ADBD3}.Debug|Win32.ActiveCfg = Debug|Win32
   18.56 +		{5FBDC49A-7939-40F9-B78E-975F190ADBD3}.Debug|Win32.Build.0 = Debug|Win32
   18.57 +		{5FBDC49A-7939-40F9-B78E-975F190ADBD3}.Debug|x64.ActiveCfg = Debug|x64
   18.58 +		{5FBDC49A-7939-40F9-B78E-975F190ADBD3}.Debug|x64.Build.0 = Debug|x64
   18.59 +		{5FBDC49A-7939-40F9-B78E-975F190ADBD3}.Release|ARM.ActiveCfg = Release|ARM
   18.60 +		{5FBDC49A-7939-40F9-B78E-975F190ADBD3}.Release|ARM.Build.0 = Release|ARM
   18.61 +		{5FBDC49A-7939-40F9-B78E-975F190ADBD3}.Release|Win32.ActiveCfg = Release|Win32
   18.62 +		{5FBDC49A-7939-40F9-B78E-975F190ADBD3}.Release|Win32.Build.0 = Release|Win32
   18.63 +		{5FBDC49A-7939-40F9-B78E-975F190ADBD3}.Release|x64.ActiveCfg = Release|x64
   18.64 +		{5FBDC49A-7939-40F9-B78E-975F190ADBD3}.Release|x64.Build.0 = Release|x64
   18.65 +		{1EB035A3-815A-4382-90D3-4510AB605AD9}.Debug|ARM.ActiveCfg = Debug|ARM
   18.66 +		{1EB035A3-815A-4382-90D3-4510AB605AD9}.Debug|ARM.Build.0 = Debug|ARM
   18.67 +		{1EB035A3-815A-4382-90D3-4510AB605AD9}.Debug|Win32.ActiveCfg = Debug|Win32
   18.68 +		{1EB035A3-815A-4382-90D3-4510AB605AD9}.Debug|Win32.Build.0 = Debug|Win32
   18.69 +		{1EB035A3-815A-4382-90D3-4510AB605AD9}.Debug|x64.ActiveCfg = Debug|x64
   18.70 +		{1EB035A3-815A-4382-90D3-4510AB605AD9}.Debug|x64.Build.0 = Debug|x64
   18.71 +		{1EB035A3-815A-4382-90D3-4510AB605AD9}.Release|ARM.ActiveCfg = Release|ARM
   18.72 +		{1EB035A3-815A-4382-90D3-4510AB605AD9}.Release|ARM.Build.0 = Release|ARM
   18.73 +		{1EB035A3-815A-4382-90D3-4510AB605AD9}.Release|Win32.ActiveCfg = Release|Win32
   18.74 +		{1EB035A3-815A-4382-90D3-4510AB605AD9}.Release|Win32.Build.0 = Release|Win32
   18.75 +		{1EB035A3-815A-4382-90D3-4510AB605AD9}.Release|x64.ActiveCfg = Release|x64
   18.76 +		{1EB035A3-815A-4382-90D3-4510AB605AD9}.Release|x64.Build.0 = Release|x64
   18.77 +		{ACEA4101-6F4A-44ED-9EC1-289821DAC711}.Debug|ARM.ActiveCfg = Debug|ARM
   18.78 +		{ACEA4101-6F4A-44ED-9EC1-289821DAC711}.Debug|ARM.Build.0 = Debug|ARM
   18.79 +		{ACEA4101-6F4A-44ED-9EC1-289821DAC711}.Debug|Win32.ActiveCfg = Debug|Win32
   18.80 +		{ACEA4101-6F4A-44ED-9EC1-289821DAC711}.Debug|Win32.Build.0 = Debug|Win32
   18.81 +		{ACEA4101-6F4A-44ED-9EC1-289821DAC711}.Debug|x64.ActiveCfg = Debug|x64
   18.82 +		{ACEA4101-6F4A-44ED-9EC1-289821DAC711}.Debug|x64.Build.0 = Debug|x64
   18.83 +		{ACEA4101-6F4A-44ED-9EC1-289821DAC711}.Release|ARM.ActiveCfg = Release|ARM
   18.84 +		{ACEA4101-6F4A-44ED-9EC1-289821DAC711}.Release|ARM.Build.0 = Release|ARM
   18.85 +		{ACEA4101-6F4A-44ED-9EC1-289821DAC711}.Release|Win32.ActiveCfg = Release|Win32
   18.86 +		{ACEA4101-6F4A-44ED-9EC1-289821DAC711}.Release|Win32.Build.0 = Release|Win32
   18.87 +		{ACEA4101-6F4A-44ED-9EC1-289821DAC711}.Release|x64.ActiveCfg = Release|x64
   18.88 +		{ACEA4101-6F4A-44ED-9EC1-289821DAC711}.Release|x64.Build.0 = Release|x64
   18.89 +	EndGlobalSection
   18.90 +	GlobalSection(SolutionProperties) = preSolution
   18.91 +		HideSolutionNode = FALSE
   18.92 +	EndGlobalSection
   18.93 +EndGlobal
    19.1 --- a/VisualC-WinRT/WinRT81_VS2013/SDL_image-WinRT81.vcxproj	Sat Oct 21 22:14:52 2017 -0700
    19.2 +++ b/VisualC-WinRT/WinRT81_VS2013/SDL_image-WinRT81.vcxproj	Sun Oct 22 00:36:06 2017 -0700
    19.3 @@ -35,6 +35,7 @@
    19.4      <ClCompile Include="..\..\IMG_pcx.c" />
    19.5      <ClCompile Include="..\..\IMG_png.c" />
    19.6      <ClCompile Include="..\..\IMG_pnm.c" />
    19.7 +    <ClCompile Include="..\..\IMG_svg.c" />
    19.8      <ClCompile Include="..\..\IMG_tga.c" />
    19.9      <ClCompile Include="..\..\IMG_tif.c" />
   19.10      <ClCompile Include="..\..\IMG_webp.c" />
   19.11 @@ -240,4 +241,4 @@
   19.12    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   19.13    <ImportGroup Label="ExtensionTargets">
   19.14    </ImportGroup>
   19.15 -</Project>
   19.16 +</Project>
   19.17 \ No newline at end of file
    20.1 --- a/VisualC-WinRT/WinRT81_VS2013/SDL_image-WinRT81.vcxproj.filters	Sat Oct 21 22:14:52 2017 -0700
    20.2 +++ b/VisualC-WinRT/WinRT81_VS2013/SDL_image-WinRT81.vcxproj.filters	Sun Oct 22 00:36:06 2017 -0700
    20.3 @@ -16,5 +16,6 @@
    20.4      <ClCompile Include="..\..\IMG_xpm.c" />
    20.5      <ClCompile Include="..\..\IMG_xv.c" />
    20.6      <ClCompile Include="..\..\IMG_xxx.c" />
    20.7 +    <ClCompile Include="..\..\IMG_svg.c" />
    20.8    </ItemGroup>
    20.9  </Project>
   20.10 \ No newline at end of file
    21.1 --- a/VisualC/SDL_image.vcxproj	Sat Oct 21 22:14:52 2017 -0700
    21.2 +++ b/VisualC/SDL_image.vcxproj	Sun Oct 22 00:36:06 2017 -0700
    21.3 @@ -92,7 +92,7 @@
    21.4      <ClCompile>
    21.5        <Optimization>Disabled</Optimization>
    21.6        <AdditionalIncludeDirectories>external\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
    21.7 -      <PreprocessorDefinitions>_DEBUG;WIN32;_WINDOWS;LOAD_BMP;LOAD_GIF;LOAD_JPG;LOAD_JPG_DYNAMIC="libjpeg-9.dll";LOAD_LBM;LOAD_PCX;LOAD_PNG;LOAD_PNG_DYNAMIC="libpng16-16.dll";LOAD_PNM;LOAD_TGA;LOAD_TIF;LOAD_TIF_DYNAMIC="libtiff-5.dll";LOAD_WEBP;LOAD_WEBP_DYNAMIC="libwebp-7.dll";LOAD_XPM;LOAD_XV;PNG_USE_DLL;ZLIB_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    21.8 +      <PreprocessorDefinitions>_DEBUG;WIN32;_WINDOWS;LOAD_BMP;LOAD_GIF;LOAD_JPG;LOAD_JPG_DYNAMIC="libjpeg-9.dll";LOAD_LBM;LOAD_PCX;LOAD_PNG;LOAD_PNG_DYNAMIC="libpng16-16.dll";LOAD_PNM;LOAD_SVG;LOAD_SVG;LOAD_TGA;LOAD_TIF;LOAD_TIF_DYNAMIC="libtiff-5.dll";LOAD_WEBP;LOAD_WEBP_DYNAMIC="libwebp-7.dll";LOAD_XPM;LOAD_XV;PNG_USE_DLL;ZLIB_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    21.9        <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
   21.10        <WarningLevel>Level3</WarningLevel>
   21.11        <DebugInformationFormat>OldStyle</DebugInformationFormat>
   21.12 @@ -120,7 +120,7 @@
   21.13      </Midl>
   21.14      <ClCompile>
   21.15        <AdditionalIncludeDirectories>external\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
   21.16 -      <PreprocessorDefinitions>_DEBUG;WIN32;_WINDOWS;LOAD_BMP;LOAD_GIF;LOAD_JPG;LOAD_JPG_DYNAMIC="libjpeg-9.dll";LOAD_LBM;LOAD_PCX;LOAD_PNG;LOAD_PNG_DYNAMIC="libpng16-16.dll";LOAD_PNM;LOAD_TGA;LOAD_TIF;LOAD_TIF_DYNAMIC="libtiff-5.dll";LOAD_WEBP;LOAD_WEBP_DYNAMIC="libwebp-7.dll";LOAD_XPM;LOAD_XV;PNG_USE_DLL;ZLIB_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   21.17 +      <PreprocessorDefinitions>_DEBUG;WIN32;_WINDOWS;LOAD_BMP;LOAD_GIF;LOAD_JPG;LOAD_JPG_DYNAMIC="libjpeg-9.dll";LOAD_LBM;LOAD_PCX;LOAD_PNG;LOAD_PNG_DYNAMIC="libpng16-16.dll";LOAD_PNM;LOAD_SVG;LOAD_TGA;LOAD_TIF;LOAD_TIF_DYNAMIC="libtiff-5.dll";LOAD_WEBP;LOAD_WEBP_DYNAMIC="libwebp-7.dll";LOAD_XPM;LOAD_XV;PNG_USE_DLL;ZLIB_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   21.18        <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
   21.19        <WarningLevel>Level3</WarningLevel>
   21.20        <Optimization>Disabled</Optimization>
   21.21 @@ -149,7 +149,7 @@
   21.22      </Midl>
   21.23      <ClCompile>
   21.24        <AdditionalIncludeDirectories>external\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
   21.25 -      <PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;LOAD_BMP;LOAD_GIF;LOAD_JPG;LOAD_JPG_DYNAMIC="libjpeg-9.dll";LOAD_LBM;LOAD_PCX;LOAD_PNG;LOAD_PNG_DYNAMIC="libpng16-16.dll";LOAD_PNM;LOAD_TGA;LOAD_TIF;LOAD_TIF_DYNAMIC="libtiff-5.dll";LOAD_WEBP;LOAD_WEBP_DYNAMIC="libwebp-7.dll";LOAD_XPM;LOAD_XV;PNG_USE_DLL;ZLIB_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   21.26 +      <PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;LOAD_BMP;LOAD_GIF;LOAD_JPG;LOAD_JPG_DYNAMIC="libjpeg-9.dll";LOAD_LBM;LOAD_PCX;LOAD_PNG;LOAD_PNG_DYNAMIC="libpng16-16.dll";LOAD_PNM;LOAD_SVG;LOAD_TGA;LOAD_TIF;LOAD_TIF_DYNAMIC="libtiff-5.dll";LOAD_WEBP;LOAD_WEBP_DYNAMIC="libwebp-7.dll";LOAD_XPM;LOAD_XV;PNG_USE_DLL;ZLIB_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   21.27        <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
   21.28        <WarningLevel>Level3</WarningLevel>
   21.29        <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
   21.30 @@ -175,7 +175,7 @@
   21.31      </Midl>
   21.32      <ClCompile>
   21.33        <AdditionalIncludeDirectories>external\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
   21.34 -      <PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;LOAD_BMP;LOAD_GIF;LOAD_JPG;LOAD_JPG_DYNAMIC="libjpeg-9.dll";LOAD_LBM;LOAD_PCX;LOAD_PNG;LOAD_PNG_DYNAMIC="libpng16-16.dll";LOAD_PNM;LOAD_TGA;LOAD_TIF;LOAD_TIF_DYNAMIC="libtiff-5.dll";LOAD_WEBP;LOAD_WEBP_DYNAMIC="libwebp-7.dll";LOAD_XPM;LOAD_XV;PNG_USE_DLL;ZLIB_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   21.35 +      <PreprocessorDefinitions>NDEBUG;WIN32;_WINDOWS;LOAD_BMP;LOAD_GIF;LOAD_JPG;LOAD_JPG_DYNAMIC="libjpeg-9.dll";LOAD_LBM;LOAD_PCX;LOAD_PNG;LOAD_PNG_DYNAMIC="libpng16-16.dll";LOAD_PNM;LOAD_SVG;LOAD_TGA;LOAD_TIF;LOAD_TIF_DYNAMIC="libtiff-5.dll";LOAD_WEBP;LOAD_WEBP_DYNAMIC="libwebp-7.dll";LOAD_XPM;LOAD_XV;PNG_USE_DLL;ZLIB_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
   21.36        <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
   21.37        <WarningLevel>Level3</WarningLevel>
   21.38        <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>
   21.39 @@ -270,6 +270,7 @@
   21.40        <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
   21.41        <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
   21.42      </ClCompile>
   21.43 +    <ClCompile Include="..\IMG_svg.c" />
   21.44      <ClCompile Include="..\IMG_tga.c">
   21.45        <AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
   21.46        <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
   21.47 @@ -519,4 +520,4 @@
   21.48    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   21.49    <ImportGroup Label="ExtensionTargets">
   21.50    </ImportGroup>
   21.51 -</Project>
   21.52 +</Project>
   21.53 \ No newline at end of file
    22.1 --- a/VisualC/SDL_image.vcxproj.filters	Sat Oct 21 22:14:52 2017 -0700
    22.2 +++ b/VisualC/SDL_image.vcxproj.filters	Sun Oct 22 00:36:06 2017 -0700
    22.3 @@ -46,6 +46,10 @@
    22.4      <ClCompile Include="..\IMG_xxx.c">
    22.5        <Filter>Sources</Filter>
    22.6      </ClCompile>
    22.7 +    <ClCompile Include="..\IMG_WIC.c" />
    22.8 +    <ClCompile Include="..\IMG_svg.c">
    22.9 +      <Filter>Sources</Filter>
   22.10 +    </ClCompile>
   22.11    </ItemGroup>
   22.12    <ItemGroup>
   22.13      <Filter Include="Sources">
   22.14 @@ -133,4 +137,4 @@
   22.15        <Filter>x86</Filter>
   22.16      </CustomBuild>
   22.17    </ItemGroup>
   22.18 -</Project>
   22.19 +</Project>
   22.20 \ No newline at end of file
    23.1 --- a/Xcode-iOS/SDL_image.xcodeproj/project.pbxproj	Sat Oct 21 22:14:52 2017 -0700
    23.2 +++ b/Xcode-iOS/SDL_image.xcodeproj/project.pbxproj	Sun Oct 22 00:36:06 2017 -0700
    23.3 @@ -24,6 +24,7 @@
    23.4  		AA126AA81617A4A4005ABC8F /* IMG_xv.c in Sources */ = {isa = PBXBuildFile; fileRef = AA126A971617A4A4005ABC8F /* IMG_xv.c */; };
    23.5  		AA126AA91617A4A4005ABC8F /* IMG_xxx.c in Sources */ = {isa = PBXBuildFile; fileRef = AA126A981617A4A4005ABC8F /* IMG_xxx.c */; };
    23.6  		AA126AAA1617A4A4005ABC8F /* IMG.c in Sources */ = {isa = PBXBuildFile; fileRef = AA126A991617A4A4005ABC8F /* IMG.c */; };
    23.7 +		AA50AA491F9C7DB6003B9C0C /* IMG_svg.c in Sources */ = {isa = PBXBuildFile; fileRef = AA50AA481F9C7DB6003B9C0C /* IMG_svg.c */; };
    23.8  /* End PBXBuildFile section */
    23.9  
   23.10  /* Begin PBXFileReference section */
   23.11 @@ -44,6 +45,7 @@
   23.12  		AA126A971617A4A4005ABC8F /* IMG_xv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = IMG_xv.c; path = ../IMG_xv.c; sourceTree = "<group>"; };
   23.13  		AA126A981617A4A4005ABC8F /* IMG_xxx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = IMG_xxx.c; path = ../IMG_xxx.c; sourceTree = "<group>"; };
   23.14  		AA126A991617A4A4005ABC8F /* IMG.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = IMG.c; path = ../IMG.c; sourceTree = "<group>"; };
   23.15 +		AA50AA481F9C7DB6003B9C0C /* IMG_svg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = IMG_svg.c; path = ../IMG_svg.c; sourceTree = "<group>"; };
   23.16  		BE1FA74107AF4C45004B6283 /* libSDL2_image.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDL2_image.a; sourceTree = BUILT_PRODUCTS_DIR; };
   23.17  /* End PBXFileReference section */
   23.18  
   23.19 @@ -104,6 +106,7 @@
   23.20  				AA126A8E1617A4A4005ABC8F /* IMG_pcx.c */,
   23.21  				AA126A8F1617A4A4005ABC8F /* IMG_png.c */,
   23.22  				AA126A901617A4A4005ABC8F /* IMG_pnm.c */,
   23.23 +				AA50AA481F9C7DB6003B9C0C /* IMG_svg.c */,
   23.24  				AA126A911617A4A4005ABC8F /* IMG_tga.c */,
   23.25  				AA126A921617A4A4005ABC8F /* IMG_tif.c */,
   23.26  				AA126A941617A4A4005ABC8F /* IMG_webp.c */,
   23.27 @@ -207,6 +210,7 @@
   23.28  				AA126AA81617A4A4005ABC8F /* IMG_xv.c in Sources */,
   23.29  				AA126AA91617A4A4005ABC8F /* IMG_xxx.c in Sources */,
   23.30  				AA126AAA1617A4A4005ABC8F /* IMG.c in Sources */,
   23.31 +				AA50AA491F9C7DB6003B9C0C /* IMG_svg.c in Sources */,
   23.32  			);
   23.33  			runOnlyForDeploymentPostprocessing = 0;
   23.34  		};
   23.35 @@ -226,6 +230,7 @@
   23.36  					LOAD_PCX,
   23.37  					LOAD_PNG,
   23.38  					LOAD_PNM,
   23.39 +					LOAD_SVG,
   23.40  					LOAD_TGA,
   23.41  					LOAD_TIF,
   23.42  					LOAD_XPM,
   23.43 @@ -266,6 +271,7 @@
   23.44  					LOAD_PCX,
   23.45  					LOAD_PNG,
   23.46  					LOAD_PNM,
   23.47 +					LOAD_SVG,
   23.48  					LOAD_TGA,
   23.49  					LOAD_TIF,
   23.50  					LOAD_XPM,
    24.1 --- a/Xcode/SDL_image.xcodeproj/project.pbxproj	Sat Oct 21 22:14:52 2017 -0700
    24.2 +++ b/Xcode/SDL_image.xcodeproj/project.pbxproj	Sun Oct 22 00:36:06 2017 -0700
    24.3 @@ -8,6 +8,7 @@
    24.4  
    24.5  /* Begin PBXBuildFile section */
    24.6  		007288A80F0DA79800C302A9 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007288A60F0DA79800C302A9 /* ApplicationServices.framework */; };
    24.7 +		AA50AA471F9C7C50003B9C0C /* IMG_svg.c in Sources */ = {isa = PBXBuildFile; fileRef = AA50AA461F9C7C50003B9C0C /* IMG_svg.c */; };
    24.8  		AA579DF2161C07E6005F809B /* IMG_bmp.c in Sources */ = {isa = PBXBuildFile; fileRef = AA579DE2161C07E6005F809B /* IMG_bmp.c */; };
    24.9  		AA579DF3161C07E7005F809B /* IMG_bmp.c in Sources */ = {isa = PBXBuildFile; fileRef = AA579DE2161C07E6005F809B /* IMG_bmp.c */; };
   24.10  		AA579DF4161C07E7005F809B /* IMG_gif.c in Sources */ = {isa = PBXBuildFile; fileRef = AA579DE3161C07E6005F809B /* IMG_gif.c */; };
   24.11 @@ -75,6 +76,7 @@
   24.12  		007288A60F0DA79800C302A9 /* ApplicationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ApplicationServices.framework; path = /System/Library/Frameworks/ApplicationServices.framework; sourceTree = "<absolute>"; };
   24.13  		1014BAEA010A4B677F000001 /* SDL_image.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = SDL_image.h; path = ../SDL_image.h; sourceTree = SOURCE_ROOT; };
   24.14  		61F85449145A19BC002CA294 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
   24.15 +		AA50AA461F9C7C50003B9C0C /* IMG_svg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = IMG_svg.c; path = ../IMG_svg.c; sourceTree = "<group>"; };
   24.16  		AA579DE2161C07E6005F809B /* IMG_bmp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = IMG_bmp.c; path = ../IMG_bmp.c; sourceTree = "<group>"; };
   24.17  		AA579DE3161C07E6005F809B /* IMG_gif.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = IMG_gif.c; path = ../IMG_gif.c; sourceTree = "<group>"; };
   24.18  		AA579DE4161C07E6005F809B /* IMG_ImageIO.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = IMG_ImageIO.m; path = ../IMG_ImageIO.m; sourceTree = "<group>"; };
   24.19 @@ -166,14 +168,16 @@
   24.20  		08FB77ACFE841707C02AAC07 /* Library Source */ = {
   24.21  			isa = PBXGroup;
   24.22  			children = (
   24.23 +				AA579DF1161C07E6005F809B /* IMG.c */,
   24.24 +				AA579DE4161C07E6005F809B /* IMG_ImageIO.m */,
   24.25  				AA579DE2161C07E6005F809B /* IMG_bmp.c */,
   24.26  				AA579DE3161C07E6005F809B /* IMG_gif.c */,
   24.27 -				AA579DE4161C07E6005F809B /* IMG_ImageIO.m */,
   24.28  				AA579DE5161C07E6005F809B /* IMG_jpg.c */,
   24.29  				AA579DE6161C07E6005F809B /* IMG_lbm.c */,
   24.30  				AA579DE7161C07E6005F809B /* IMG_pcx.c */,
   24.31  				AA579DE8161C07E6005F809B /* IMG_png.c */,
   24.32  				AA579DE9161C07E6005F809B /* IMG_pnm.c */,
   24.33 +				AA50AA461F9C7C50003B9C0C /* IMG_svg.c */,
   24.34  				AA579DEA161C07E6005F809B /* IMG_tga.c */,
   24.35  				AA579DEB161C07E6005F809B /* IMG_tif.c */,
   24.36  				AA579DEC161C07E6005F809B /* IMG_webp.c */,
   24.37 @@ -181,7 +185,6 @@
   24.38  				AA579DEE161C07E6005F809B /* IMG_xpm.c */,
   24.39  				AA579DEF161C07E6005F809B /* IMG_xv.c */,
   24.40  				AA579DF0161C07E6005F809B /* IMG_xxx.c */,
   24.41 -				AA579DF1161C07E6005F809B /* IMG.c */,
   24.42  			);
   24.43  			name = "Library Source";
   24.44  			sourceTree = "<group>";
   24.45 @@ -422,6 +425,7 @@
   24.46  				AA579E0C161C07E7005F809B /* IMG_xv.c in Sources */,
   24.47  				AA579E0E161C07E7005F809B /* IMG_xxx.c in Sources */,
   24.48  				AA579E10161C07E7005F809B /* IMG.c in Sources */,
   24.49 +				AA50AA471F9C7C50003B9C0C /* IMG_svg.c in Sources */,
   24.50  			);
   24.51  			runOnlyForDeploymentPostprocessing = 0;
   24.52  		};
   24.53 @@ -477,6 +481,7 @@
   24.54  					LOAD_PCX,
   24.55  					LOAD_PNG,
   24.56  					LOAD_PNM,
   24.57 +					LOAD_SVG,
   24.58  					LOAD_TGA,
   24.59  					LOAD_TIF,
   24.60  					LOAD_WEBP,
   24.61 @@ -512,6 +517,7 @@
   24.62  				INFOPLIST_FILE = "Info-Framework.plist";
   24.63  				INSTALL_PATH = "@rpath";
   24.64  				LD_RUNPATH_SEARCH_PATHS = "@loader_path/Frameworks";
   24.65 +				MACOSX_DEPLOYMENT_TARGET = 10.6;
   24.66  				OTHER_LDFLAGS = (
   24.67  					"-weak_framework",
   24.68  					webp,
   24.69 @@ -538,6 +544,7 @@
   24.70  					LOAD_PCX,
   24.71  					LOAD_PNG,
   24.72  					LOAD_PNM,
   24.73 +					LOAD_SVG,
   24.74  					LOAD_TGA,
   24.75  					LOAD_TIF,
   24.76  					LOAD_WEBP,
   24.77 @@ -598,6 +605,7 @@
   24.78  					LOAD_PCX,
   24.79  					LOAD_PNG,
   24.80  					LOAD_PNM,
   24.81 +					LOAD_SVG,
   24.82  					LOAD_TGA,
   24.83  					LOAD_TIF,
   24.84  					LOAD_WEBP,
   24.85 @@ -634,6 +642,7 @@
   24.86  				INFOPLIST_FILE = "Info-Framework.plist";
   24.87  				INSTALL_PATH = "@rpath";
   24.88  				LD_RUNPATH_SEARCH_PATHS = "@loader_path/Frameworks";
   24.89 +				MACOSX_DEPLOYMENT_TARGET = 10.6;
   24.90  				OTHER_LDFLAGS = (
   24.91  					"-weak_framework",
   24.92  					webp,
   24.93 @@ -658,6 +667,7 @@
   24.94  					LOAD_PCX,
   24.95  					LOAD_PNG,
   24.96  					LOAD_PNM,
   24.97 +					LOAD_SVG,
   24.98  					LOAD_TGA,
   24.99  					LOAD_TIF,
  24.100  					LOAD_WEBP,
    25.1 --- a/aclocal.m4	Sat Oct 21 22:14:52 2017 -0700
    25.2 +++ b/aclocal.m4	Sun Oct 22 00:36:06 2017 -0700
    25.3 @@ -1,6 +1,6 @@
    25.4 -# generated automatically by aclocal 1.13.1 -*- Autoconf -*-
    25.5 +# generated automatically by aclocal 1.14 -*- Autoconf -*-
    25.6  
    25.7 -# Copyright (C) 1996-2012 Free Software Foundation, Inc.
    25.8 +# Copyright (C) 1996-2013 Free Software Foundation, Inc.
    25.9  
   25.10  # This file is free software; the Free Software Foundation
   25.11  # gives unlimited permission to copy and/or distribute it,
   25.12 @@ -22,7 +22,8 @@
   25.13  
   25.14  # lt~obsolete.m4 -- aclocal satisfying obsolete definitions.    -*-Autoconf-*-
   25.15  #
   25.16 -#   Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
   25.17 +#   Copyright (C) 2004-2005, 2007, 2009, 2011-2015 Free Software
   25.18 +#   Foundation, Inc.
   25.19  #   Written by Scott James Remnant, 2004.
   25.20  #
   25.21  # This file is free software; the Free Software Foundation gives
   25.22 @@ -33,7 +34,7 @@
   25.23  
   25.24  # These exist entirely to fool aclocal when bootstrapping libtool.
   25.25  #
   25.26 -# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN)
   25.27 +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN),
   25.28  # which have later been changed to m4_define as they aren't part of the
   25.29  # exported API, or moved to Autoconf or Automake where they belong.
   25.30  #
   25.31 @@ -47,7 +48,7 @@
   25.32  # included after everything else.  This provides aclocal with the
   25.33  # AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything
   25.34  # because those macros already exist, or will be overwritten later.
   25.35 -# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. 
   25.36 +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6.
   25.37  #
   25.38  # Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here.
   25.39  # Yes, that means every name once taken will need to remain here until
   25.40 @@ -131,10 +132,10 @@
   25.41  # generated from the m4 files accompanying Automake X.Y.
   25.42  # (This private macro should not be called outside this file.)
   25.43  AC_DEFUN([AM_AUTOMAKE_VERSION],
   25.44 -[am__api_version='1.13'
   25.45 +[am__api_version='1.14'
   25.46  dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
   25.47  dnl require some minimum version.  Point them to the right macro.
   25.48 -m4_if([$1], [1.13.1], [],
   25.49 +m4_if([$1], [1.14], [],
   25.50        [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
   25.51  ])
   25.52  
   25.53 @@ -150,7 +151,7 @@
   25.54  # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
   25.55  # This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
   25.56  AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
   25.57 -[AM_AUTOMAKE_VERSION([1.13.1])dnl
   25.58 +[AM_AUTOMAKE_VERSION([1.14])dnl
   25.59  m4_ifndef([AC_AUTOCONF_VERSION],
   25.60    [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
   25.61  _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
   25.62 @@ -472,7 +473,7 @@
   25.63      DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
   25.64      test -z "$DEPDIR" && continue
   25.65      am__include=`sed -n 's/^am__include = //p' < "$mf"`
   25.66 -    test -z "am__include" && continue
   25.67 +    test -z "$am__include" && continue
   25.68      am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
   25.69      # Find all dependency output files, they are included files with
   25.70      # $(DEPDIR) in their names.  We invoke sed twice because it is the
   25.71 @@ -517,6 +518,12 @@
   25.72  # This macro actually does too much.  Some checks are only needed if
   25.73  # your package does certain things.  But this isn't really a big deal.
   25.74  
   25.75 +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O.
   25.76 +m4_define([AC_PROG_CC],
   25.77 +m4_defn([AC_PROG_CC])
   25.78 +[_AM_PROG_CC_C_O
   25.79 +])
   25.80 +
   25.81  # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
   25.82  # AM_INIT_AUTOMAKE([OPTIONS])
   25.83  # -----------------------------------------------
   25.84 @@ -625,7 +632,48 @@
   25.85  AC_CONFIG_COMMANDS_PRE(dnl
   25.86  [m4_provide_if([_AM_COMPILER_EXEEXT],
   25.87    [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
   25.88 -])
   25.89 +
   25.90 +# POSIX will say in a future version that running "rm -f" with no argument
   25.91 +# is OK; and we want to be able to make that assumption in our Makefile
   25.92 +# recipes.  So use an aggressive probe to check that the usage we want is
   25.93 +# actually supported "in the wild" to an acceptable degree.
   25.94 +# See automake bug#10828.
   25.95 +# To make any issue more visible, cause the running configure to be aborted
   25.96 +# by default if the 'rm' program in use doesn't match our expectations; the
   25.97 +# user can still override this though.
   25.98 +if rm -f && rm -fr && rm -rf; then : OK; else
   25.99 +  cat >&2 <<'END'
  25.100 +Oops!
  25.101 +
  25.102 +Your 'rm' program seems unable to run without file operands specified
  25.103 +on the command line, even when the '-f' option is present.  This is contrary
  25.104 +to the behaviour of most rm programs out there, and not conforming with
  25.105 +the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
  25.106 +
  25.107 +Please tell bug-automake@gnu.org about your system, including the value
  25.108 +of your $PATH and any error possibly output before this message.  This
  25.109 +can help us improve future automake versions.
  25.110 +
  25.111 +END
  25.112 +  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
  25.113 +    echo 'Configuration will proceed anyway, since you have set the' >&2
  25.114 +    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
  25.115 +    echo >&2
  25.116 +  else
  25.117 +    cat >&2 <<'END'
  25.118 +Aborting the configuration process, to ensure you take notice of the issue.
  25.119 +
  25.120 +You can download and install GNU coreutils to get an 'rm' implementation
  25.121 +that behaves properly: <http://www.gnu.org/software/coreutils/>.
  25.122 +
  25.123 +If you want to complete the configuration process using your problematic
  25.124 +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
  25.125 +to "yes", and re-run configure.
  25.126 +
  25.127 +END
  25.128 +    AC_MSG_ERROR([Your 'rm' program is bad, sorry.])
  25.129 +  fi
  25.130 +fi])
  25.131  
  25.132  dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion.  Do not
  25.133  dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
  25.134 @@ -633,7 +681,6 @@
  25.135  m4_define([_AC_COMPILER_EXEEXT],
  25.136  m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
  25.137  
  25.138 -
  25.139  # When config.status generates a header, we must update the stamp-h file.
  25.140  # This file resides in the same directory as the config header
  25.141  # that is generated.  The stamp files are numbered to have different names.
  25.142 @@ -815,6 +862,70 @@
  25.143  AC_DEFUN([_AM_IF_OPTION],
  25.144  [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
  25.145  
  25.146 +# Copyright (C) 1999-2013 Free Software Foundation, Inc.
  25.147 +#
  25.148 +# This file is free software; the Free Software Foundation
  25.149 +# gives unlimited permission to copy and/or distribute it,
  25.150 +# with or without modifications, as long as this notice is preserved.
  25.151 +
  25.152 +# _AM_PROG_CC_C_O
  25.153 +# ---------------
  25.154 +# Like AC_PROG_CC_C_O, but changed for automake.  We rewrite AC_PROG_CC
  25.155 +# to automatically call this.
  25.156 +AC_DEFUN([_AM_PROG_CC_C_O],
  25.157 +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
  25.158 +AC_REQUIRE_AUX_FILE([compile])dnl
  25.159 +AC_LANG_PUSH([C])dnl
  25.160 +AC_CACHE_CHECK(
  25.161 +  [whether $CC understands -c and -o together],
  25.162 +  [am_cv_prog_cc_c_o],
  25.163 +  [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])])
  25.164 +  # Make sure it works both with $CC and with simple cc.
  25.165 +  # Following AC_PROG_CC_C_O, we do the test twice because some
  25.166 +  # compilers refuse to overwrite an existing .o file with -o,
  25.167 +  # though they will create one.
  25.168 +  am_cv_prog_cc_c_o=yes
  25.169 +  for am_i in 1 2; do
  25.170 +    if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \
  25.171 +         && test -f conftest2.$ac_objext; then
  25.172 +      : OK
  25.173 +    else
  25.174 +      am_cv_prog_cc_c_o=no
  25.175 +      break
  25.176 +    fi
  25.177 +  done
  25.178 +  rm -f core conftest*
  25.179 +  unset am_i])
  25.180 +if test "$am_cv_prog_cc_c_o" != yes; then
  25.181 +   # Losing compiler, so override with the script.
  25.182 +   # FIXME: It is wrong to rewrite CC.
  25.183 +   # But if we don't then we get into trouble of one sort or another.
  25.184 +   # A longer-term fix would be to have automake use am__CC in this case,
  25.185 +   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
  25.186 +   CC="$am_aux_dir/compile $CC"
  25.187 +fi
  25.188 +AC_LANG_POP([C])])
  25.189 +
  25.190 +# For backward compatibility.
  25.191 +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
  25.192 +
  25.193 +# Copyright (C) 2001-2013 Free Software Foundation, Inc.
  25.194 +#
  25.195 +# This file is free software; the Free Software Foundation
  25.196 +# gives unlimited permission to copy and/or distribute it,
  25.197 +# with or without modifications, as long as this notice is preserved.
  25.198 +
  25.199 +# AM_RUN_LOG(COMMAND)
  25.200 +# -------------------
  25.201 +# Run COMMAND, save the exit status in ac_status, and log it.
  25.202 +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.)
  25.203 +AC_DEFUN([AM_RUN_LOG],
  25.204 +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD
  25.205 +   ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD
  25.206 +   ac_status=$?
  25.207 +   echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD
  25.208 +   (exit $ac_status); }])
  25.209 +
  25.210  # Check to make sure that the build environment is sane.    -*- Autoconf -*-
  25.211  
  25.212  # Copyright (C) 1996-2013 Free Software Foundation, Inc.
  25.213 @@ -1024,76 +1135,114 @@
  25.214  # Substitute a variable $(am__untar) that extract such
  25.215  # a tarball read from stdin.
  25.216  #     $(am__untar) < result.tar
  25.217 +#
  25.218  AC_DEFUN([_AM_PROG_TAR],
  25.219  [# Always define AMTAR for backward compatibility.  Yes, it's still used
  25.220  # in the wild :-(  We should find a proper way to deprecate it ...
  25.221  AC_SUBST([AMTAR], ['$${TAR-tar}'])
  25.222 +
  25.223 +# We'll loop over all known methods to create a tar archive until one works.
  25.224 +_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
  25.225 +
  25.226  m4_if([$1], [v7],
  25.227 -     [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
  25.228 -     [m4_case([$1], [ustar],, [pax],,
  25.229 -              [m4_fatal([Unknown tar format])])
  25.230 -AC_MSG_CHECKING([how to create a $1 tar archive])
  25.231 -# Loop over all known methods to create a tar archive until one works.
  25.232 -_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
  25.233 -_am_tools=${am_cv_prog_tar_$1-$_am_tools}
  25.234 -# Do not fold the above two line into one, because Tru64 sh and
  25.235 -# Solaris sh will not grok spaces in the rhs of '-'.
  25.236 -for _am_tool in $_am_tools
  25.237 -do
  25.238 -  case $_am_tool in
  25.239 -  gnutar)
  25.240 -    for _am_tar in tar gnutar gtar;
  25.241 -    do
  25.242 -      AM_RUN_LOG([$_am_tar --version]) && break
  25.243 -    done
  25.244 -    am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
  25.245 -    am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
  25.246 -    am__untar="$_am_tar -xf -"
  25.247 -    ;;
  25.248 -  plaintar)
  25.249 -    # Must skip GNU tar: if it does not support --format= it doesn't create
  25.250 -    # ustar tarball either.
  25.251 -    (tar --version) >/dev/null 2>&1 && continue
  25.252 -    am__tar='tar chf - "$$tardir"'
  25.253 -    am__tar_='tar chf - "$tardir"'
  25.254 -    am__untar='tar xf -'
  25.255 -    ;;
  25.256 -  pax)
  25.257 -    am__tar='pax -L -x $1 -w "$$tardir"'
  25.258 -    am__tar_='pax -L -x $1 -w "$tardir"'
  25.259 -    am__untar='pax -r'
  25.260 -    ;;
  25.261 -  cpio)
  25.262 -    am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
  25.263 -    am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
  25.264 -    am__untar='cpio -i -H $1 -d'
  25.265 -    ;;
  25.266 -  none)
  25.267 -    am__tar=false
  25.268 -    am__tar_=false
  25.269 -    am__untar=false
  25.270 -    ;;
  25.271 -  esac
  25.272 +  [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'],
  25.273  
  25.274 -  # If the value was cached, stop now.  We just wanted to have am__tar
  25.275 -  # and am__untar set.
  25.276 -  test -n "${am_cv_prog_tar_$1}" && break
  25.277 +  [m4_case([$1],
  25.278 +    [ustar],
  25.279 +     [# The POSIX 1988 'ustar' format is defined with fixed-size fields.
  25.280 +      # There is notably a 21 bits limit for the UID and the GID.  In fact,
  25.281 +      # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343
  25.282 +      # and bug#13588).
  25.283 +      am_max_uid=2097151 # 2^21 - 1
  25.284 +      am_max_gid=$am_max_uid
  25.285 +      # The $UID and $GID variables are not portable, so we need to resort
  25.286 +      # to the POSIX-mandated id(1) utility.  Errors in the 'id' calls
  25.287 +      # below are definitely unexpected, so allow the users to see them
  25.288 +      # (that is, avoid stderr redirection).
  25.289 +      am_uid=`id -u || echo unknown`
  25.290 +      am_gid=`id -g || echo unknown`
  25.291 +      AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format])
  25.292 +      if test $am_uid -le $am_max_uid; then
  25.293 +         AC_MSG_RESULT([yes])
  25.294 +      else
  25.295 +         AC_MSG_RESULT([no])
  25.296 +         _am_tools=none
  25.297 +      fi
  25.298 +      AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format])
  25.299 +      if test $am_gid -le $am_max_gid; then
  25.300 +         AC_MSG_RESULT([yes])
  25.301 +      else
  25.302 +        AC_MSG_RESULT([no])
  25.303 +        _am_tools=none
  25.304 +      fi],
  25.305  
  25.306 -  # tar/untar a dummy directory, and stop if the command works
  25.307 +  [pax],
  25.308 +    [],
  25.309 +
  25.310 +  [m4_fatal([Unknown tar format])])
  25.311 +
  25.312 +  AC_MSG_CHECKING([how to create a $1 tar archive])
  25.313 +
  25.314 +  # Go ahead even if we have the value already cached.  We do so because we
  25.315 +  # need to set the values for the 'am__tar' and 'am__untar' variables.
  25.316 +  _am_tools=${am_cv_prog_tar_$1-$_am_tools}
  25.317 +
  25.318 +  for _am_tool in $_am_tools; do
  25.319 +    case $_am_tool in
  25.320 +    gnutar)
  25.321 +      for _am_tar in tar gnutar gtar; do
  25.322 +        AM_RUN_LOG([$_am_tar --version]) && break
  25.323 +      done
  25.324 +      am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
  25.325 +      am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
  25.326 +      am__untar="$_am_tar -xf -"
  25.327 +      ;;
  25.328 +    plaintar)
  25.329 +      # Must skip GNU tar: if it does not support --format= it doesn't create
  25.330 +      # ustar tarball either.
  25.331 +      (tar --version) >/dev/null 2>&1 && continue
  25.332 +      am__tar='tar chf - "$$tardir"'
  25.333 +      am__tar_='tar chf - "$tardir"'
  25.334 +      am__untar='tar xf -'
  25.335 +      ;;
  25.336 +    pax)
  25.337 +      am__tar='pax -L -x $1 -w "$$tardir"'
  25.338 +      am__tar_='pax -L -x $1 -w "$tardir"'
  25.339 +      am__untar='pax -r'
  25.340 +      ;;
  25.341 +    cpio)
  25.342 +      am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
  25.343 +      am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
  25.344 +      am__untar='cpio -i -H $1 -d'
  25.345 +      ;;
  25.346 +    none)
  25.347 +      am__tar=false
  25.348 +      am__tar_=false
  25.349 +      am__untar=false
  25.350 +      ;;
  25.351 +    esac
  25.352 +
  25.353 +    # If the value was cached, stop now.  We just wanted to have am__tar
  25.354 +    # and am__untar set.
  25.355 +    test -n "${am_cv_prog_tar_$1}" && break
  25.356 +
  25.357 +    # tar/untar a dummy directory, and stop if the command works.
  25.358 +    rm -rf conftest.dir
  25.359 +    mkdir conftest.dir
  25.360 +    echo GrepMe > conftest.dir/file
  25.361 +    AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
  25.362 +    rm -rf conftest.dir
  25.363 +    if test -s conftest.tar; then
  25.364 +      AM_RUN_LOG([$am__untar <conftest.tar])
  25.365 +      AM_RUN_LOG([cat conftest.dir/file])
  25.366 +      grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
  25.367 +    fi
  25.368 +  done
  25.369    rm -rf conftest.dir
  25.370 -  mkdir conftest.dir
  25.371 -  echo GrepMe > conftest.dir/file
  25.372 -  AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
  25.373 -  rm -rf conftest.dir
  25.374 -  if test -s conftest.tar; then
  25.375 -    AM_RUN_LOG([$am__untar <conftest.tar])
  25.376 -    grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
  25.377 -  fi
  25.378 -done
  25.379 -rm -rf conftest.dir
  25.380  
  25.381 -AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
  25.382 -AC_MSG_RESULT([$am_cv_prog_tar_$1])])
  25.383 +  AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
  25.384 +  AC_MSG_RESULT([$am_cv_prog_tar_$1])])
  25.385 +
  25.386  AC_SUBST([am__tar])
  25.387  AC_SUBST([am__untar])
  25.388  ]) # _AM_PROG_TAR
    26.1 --- a/configure	Sat Oct 21 22:14:52 2017 -0700
    26.2 +++ b/configure	Sun Oct 22 00:36:06 2017 -0700
    26.3 @@ -938,6 +938,7 @@
    26.4  enable_png
    26.5  enable_png_shared
    26.6  enable_pnm
    26.7 +enable_svg
    26.8  enable_tga
    26.9  enable_tif
   26.10  enable_tif_shared
   26.11 @@ -1604,6 +1605,7 @@
   26.12    --enable-png            support loading PNG images [default=yes]
   26.13    --enable-png-shared     dynamically load PNG support [[default=yes]]
   26.14    --enable-pnm            support loading PNM images [default=yes]
   26.15 +  --enable-svg            support loading SVG images [default=yes]
   26.16    --enable-tga            support loading TGA images [default=yes]
   26.17    --enable-tif            support loading TIFF images [default=yes]
   26.18    --enable-tif-shared     dynamically load TIFF support [[default=yes]]
   26.19 @@ -2611,6 +2613,9 @@
   26.20  case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
   26.21  
   26.22  
   26.23 +# expand $ac_aux_dir to an absolute path
   26.24 +am_aux_dir=`cd $ac_aux_dir && pwd`
   26.25 +
   26.26  ac_ext=c
   26.27  ac_cpp='$CPP $CPPFLAGS'
   26.28  ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
   26.29 @@ -3400,6 +3405,65 @@
   26.30  ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
   26.31  ac_compiler_gnu=$ac_cv_c_compiler_gnu
   26.32  
   26.33 +ac_ext=c
   26.34 +ac_cpp='$CPP $CPPFLAGS'
   26.35 +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
   26.36 +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
   26.37 +ac_compiler_gnu=$ac_cv_c_compiler_gnu
   26.38 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
   26.39 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
   26.40 +if ${am_cv_prog_cc_c_o+:} false; then :
   26.41 +  $as_echo_n "(cached) " >&6
   26.42 +else
   26.43 +  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
   26.44 +/* end confdefs.h.  */
   26.45 +
   26.46 +int
   26.47 +main ()
   26.48 +{
   26.49 +
   26.50 +  ;
   26.51 +  return 0;
   26.52 +}
   26.53 +_ACEOF
   26.54 +  # Make sure it works both with $CC and with simple cc.
   26.55 +  # Following AC_PROG_CC_C_O, we do the test twice because some
   26.56 +  # compilers refuse to overwrite an existing .o file with -o,
   26.57 +  # though they will create one.
   26.58 +  am_cv_prog_cc_c_o=yes
   26.59 +  for am_i in 1 2; do
   26.60 +    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
   26.61 +   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
   26.62 +   ac_status=$?
   26.63 +   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   26.64 +   (exit $ac_status); } \
   26.65 +         && test -f conftest2.$ac_objext; then
   26.66 +      : OK
   26.67 +    else
   26.68 +      am_cv_prog_cc_c_o=no
   26.69 +      break
   26.70 +    fi
   26.71 +  done
   26.72 +  rm -f core conftest*
   26.73 +  unset am_i
   26.74 +fi
   26.75 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
   26.76 +$as_echo "$am_cv_prog_cc_c_o" >&6; }
   26.77 +if test "$am_cv_prog_cc_c_o" != yes; then
   26.78 +   # Losing compiler, so override with the script.
   26.79 +   # FIXME: It is wrong to rewrite CC.
   26.80 +   # But if we don't then we get into trouble of one sort or another.
   26.81 +   # A longer-term fix would be to have automake use am__CC in this case,
   26.82 +   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
   26.83 +   CC="$am_aux_dir/compile $CC"
   26.84 +fi
   26.85 +ac_ext=c
   26.86 +ac_cpp='$CPP $CPPFLAGS'
   26.87 +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
   26.88 +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
   26.89 +ac_compiler_gnu=$ac_cv_c_compiler_gnu
   26.90 +
   26.91 +
   26.92  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5
   26.93  $as_echo_n "checking for a sed that does not truncate output... " >&6; }
   26.94  if ${ac_cv_path_SED+:} false; then :
   26.95 @@ -3984,13 +4048,13 @@
   26.96  else
   26.97    lt_cv_nm_interface="BSD nm"
   26.98    echo "int some_variable = 0;" > conftest.$ac_ext
   26.99 -  (eval echo "\"\$as_me:3987: $ac_compile\"" >&5)
  26.100 +  (eval echo "\"\$as_me:4051: $ac_compile\"" >&5)
  26.101    (eval "$ac_compile" 2>conftest.err)
  26.102    cat conftest.err >&5
  26.103 -  (eval echo "\"\$as_me:3990: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
  26.104 +  (eval echo "\"\$as_me:4054: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
  26.105    (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
  26.106    cat conftest.err >&5
  26.107 -  (eval echo "\"\$as_me:3993: output\"" >&5)
  26.108 +  (eval echo "\"\$as_me:4057: output\"" >&5)
  26.109    cat conftest.out >&5
  26.110    if $GREP 'External.*some_variable' conftest.out > /dev/null; then
  26.111      lt_cv_nm_interface="MS dumpbin"
  26.112 @@ -5201,7 +5265,7 @@
  26.113    ;;
  26.114  *-*-irix6*)
  26.115    # Find out which ABI we are using.
  26.116 -  echo '#line 5204 "configure"' > conftest.$ac_ext
  26.117 +  echo '#line 5268 "configure"' > conftest.$ac_ext
  26.118    if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
  26.119    (eval $ac_compile) 2>&5
  26.120    ac_status=$?
  26.121 @@ -5273,7 +5337,10 @@
  26.122  	  x86_64-*linux*)
  26.123  	    LD="${LD-ld} -m elf_x86_64"
  26.124  	    ;;
  26.125 -	  ppc*-*linux*|powerpc*-*linux*)
  26.126 +	  powerpc64le-*linux*)
  26.127 +	    LD="${LD-ld} -m elf64lppc"
  26.128 +	    ;;
  26.129 +	  powerpc64-*linux*)
  26.130  	    LD="${LD-ld} -m elf64ppc"
  26.131  	    ;;
  26.132  	  s390*-*linux*|s390*-*tpf*)
  26.133 @@ -7028,11 +7095,11 @@
  26.134     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
  26.135     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
  26.136     -e 's:$: $lt_compiler_flag:'`
  26.137 -   (eval echo "\"\$as_me:7031: $lt_compile\"" >&5)
  26.138 +   (eval echo "\"\$as_me:7098: $lt_compile\"" >&5)
  26.139     (eval "$lt_compile" 2>conftest.err)
  26.140     ac_status=$?
  26.141     cat conftest.err >&5
  26.142 -   echo "$as_me:7035: \$? = $ac_status" >&5
  26.143 +   echo "$as_me:7102: \$? = $ac_status" >&5
  26.144     if (exit $ac_status) && test -s "$ac_outfile"; then
  26.145       # The compiler can only warn and ignore the option if not recognized
  26.146       # So say no if there are warnings other than the usual output.
  26.147 @@ -7367,11 +7434,11 @@
  26.148     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
  26.149     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
  26.150     -e 's:$: $lt_compiler_flag:'`
  26.151 -   (eval echo "\"\$as_me:7370: $lt_compile\"" >&5)
  26.152 +   (eval echo "\"\$as_me:7437: $lt_compile\"" >&5)
  26.153     (eval "$lt_compile" 2>conftest.err)
  26.154     ac_status=$?
  26.155     cat conftest.err >&5
  26.156 -   echo "$as_me:7374: \$? = $ac_status" >&5
  26.157 +   echo "$as_me:7441: \$? = $ac_status" >&5
  26.158     if (exit $ac_status) && test -s "$ac_outfile"; then
  26.159       # The compiler can only warn and ignore the option if not recognized
  26.160       # So say no if there are warnings other than the usual output.
  26.161 @@ -7472,11 +7539,11 @@
  26.162     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
  26.163     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
  26.164     -e 's:$: $lt_compiler_flag:'`
  26.165 -   (eval echo "\"\$as_me:7475: $lt_compile\"" >&5)
  26.166 +   (eval echo "\"\$as_me:7542: $lt_compile\"" >&5)
  26.167     (eval "$lt_compile" 2>out/conftest.err)
  26.168     ac_status=$?
  26.169     cat out/conftest.err >&5
  26.170 -   echo "$as_me:7479: \$? = $ac_status" >&5
  26.171 +   echo "$as_me:7546: \$? = $ac_status" >&5
  26.172     if (exit $ac_status) && test -s out/conftest2.$ac_objext
  26.173     then
  26.174       # The compiler can only warn and ignore the option if not recognized
  26.175 @@ -7527,11 +7594,11 @@
  26.176     -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
  26.177     -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
  26.178     -e 's:$: $lt_compiler_flag:'`
  26.179 -   (eval echo "\"\$as_me:7530: $lt_compile\"" >&5)
  26.180 +   (eval echo "\"\$as_me:7597: $lt_compile\"" >&5)
  26.181     (eval "$lt_compile" 2>out/conftest.err)
  26.182     ac_status=$?
  26.183     cat out/conftest.err >&5
  26.184 -   echo "$as_me:7534: \$? = $ac_status" >&5
  26.185 +   echo "$as_me:7601: \$? = $ac_status" >&5
  26.186     if (exit $ac_status) && test -s out/conftest2.$ac_objext
  26.187     then
  26.188       # The compiler can only warn and ignore the option if not recognized
  26.189 @@ -9896,7 +9963,7 @@
  26.190    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
  26.191    lt_status=$lt_dlunknown
  26.192    cat > conftest.$ac_ext <<_LT_EOF
  26.193 -#line 9899 "configure"
  26.194 +#line 9966 "configure"
  26.195  #include "confdefs.h"
  26.196  
  26.197  #if HAVE_DLFCN_H
  26.198 @@ -9992,7 +10059,7 @@
  26.199    lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
  26.200    lt_status=$lt_dlunknown
  26.201    cat > conftest.$ac_ext <<_LT_EOF
  26.202 -#line 9995 "configure"
  26.203 +#line 10062 "configure"
  26.204  #include "confdefs.h"
  26.205  
  26.206  #if HAVE_DLFCN_H
  26.207 @@ -10232,7 +10299,7 @@
  26.208  
  26.209  
  26.210  
  26.211 -am__api_version='1.13'
  26.212 +am__api_version='1.14'
  26.213  
  26.214  # Find a good install program.  We prefer a C program (faster),
  26.215  # so one script is as good as another.  But avoid the broken or
  26.216 @@ -10404,9 +10471,6 @@
  26.217  ac_script='s/[\\$]/&&/g;s/;s,x,x,$//'
  26.218  program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
  26.219  
  26.220 -# expand $ac_aux_dir to an absolute path
  26.221 -am_aux_dir=`cd $ac_aux_dir && pwd`
  26.222 -
  26.223  if test x"${MISSING+set}" != xset; then
  26.224    case $am_aux_dir in
  26.225    *\ * | *\	*)
  26.226 @@ -10822,11 +10886,16 @@
  26.227  # in the wild :-(  We should find a proper way to deprecate it ...
  26.228  AMTAR='$${TAR-tar}'
  26.229  
  26.230 +
  26.231 +# We'll loop over all known methods to create a tar archive until one works.
  26.232 +_am_tools='gnutar  pax cpio none'
  26.233 +
  26.234  am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'
  26.235  
  26.236  
  26.237  
  26.238  
  26.239 +
  26.240  depcc="$CC"   am_compiler_list=
  26.241  
  26.242  { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5
  26.243 @@ -10956,6 +11025,47 @@
  26.244  
  26.245  
  26.246  
  26.247 +# POSIX will say in a future version that running "rm -f" with no argument
  26.248 +# is OK; and we want to be able to make that assumption in our Makefile
  26.249 +# recipes.  So use an aggressive probe to check that the usage we want is
  26.250 +# actually supported "in the wild" to an acceptable degree.
  26.251 +# See automake bug#10828.
  26.252 +# To make any issue more visible, cause the running configure to be aborted
  26.253 +# by default if the 'rm' program in use doesn't match our expectations; the
  26.254 +# user can still override this though.
  26.255 +if rm -f && rm -fr && rm -rf; then : OK; else
  26.256 +  cat >&2 <<'END'
  26.257 +Oops!
  26.258 +
  26.259 +Your 'rm' program seems unable to run without file operands specified
  26.260 +on the command line, even when the '-f' option is present.  This is contrary
  26.261 +to the behaviour of most rm programs out there, and not conforming with
  26.262 +the upcoming POSIX standard: <http://austingroupbugs.net/view.php?id=542>
  26.263 +
  26.264 +Please tell bug-automake@gnu.org about your system, including the value
  26.265 +of your $PATH and any error possibly output before this message.  This
  26.266 +can help us improve future automake versions.
  26.267 +
  26.268 +END
  26.269 +  if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then
  26.270 +    echo 'Configuration will proceed anyway, since you have set the' >&2
  26.271 +    echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2
  26.272 +    echo >&2
  26.273 +  else
  26.274 +    cat >&2 <<'END'
  26.275 +Aborting the configuration process, to ensure you take notice of the issue.
  26.276 +
  26.277 +You can download and install GNU coreutils to get an 'rm' implementation
  26.278 +that behaves properly: <http://www.gnu.org/software/coreutils/>.
  26.279 +
  26.280 +If you want to complete the configuration process using your problematic
  26.281 +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM
  26.282 +to "yes", and re-run configure.
  26.283 +
  26.284 +END
  26.285 +    as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5
  26.286 +  fi
  26.287 +fi
  26.288  
  26.289  
  26.290  ac_ext=c
  26.291 @@ -11497,6 +11607,65 @@
  26.292  ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
  26.293  ac_compiler_gnu=$ac_cv_c_compiler_gnu
  26.294  
  26.295 +ac_ext=c
  26.296 +ac_cpp='$CPP $CPPFLAGS'
  26.297 +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
  26.298 +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
  26.299 +ac_compiler_gnu=$ac_cv_c_compiler_gnu
  26.300 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5
  26.301 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; }
  26.302 +if ${am_cv_prog_cc_c_o+:} false; then :
  26.303 +  $as_echo_n "(cached) " >&6
  26.304 +else
  26.305 +  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
  26.306 +/* end confdefs.h.  */
  26.307 +
  26.308 +int
  26.309 +main ()
  26.310 +{
  26.311 +
  26.312 +  ;
  26.313 +  return 0;
  26.314 +}
  26.315 +_ACEOF
  26.316 +  # Make sure it works both with $CC and with simple cc.
  26.317 +  # Following AC_PROG_CC_C_O, we do the test twice because some
  26.318 +  # compilers refuse to overwrite an existing .o file with -o,
  26.319 +  # though they will create one.
  26.320 +  am_cv_prog_cc_c_o=yes
  26.321 +  for am_i in 1 2; do
  26.322 +    if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5
  26.323 +   ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5
  26.324 +   ac_status=$?
  26.325 +   echo "$as_me:$LINENO: \$? = $ac_status" >&5
  26.326 +   (exit $ac_status); } \
  26.327 +         && test -f conftest2.$ac_objext; then
  26.328 +      : OK
  26.329 +    else
  26.330 +      am_cv_prog_cc_c_o=no
  26.331 +      break
  26.332 +    fi
  26.333 +  done
  26.334 +  rm -f core conftest*
  26.335 +  unset am_i
  26.336 +fi
  26.337 +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5
  26.338 +$as_echo "$am_cv_prog_cc_c_o" >&6; }
  26.339 +if test "$am_cv_prog_cc_c_o" != yes; then
  26.340 +   # Losing compiler, so override with the script.
  26.341 +   # FIXME: It is wrong to rewrite CC.
  26.342 +   # But if we don't then we get into trouble of one sort or another.
  26.343 +   # A longer-term fix would be to have automake use am__CC in this case,
  26.344 +   # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
  26.345 +   CC="$am_aux_dir/compile $CC"
  26.346 +fi
  26.347 +ac_ext=c
  26.348 +ac_cpp='$CPP $CPPFLAGS'
  26.349 +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
  26.350 +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
  26.351 +ac_compiler_gnu=$ac_cv_c_compiler_gnu
  26.352 +
  26.353 +
  26.354  ac_ext=m
  26.355  ac_cpp='$OBJCPP $CPPFLAGS'
  26.356  ac_compile='$OBJC -c $OBJCFLAGS $CPPFLAGS conftest.$ac_ext >&5'
  26.357 @@ -12593,6 +12762,13 @@
  26.358    enable_pnm=yes
  26.359  fi
  26.360  
  26.361 +# Check whether --enable-svg was given.
  26.362 +if test "${enable_svg+set}" = set; then :
  26.363 +  enableval=$enable_svg;
  26.364 +else
  26.365 +  enable_svg=yes
  26.366 +fi
  26.367 +
  26.368  # Check whether --enable-tga was given.
  26.369  if test "${enable_tga+set}" = set; then :
  26.370    enableval=$enable_tga;
  26.371 @@ -13237,6 +13413,11 @@
  26.372  
  26.373  fi
  26.374  
  26.375 +if test x$enable_svg = xyes; then
  26.376 +    $as_echo "#define LOAD_SVG 1" >>confdefs.h
  26.377 +
  26.378 +fi
  26.379 +
  26.380  if test x$enable_tga = xyes; then
  26.381      $as_echo "#define LOAD_TGA 1" >>confdefs.h
  26.382  
  26.383 @@ -15455,7 +15636,7 @@
  26.384      DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"`
  26.385      test -z "$DEPDIR" && continue
  26.386      am__include=`sed -n 's/^am__include = //p' < "$mf"`
  26.387 -    test -z "am__include" && continue
  26.388 +    test -z "$am__include" && continue
  26.389      am__quote=`sed -n 's/^am__quote = //p' < "$mf"`
  26.390      # Find all dependency output files, they are included files with
  26.391      # $(DEPDIR) in their names.  We invoke sed twice because it is the
    27.1 --- a/configure.in	Sat Oct 21 22:14:52 2017 -0700
    27.2 +++ b/configure.in	Sun Oct 22 00:36:06 2017 -0700
    27.3 @@ -142,6 +142,8 @@
    27.4   [], [enable_png_shared=yes])
    27.5  AC_ARG_ENABLE([pnm], [AC_HELP_STRING([--enable-pnm], [support loading PNM images [default=yes]])],
    27.6   [], [enable_pnm=yes])
    27.7 +AC_ARG_ENABLE([svg], [AC_HELP_STRING([--enable-svg], [support loading SVG images [default=yes]])],
    27.8 + [], [enable_svg=yes])
    27.9  AC_ARG_ENABLE([tga], [AC_HELP_STRING([--enable-tga], [support loading TGA images [default=yes]])],
   27.10   [], [enable_tga=yes])
   27.11  AC_ARG_ENABLE([tif], [AC_HELP_STRING([--enable-tif], [support loading TIFF images [default=yes]])],
   27.12 @@ -312,6 +314,10 @@
   27.13      AC_DEFINE([LOAD_PNM])
   27.14  fi
   27.15  
   27.16 +if test x$enable_svg = xyes; then
   27.17 +    AC_DEFINE([LOAD_SVG])
   27.18 +fi
   27.19 +
   27.20  if test x$enable_tga = xyes; then
   27.21      AC_DEFINE([LOAD_TGA])
   27.22  fi
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/nanosvg.h	Sun Oct 22 00:36:06 2017 -0700
    28.3 @@ -0,0 +1,2925 @@
    28.4 +/*
    28.5 + * Copyright (c) 2013-14 Mikko Mononen memon@inside.org
    28.6 + *
    28.7 + * This software is provided 'as-is', without any express or implied
    28.8 + * warranty.  In no event will the authors be held liable for any damages
    28.9 + * arising from the use of this software.
   28.10 + *
   28.11 + * Permission is granted to anyone to use this software for any purpose,
   28.12 + * including commercial applications, and to alter it and redistribute it
   28.13 + * freely, subject to the following restrictions:
   28.14 + *
   28.15 + * 1. The origin of this software must not be misrepresented; you must not
   28.16 + * claim that you wrote the original software. If you use this software
   28.17 + * in a product, an acknowledgment in the product documentation would be
   28.18 + * appreciated but is not required.
   28.19 + * 2. Altered source versions must be plainly marked as such, and must not be
   28.20 + * misrepresented as being the original software.
   28.21 + * 3. This notice may not be removed or altered from any source distribution.
   28.22 + *
   28.23 + * The SVG parser is based on Anti-Grain Geometry 2.4 SVG example
   28.24 + * Copyright (C) 2002-2004 Maxim Shemanarev (McSeem) (http://www.antigrain.com/)
   28.25 + *
   28.26 + * Arc calculation code based on canvg (https://code.google.com/p/canvg/)
   28.27 + *
   28.28 + * Bounding box calculation based on http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html
   28.29 + *
   28.30 + */
   28.31 +
   28.32 +#ifndef NANOSVG_H
   28.33 +#define NANOSVG_H
   28.34 +
   28.35 +#ifdef __cplusplus
   28.36 +extern "C" {
   28.37 +#endif
   28.38 +
   28.39 +// NanoSVG is a simple stupid single-header-file SVG parse. The output of the parser is a list of cubic bezier shapes.
   28.40 +//
   28.41 +// The library suits well for anything from rendering scalable icons in your editor application to prototyping a game.
   28.42 +//
   28.43 +// NanoSVG supports a wide range of SVG features, but something may be missing, feel free to create a pull request!
   28.44 +//
   28.45 +// The shapes in the SVG images are transformed by the viewBox and converted to specified units.
   28.46 +// That is, you should get the same looking data as your designed in your favorite app.
   28.47 +//
   28.48 +// NanoSVG can return the paths in few different units. For example if you want to render an image, you may choose
   28.49 +// to get the paths in pixels, or if you are feeding the data into a CNC-cutter, you may want to use millimeters.
   28.50 +//
   28.51 +// The units passed to NanoVG should be one of: 'px', 'pt', 'pc' 'mm', 'cm', or 'in'.
   28.52 +// DPI (dots-per-inch) controls how the unit conversion is done.
   28.53 +//
   28.54 +// If you don't know or care about the units stuff, "px" and 96 should get you going.
   28.55 +
   28.56 +
   28.57 +/* Example Usage:
   28.58 +	// Load
   28.59 +	NSVGImage* image;
   28.60 +	image = nsvgParseFromFile("test.svg", "px", 96);
   28.61 +	printf("size: %f x %f\n", image->width, image->height);
   28.62 +	// Use...
   28.63 +	for (NSVGshape *shape = image->shapes; shape != NULL; shape = shape->next) {
   28.64 +		for (NSVGpath *path = shape->paths; path != NULL; path = path->next) {
   28.65 +			for (int i = 0; i < path->npts-1; i += 3) {
   28.66 +				float* p = &path->pts[i*2];
   28.67 +				drawCubicBez(p[0],p[1], p[2],p[3], p[4],p[5], p[6],p[7]);
   28.68 +			}
   28.69 +		}
   28.70 +	}
   28.71 +	// Delete
   28.72 +	nsvgDelete(image);
   28.73 +*/
   28.74 +
   28.75 +enum NSVGpaintType {
   28.76 +	NSVG_PAINT_NONE = 0,
   28.77 +	NSVG_PAINT_COLOR = 1,
   28.78 +	NSVG_PAINT_LINEAR_GRADIENT = 2,
   28.79 +	NSVG_PAINT_RADIAL_GRADIENT = 3
   28.80 +};
   28.81 +
   28.82 +enum NSVGspreadType {
   28.83 +	NSVG_SPREAD_PAD = 0,
   28.84 +	NSVG_SPREAD_REFLECT = 1,
   28.85 +	NSVG_SPREAD_REPEAT = 2
   28.86 +};
   28.87 +
   28.88 +enum NSVGlineJoin {
   28.89 +	NSVG_JOIN_MITER = 0,
   28.90 +	NSVG_JOIN_ROUND = 1,
   28.91 +	NSVG_JOIN_BEVEL = 2
   28.92 +};
   28.93 +
   28.94 +enum NSVGlineCap {
   28.95 +	NSVG_CAP_BUTT = 0,
   28.96 +	NSVG_CAP_ROUND = 1,
   28.97 +	NSVG_CAP_SQUARE = 2
   28.98 +};
   28.99 +
  28.100 +enum NSVGfillRule {
  28.101 +	NSVG_FILLRULE_NONZERO = 0,
  28.102 +	NSVG_FILLRULE_EVENODD = 1
  28.103 +};
  28.104 +
  28.105 +enum NSVGflags {
  28.106 +	NSVG_FLAGS_VISIBLE = 0x01
  28.107 +};
  28.108 +
  28.109 +typedef struct NSVGgradientStop {
  28.110 +	unsigned int color;
  28.111 +	float offset;
  28.112 +} NSVGgradientStop;
  28.113 +
  28.114 +typedef struct NSVGgradient {
  28.115 +	float xform[6];
  28.116 +	char spread;
  28.117 +	float fx, fy;
  28.118 +	int nstops;
  28.119 +	NSVGgradientStop stops[1];
  28.120 +} NSVGgradient;
  28.121 +
  28.122 +typedef struct NSVGpaint {
  28.123 +	char type;
  28.124 +	union {
  28.125 +		unsigned int color;
  28.126 +		NSVGgradient* gradient;
  28.127 +	};
  28.128 +} NSVGpaint;
  28.129 +
  28.130 +typedef struct NSVGpath
  28.131 +{
  28.132 +	float* pts;					// Cubic bezier points: x0,y0, [cpx1,cpx1,cpx2,cpy2,x1,y1], ...
  28.133 +	int npts;					// Total number of bezier points.
  28.134 +	char closed;				// Flag indicating if shapes should be treated as closed.
  28.135 +	float bounds[4];			// Tight bounding box of the shape [minx,miny,maxx,maxy].
  28.136 +	struct NSVGpath* next;		// Pointer to next path, or NULL if last element.
  28.137 +} NSVGpath;
  28.138 +
  28.139 +typedef struct NSVGshape
  28.140 +{
  28.141 +	char id[64];				// Optional 'id' attr of the shape or its group
  28.142 +	NSVGpaint fill;				// Fill paint
  28.143 +	NSVGpaint stroke;			// Stroke paint
  28.144 +	float opacity;				// Opacity of the shape.
  28.145 +	float strokeWidth;			// Stroke width (scaled).
  28.146 +	float strokeDashOffset;		// Stroke dash offset (scaled).
  28.147 +	float strokeDashArray[8];			// Stroke dash array (scaled).
  28.148 +	char strokeDashCount;				// Number of dash values in dash array.
  28.149 +	char strokeLineJoin;		// Stroke join type.
  28.150 +	char strokeLineCap;			// Stroke cap type.
  28.151 +	float miterLimit;			// Miter limit
  28.152 +	char fillRule;				// Fill rule, see NSVGfillRule.
  28.153 +	unsigned char flags;		// Logical or of NSVG_FLAGS_* flags
  28.154 +	float bounds[4];			// Tight bounding box of the shape [minx,miny,maxx,maxy].
  28.155 +	NSVGpath* paths;			// Linked list of paths in the image.
  28.156 +	struct NSVGshape* next;		// Pointer to next shape, or NULL if last element.
  28.157 +} NSVGshape;
  28.158 +
  28.159 +typedef struct NSVGimage
  28.160 +{
  28.161 +	float width;				// Width of the image.
  28.162 +	float height;				// Height of the image.
  28.163 +	NSVGshape* shapes;			// Linked list of shapes in the image.
  28.164 +} NSVGimage;
  28.165 +
  28.166 +// Parses SVG file from a file, returns SVG image as paths.
  28.167 +NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi);
  28.168 +
  28.169 +// Parses SVG file from a null terminated string, returns SVG image as paths.
  28.170 +// Important note: changes the string.
  28.171 +NSVGimage* nsvgParse(char* input, const char* units, float dpi);
  28.172 +
  28.173 +// Deletes list of paths.
  28.174 +void nsvgDelete(NSVGimage* image);
  28.175 +
  28.176 +#ifdef __cplusplus
  28.177 +}
  28.178 +#endif
  28.179 +
  28.180 +#endif // NANOSVG_H
  28.181 +
  28.182 +#ifdef NANOSVG_IMPLEMENTATION
  28.183 +
  28.184 +#include <string.h>
  28.185 +#include <stdlib.h>
  28.186 +#include <math.h>
  28.187 +
  28.188 +#define NSVG_PI (3.14159265358979323846264338327f)
  28.189 +#define NSVG_KAPPA90 (0.5522847493f)	// Length proportional to radius of a cubic bezier handle for 90deg arcs.
  28.190 +
  28.191 +#define NSVG_ALIGN_MIN 0
  28.192 +#define NSVG_ALIGN_MID 1
  28.193 +#define NSVG_ALIGN_MAX 2
  28.194 +#define NSVG_ALIGN_NONE 0
  28.195 +#define NSVG_ALIGN_MEET 1
  28.196 +#define NSVG_ALIGN_SLICE 2
  28.197 +
  28.198 +#define NSVG_NOTUSED(v) do { (void)(1 ? (void)0 : ( (void)(v) ) ); } while(0)
  28.199 +#define NSVG_RGB(r, g, b) (((unsigned int)r) | ((unsigned int)g << 8) | ((unsigned int)b << 16))
  28.200 +
  28.201 +#ifdef _MSC_VER
  28.202 +	#pragma warning (disable: 4996) // Switch off security warnings
  28.203 +	#pragma warning (disable: 4100) // Switch off unreferenced formal parameter warnings
  28.204 +	#ifdef __cplusplus
  28.205 +	#define NSVG_INLINE inline
  28.206 +	#else
  28.207 +	#define NSVG_INLINE
  28.208 +	#endif
  28.209 +#else
  28.210 +	#define NSVG_INLINE inline
  28.211 +#endif
  28.212 +
  28.213 +
  28.214 +static int nsvg__isspace(char c)
  28.215 +{
  28.216 +	return strchr(" \t\n\v\f\r", c) != 0;
  28.217 +}
  28.218 +
  28.219 +static int nsvg__isdigit(char c)
  28.220 +{
  28.221 +	return c >= '0' && c <= '9';
  28.222 +}
  28.223 +
  28.224 +static int nsvg__isnum(char c)
  28.225 +{
  28.226 +	return strchr("0123456789+-.eE", c) != 0;
  28.227 +}
  28.228 +
  28.229 +static NSVG_INLINE float nsvg__minf(float a, float b) { return a < b ? a : b; }
  28.230 +static NSVG_INLINE float nsvg__maxf(float a, float b) { return a > b ? a : b; }
  28.231 +
  28.232 +
  28.233 +// Simple XML parser
  28.234 +
  28.235 +#define NSVG_XML_TAG 1
  28.236 +#define NSVG_XML_CONTENT 2
  28.237 +#define NSVG_XML_MAX_ATTRIBS 256
  28.238 +
  28.239 +static void nsvg__parseContent(char* s,
  28.240 +							   void (*contentCb)(void* ud, const char* s),
  28.241 +							   void* ud)
  28.242 +{
  28.243 +	// Trim start white spaces
  28.244 +	while (*s && nsvg__isspace(*s)) s++;
  28.245 +	if (!*s) return;
  28.246 +
  28.247 +	if (contentCb)
  28.248 +		(*contentCb)(ud, s);
  28.249 +}
  28.250 +
  28.251 +static void nsvg__parseElement(char* s,
  28.252 +							   void (*startelCb)(void* ud, const char* el, const char** attr),
  28.253 +							   void (*endelCb)(void* ud, const char* el),
  28.254 +							   void* ud)
  28.255 +{
  28.256 +	const char* attr[NSVG_XML_MAX_ATTRIBS];
  28.257 +	int nattr = 0;
  28.258 +	char* name;
  28.259 +	int start = 0;
  28.260 +	int end = 0;
  28.261 +	char quote;
  28.262 +
  28.263 +	// Skip white space after the '<'
  28.264 +	while (*s && nsvg__isspace(*s)) s++;
  28.265 +
  28.266 +	// Check if the tag is end tag
  28.267 +	if (*s == '/') {
  28.268 +		s++;
  28.269 +		end = 1;
  28.270 +	} else {
  28.271 +		start = 1;
  28.272 +	}
  28.273 +
  28.274 +	// Skip comments, data and preprocessor stuff.
  28.275 +	if (!*s || *s == '?' || *s == '!')
  28.276 +		return;
  28.277 +
  28.278 +	// Get tag name
  28.279 +	name = s;
  28.280 +	while (*s && !nsvg__isspace(*s)) s++;
  28.281 +	if (*s) { *s++ = '\0'; }
  28.282 +
  28.283 +	// Get attribs
  28.284 +	while (!end && *s && nattr < NSVG_XML_MAX_ATTRIBS-3) {
  28.285 +		char* name = NULL;
  28.286 +		char* value = NULL;
  28.287 +
  28.288 +		// Skip white space before the attrib name
  28.289 +		while (*s && nsvg__isspace(*s)) s++;
  28.290 +		if (!*s) break;
  28.291 +		if (*s == '/') {
  28.292 +			end = 1;
  28.293 +			break;
  28.294 +		}
  28.295 +		name = s;
  28.296 +		// Find end of the attrib name.
  28.297 +		while (*s && !nsvg__isspace(*s) && *s != '=') s++;
  28.298 +		if (*s) { *s++ = '\0'; }
  28.299 +		// Skip until the beginning of the value.
  28.300 +		while (*s && *s != '\"' && *s != '\'') s++;
  28.301 +		if (!*s) break;
  28.302 +		quote = *s;
  28.303 +		s++;
  28.304 +		// Store value and find the end of it.
  28.305 +		value = s;
  28.306 +		while (*s && *s != quote) s++;
  28.307 +		if (*s) { *s++ = '\0'; }
  28.308 +
  28.309 +		// Store only well formed attributes
  28.310 +		if (name && value) {
  28.311 +			attr[nattr++] = name;
  28.312 +			attr[nattr++] = value;
  28.313 +		}
  28.314 +	}
  28.315 +
  28.316 +	// List terminator
  28.317 +	attr[nattr++] = 0;
  28.318 +	attr[nattr++] = 0;
  28.319 +
  28.320 +	// Call callbacks.
  28.321 +	if (start && startelCb)
  28.322 +		(*startelCb)(ud, name, attr);
  28.323 +	if (end && endelCb)
  28.324 +		(*endelCb)(ud, name);
  28.325 +}
  28.326 +
  28.327 +int nsvg__parseXML(char* input,
  28.328 +				   void (*startelCb)(void* ud, const char* el, const char** attr),
  28.329 +				   void (*endelCb)(void* ud, const char* el),
  28.330 +				   void (*contentCb)(void* ud, const char* s),
  28.331 +				   void* ud)
  28.332 +{
  28.333 +	char* s = input;
  28.334 +	char* mark = s;
  28.335 +	int state = NSVG_XML_CONTENT;
  28.336 +	while (*s) {
  28.337 +		if (*s == '<' && state == NSVG_XML_CONTENT) {
  28.338 +			// Start of a tag
  28.339 +			*s++ = '\0';
  28.340 +			nsvg__parseContent(mark, contentCb, ud);
  28.341 +			mark = s;
  28.342 +			state = NSVG_XML_TAG;
  28.343 +		} else if (*s == '>' && state == NSVG_XML_TAG) {
  28.344 +			// Start of a content or new tag.
  28.345 +			*s++ = '\0';
  28.346 +			nsvg__parseElement(mark, startelCb, endelCb, ud);
  28.347 +			mark = s;
  28.348 +			state = NSVG_XML_CONTENT;
  28.349 +		} else {
  28.350 +			s++;
  28.351 +		}
  28.352 +	}
  28.353 +
  28.354 +	return 1;
  28.355 +}
  28.356 +
  28.357 +
  28.358 +/* Simple SVG parser. */
  28.359 +
  28.360 +#define NSVG_MAX_ATTR 128
  28.361 +
  28.362 +enum NSVGgradientUnits {
  28.363 +	NSVG_USER_SPACE = 0,
  28.364 +	NSVG_OBJECT_SPACE = 1
  28.365 +};
  28.366 +
  28.367 +#define NSVG_MAX_DASHES 8
  28.368 +
  28.369 +enum NSVGunits {
  28.370 +	NSVG_UNITS_USER,
  28.371 +	NSVG_UNITS_PX,
  28.372 +	NSVG_UNITS_PT,
  28.373 +	NSVG_UNITS_PC,
  28.374 +	NSVG_UNITS_MM,
  28.375 +	NSVG_UNITS_CM,
  28.376 +	NSVG_UNITS_IN,
  28.377 +	NSVG_UNITS_PERCENT,
  28.378 +	NSVG_UNITS_EM,
  28.379 +	NSVG_UNITS_EX
  28.380 +};
  28.381 +
  28.382 +typedef struct NSVGcoordinate {
  28.383 +	float value;
  28.384 +	int units;
  28.385 +} NSVGcoordinate;
  28.386 +
  28.387 +typedef struct NSVGlinearData {
  28.388 +	NSVGcoordinate x1, y1, x2, y2;
  28.389 +} NSVGlinearData;
  28.390 +
  28.391 +typedef struct NSVGradialData {
  28.392 +	NSVGcoordinate cx, cy, r, fx, fy;
  28.393 +} NSVGradialData;
  28.394 +
  28.395 +typedef struct NSVGgradientData
  28.396 +{
  28.397 +	char id[64];
  28.398 +	char ref[64];
  28.399 +	char type;
  28.400 +	union {
  28.401 +		NSVGlinearData linear;
  28.402 +		NSVGradialData radial;
  28.403 +	};
  28.404 +	char spread;
  28.405 +	char units;
  28.406 +	float xform[6];
  28.407 +	int nstops;
  28.408 +	NSVGgradientStop* stops;
  28.409 +	struct NSVGgradientData* next;
  28.410 +} NSVGgradientData;
  28.411 +
  28.412 +typedef struct NSVGattrib
  28.413 +{
  28.414 +	char id[64];
  28.415 +	float xform[6];
  28.416 +	unsigned int fillColor;
  28.417 +	unsigned int strokeColor;
  28.418 +	float opacity;
  28.419 +	float fillOpacity;
  28.420 +	float strokeOpacity;
  28.421 +	char fillGradient[64];
  28.422 +	char strokeGradient[64];
  28.423 +	float strokeWidth;
  28.424 +	float strokeDashOffset;
  28.425 +	float strokeDashArray[NSVG_MAX_DASHES];
  28.426 +	int strokeDashCount;
  28.427 +	char strokeLineJoin;
  28.428 +	char strokeLineCap;
  28.429 +	float miterLimit;
  28.430 +	char fillRule;
  28.431 +	float fontSize;
  28.432 +	unsigned int stopColor;
  28.433 +	float stopOpacity;
  28.434 +	float stopOffset;
  28.435 +	char hasFill;
  28.436 +	char hasStroke;
  28.437 +	char visible;
  28.438 +} NSVGattrib;
  28.439 +
  28.440 +typedef struct NSVGparser
  28.441 +{
  28.442 +	NSVGattrib attr[NSVG_MAX_ATTR];
  28.443 +	int attrHead;
  28.444 +	float* pts;
  28.445 +	int npts;
  28.446 +	int cpts;
  28.447 +	NSVGpath* plist;
  28.448 +	NSVGimage* image;
  28.449 +	NSVGgradientData* gradients;
  28.450 +	NSVGshape* shapesTail;
  28.451 +	float viewMinx, viewMiny, viewWidth, viewHeight;
  28.452 +	int alignX, alignY, alignType;
  28.453 +	float dpi;
  28.454 +	char pathFlag;
  28.455 +	char defsFlag;
  28.456 +} NSVGparser;
  28.457 +
  28.458 +static void nsvg__xformIdentity(float* t)
  28.459 +{
  28.460 +	t[0] = 1.0f; t[1] = 0.0f;
  28.461 +	t[2] = 0.0f; t[3] = 1.0f;
  28.462 +	t[4] = 0.0f; t[5] = 0.0f;
  28.463 +}
  28.464 +
  28.465 +static void nsvg__xformSetTranslation(float* t, float tx, float ty)
  28.466 +{
  28.467 +	t[0] = 1.0f; t[1] = 0.0f;
  28.468 +	t[2] = 0.0f; t[3] = 1.0f;
  28.469 +	t[4] = tx; t[5] = ty;
  28.470 +}
  28.471 +
  28.472 +static void nsvg__xformSetScale(float* t, float sx, float sy)
  28.473 +{
  28.474 +	t[0] = sx; t[1] = 0.0f;
  28.475 +	t[2] = 0.0f; t[3] = sy;
  28.476 +	t[4] = 0.0f; t[5] = 0.0f;
  28.477 +}
  28.478 +
  28.479 +static void nsvg__xformSetSkewX(float* t, float a)
  28.480 +{
  28.481 +	t[0] = 1.0f; t[1] = 0.0f;
  28.482 +	t[2] = tanf(a); t[3] = 1.0f;
  28.483 +	t[4] = 0.0f; t[5] = 0.0f;
  28.484 +}
  28.485 +
  28.486 +static void nsvg__xformSetSkewY(float* t, float a)
  28.487 +{
  28.488 +	t[0] = 1.0f; t[1] = tanf(a);
  28.489 +	t[2] = 0.0f; t[3] = 1.0f;
  28.490 +	t[4] = 0.0f; t[5] = 0.0f;
  28.491 +}
  28.492 +
  28.493 +static void nsvg__xformSetRotation(float* t, float a)
  28.494 +{
  28.495 +	float cs = cosf(a), sn = sinf(a);
  28.496 +	t[0] = cs; t[1] = sn;
  28.497 +	t[2] = -sn; t[3] = cs;
  28.498 +	t[4] = 0.0f; t[5] = 0.0f;
  28.499 +}
  28.500 +
  28.501 +static void nsvg__xformMultiply(float* t, float* s)
  28.502 +{
  28.503 +	float t0 = t[0] * s[0] + t[1] * s[2];
  28.504 +	float t2 = t[2] * s[0] + t[3] * s[2];
  28.505 +	float t4 = t[4] * s[0] + t[5] * s[2] + s[4];
  28.506 +	t[1] = t[0] * s[1] + t[1] * s[3];
  28.507 +	t[3] = t[2] * s[1] + t[3] * s[3];
  28.508 +	t[5] = t[4] * s[1] + t[5] * s[3] + s[5];
  28.509 +	t[0] = t0;
  28.510 +	t[2] = t2;
  28.511 +	t[4] = t4;
  28.512 +}
  28.513 +
  28.514 +static void nsvg__xformInverse(float* inv, float* t)
  28.515 +{
  28.516 +	double invdet, det = (double)t[0] * t[3] - (double)t[2] * t[1];
  28.517 +	if (det > -1e-6 && det < 1e-6) {
  28.518 +		nsvg__xformIdentity(t);
  28.519 +		return;
  28.520 +	}
  28.521 +	invdet = 1.0 / det;
  28.522 +	inv[0] = (float)(t[3] * invdet);
  28.523 +	inv[2] = (float)(-t[2] * invdet);
  28.524 +	inv[4] = (float)(((double)t[2] * t[5] - (double)t[3] * t[4]) * invdet);
  28.525 +	inv[1] = (float)(-t[1] * invdet);
  28.526 +	inv[3] = (float)(t[0] * invdet);
  28.527 +	inv[5] = (float)(((double)t[1] * t[4] - (double)t[0] * t[5]) * invdet);
  28.528 +}
  28.529 +
  28.530 +static void nsvg__xformPremultiply(float* t, float* s)
  28.531 +{
  28.532 +	float s2[6];
  28.533 +	memcpy(s2, s, sizeof(float)*6);
  28.534 +	nsvg__xformMultiply(s2, t);
  28.535 +	memcpy(t, s2, sizeof(float)*6);
  28.536 +}
  28.537 +
  28.538 +static void nsvg__xformPoint(float* dx, float* dy, float x, float y, float* t)
  28.539 +{
  28.540 +	*dx = x*t[0] + y*t[2] + t[4];
  28.541 +	*dy = x*t[1] + y*t[3] + t[5];
  28.542 +}
  28.543 +
  28.544 +static void nsvg__xformVec(float* dx, float* dy, float x, float y, float* t)
  28.545 +{
  28.546 +	*dx = x*t[0] + y*t[2];
  28.547 +	*dy = x*t[1] + y*t[3];
  28.548 +}
  28.549 +
  28.550 +#define NSVG_EPSILON (1e-12)
  28.551 +
  28.552 +static int nsvg__ptInBounds(float* pt, float* bounds)
  28.553 +{
  28.554 +	return pt[0] >= bounds[0] && pt[0] <= bounds[2] && pt[1] >= bounds[1] && pt[1] <= bounds[3];
  28.555 +}
  28.556 +
  28.557 +
  28.558 +static double nsvg__evalBezier(double t, double p0, double p1, double p2, double p3)
  28.559 +{
  28.560 +	double it = 1.0-t;
  28.561 +	return it*it*it*p0 + 3.0*it*it*t*p1 + 3.0*it*t*t*p2 + t*t*t*p3;
  28.562 +}
  28.563 +
  28.564 +static void nsvg__curveBounds(float* bounds, float* curve)
  28.565 +{
  28.566 +	int i, j, count;
  28.567 +	double roots[2], a, b, c, b2ac, t, v;
  28.568 +	float* v0 = &curve[0];
  28.569 +	float* v1 = &curve[2];
  28.570 +	float* v2 = &curve[4];
  28.571 +	float* v3 = &curve[6];
  28.572 +
  28.573 +	// Start the bounding box by end points
  28.574 +	bounds[0] = nsvg__minf(v0[0], v3[0]);
  28.575 +	bounds[1] = nsvg__minf(v0[1], v3[1]);
  28.576 +	bounds[2] = nsvg__maxf(v0[0], v3[0]);
  28.577 +	bounds[3] = nsvg__maxf(v0[1], v3[1]);
  28.578 +
  28.579 +	// Bezier curve fits inside the convex hull of it's control points.
  28.580 +	// If control points are inside the bounds, we're done.
  28.581 +	if (nsvg__ptInBounds(v1, bounds) && nsvg__ptInBounds(v2, bounds))
  28.582 +		return;
  28.583 +
  28.584 +	// Add bezier curve inflection points in X and Y.
  28.585 +	for (i = 0; i < 2; i++) {
  28.586 +		a = -3.0 * v0[i] + 9.0 * v1[i] - 9.0 * v2[i] + 3.0 * v3[i];
  28.587 +		b = 6.0 * v0[i] - 12.0 * v1[i] + 6.0 * v2[i];
  28.588 +		c = 3.0 * v1[i] - 3.0 * v0[i];
  28.589 +		count = 0;
  28.590 +		if (fabs(a) < NSVG_EPSILON) {
  28.591 +			if (fabs(b) > NSVG_EPSILON) {
  28.592 +				t = -c / b;
  28.593 +				if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
  28.594 +					roots[count++] = t;
  28.595 +			}
  28.596 +		} else {
  28.597 +			b2ac = b*b - 4.0*c*a;
  28.598 +			if (b2ac > NSVG_EPSILON) {
  28.599 +				t = (-b + sqrt(b2ac)) / (2.0 * a);
  28.600 +				if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
  28.601 +					roots[count++] = t;
  28.602 +				t = (-b - sqrt(b2ac)) / (2.0 * a);
  28.603 +				if (t > NSVG_EPSILON && t < 1.0-NSVG_EPSILON)
  28.604 +					roots[count++] = t;
  28.605 +			}
  28.606 +		}
  28.607 +		for (j = 0; j < count; j++) {
  28.608 +			v = nsvg__evalBezier(roots[j], v0[i], v1[i], v2[i], v3[i]);
  28.609 +			bounds[0+i] = nsvg__minf(bounds[0+i], (float)v);
  28.610 +			bounds[2+i] = nsvg__maxf(bounds[2+i], (float)v);
  28.611 +		}
  28.612 +	}
  28.613 +}
  28.614 +
  28.615 +static NSVGparser* nsvg__createParser()
  28.616 +{
  28.617 +	NSVGparser* p;
  28.618 +	p = (NSVGparser*)malloc(sizeof(NSVGparser));
  28.619 +	if (p == NULL) goto error;
  28.620 +	memset(p, 0, sizeof(NSVGparser));
  28.621 +
  28.622 +	p->image = (NSVGimage*)malloc(sizeof(NSVGimage));
  28.623 +	if (p->image == NULL) goto error;
  28.624 +	memset(p->image, 0, sizeof(NSVGimage));
  28.625 +
  28.626 +	// Init style
  28.627 +	nsvg__xformIdentity(p->attr[0].xform);
  28.628 +	memset(p->attr[0].id, 0, sizeof p->attr[0].id);
  28.629 +	p->attr[0].fillColor = NSVG_RGB(0,0,0);
  28.630 +	p->attr[0].strokeColor = NSVG_RGB(0,0,0);
  28.631 +	p->attr[0].opacity = 1;
  28.632 +	p->attr[0].fillOpacity = 1;
  28.633 +	p->attr[0].strokeOpacity = 1;
  28.634 +	p->attr[0].stopOpacity = 1;
  28.635 +	p->attr[0].strokeWidth = 1;
  28.636 +	p->attr[0].strokeLineJoin = NSVG_JOIN_MITER;
  28.637 +	p->attr[0].strokeLineCap = NSVG_CAP_BUTT;
  28.638 +	p->attr[0].miterLimit = 4;
  28.639 +	p->attr[0].fillRule = NSVG_FILLRULE_NONZERO;
  28.640 +	p->attr[0].hasFill = 1;
  28.641 +	p->attr[0].visible = 1;
  28.642 +
  28.643 +	return p;
  28.644 +
  28.645 +error:
  28.646 +	if (p) {
  28.647 +		if (p->image) free(p->image);
  28.648 +		free(p);
  28.649 +	}
  28.650 +	return NULL;
  28.651 +}
  28.652 +
  28.653 +static void nsvg__deletePaths(NSVGpath* path)
  28.654 +{
  28.655 +	while (path) {
  28.656 +		NSVGpath *next = path->next;
  28.657 +		if (path->pts != NULL)
  28.658 +			free(path->pts);
  28.659 +		free(path);
  28.660 +		path = next;
  28.661 +	}
  28.662 +}
  28.663 +
  28.664 +static void nsvg__deletePaint(NSVGpaint* paint)
  28.665 +{
  28.666 +	if (paint->type == NSVG_PAINT_LINEAR_GRADIENT || paint->type == NSVG_PAINT_RADIAL_GRADIENT)
  28.667 +		free(paint->gradient);
  28.668 +}
  28.669 +
  28.670 +static void nsvg__deleteGradientData(NSVGgradientData* grad)
  28.671 +{
  28.672 +	NSVGgradientData* next;
  28.673 +	while (grad != NULL) {
  28.674 +		next = grad->next;
  28.675 +		free(grad->stops);
  28.676 +		free(grad);
  28.677 +		grad = next;
  28.678 +	}
  28.679 +}
  28.680 +
  28.681 +static void nsvg__deleteParser(NSVGparser* p)
  28.682 +{
  28.683 +	if (p != NULL) {
  28.684 +		nsvg__deletePaths(p->plist);
  28.685 +		nsvg__deleteGradientData(p->gradients);
  28.686 +		nsvgDelete(p->image);
  28.687 +		free(p->pts);
  28.688 +		free(p);
  28.689 +	}
  28.690 +}
  28.691 +
  28.692 +static void nsvg__resetPath(NSVGparser* p)
  28.693 +{
  28.694 +	p->npts = 0;
  28.695 +}
  28.696 +
  28.697 +static void nsvg__addPoint(NSVGparser* p, float x, float y)
  28.698 +{
  28.699 +	if (p->npts+1 > p->cpts) {
  28.700 +		p->cpts = p->cpts ? p->cpts*2 : 8;
  28.701 +		p->pts = (float*)realloc(p->pts, p->cpts*2*sizeof(float));
  28.702 +		if (!p->pts) return;
  28.703 +	}
  28.704 +	p->pts[p->npts*2+0] = x;
  28.705 +	p->pts[p->npts*2+1] = y;
  28.706 +	p->npts++;
  28.707 +}
  28.708 +
  28.709 +static void nsvg__moveTo(NSVGparser* p, float x, float y)
  28.710 +{
  28.711 +	if (p->npts > 0) {
  28.712 +		p->pts[(p->npts-1)*2+0] = x;
  28.713 +		p->pts[(p->npts-1)*2+1] = y;
  28.714 +	} else {
  28.715 +		nsvg__addPoint(p, x, y);
  28.716 +	}
  28.717 +}
  28.718 +
  28.719 +static void nsvg__lineTo(NSVGparser* p, float x, float y)
  28.720 +{
  28.721 +	float px,py, dx,dy;
  28.722 +	if (p->npts > 0) {
  28.723 +		px = p->pts[(p->npts-1)*2+0];
  28.724 +		py = p->pts[(p->npts-1)*2+1];
  28.725 +		dx = x - px;
  28.726 +		dy = y - py;
  28.727 +		nsvg__addPoint(p, px + dx/3.0f, py + dy/3.0f);
  28.728 +		nsvg__addPoint(p, x - dx/3.0f, y - dy/3.0f);
  28.729 +		nsvg__addPoint(p, x, y);
  28.730 +	}
  28.731 +}
  28.732 +
  28.733 +static void nsvg__cubicBezTo(NSVGparser* p, float cpx1, float cpy1, float cpx2, float cpy2, float x, float y)
  28.734 +{
  28.735 +	nsvg__addPoint(p, cpx1, cpy1);
  28.736 +	nsvg__addPoint(p, cpx2, cpy2);
  28.737 +	nsvg__addPoint(p, x, y);
  28.738 +}
  28.739 +
  28.740 +static NSVGattrib* nsvg__getAttr(NSVGparser* p)
  28.741 +{
  28.742 +	return &p->attr[p->attrHead];
  28.743 +}
  28.744 +
  28.745 +static void nsvg__pushAttr(NSVGparser* p)
  28.746 +{
  28.747 +	if (p->attrHead < NSVG_MAX_ATTR-1) {
  28.748 +		p->attrHead++;
  28.749 +		memcpy(&p->attr[p->attrHead], &p->attr[p->attrHead-1], sizeof(NSVGattrib));
  28.750 +	}
  28.751 +}
  28.752 +
  28.753 +static void nsvg__popAttr(NSVGparser* p)
  28.754 +{
  28.755 +	if (p->attrHead > 0)
  28.756 +		p->attrHead--;
  28.757 +}
  28.758 +
  28.759 +static float nsvg__actualOrigX(NSVGparser* p)
  28.760 +{
  28.761 +	return p->viewMinx;
  28.762 +}
  28.763 +
  28.764 +static float nsvg__actualOrigY(NSVGparser* p)
  28.765 +{
  28.766 +	return p->viewMiny;
  28.767 +}
  28.768 +
  28.769 +static float nsvg__actualWidth(NSVGparser* p)
  28.770 +{
  28.771 +	return p->viewWidth;
  28.772 +}
  28.773 +
  28.774 +static float nsvg__actualHeight(NSVGparser* p)
  28.775 +{
  28.776 +	return p->viewHeight;
  28.777 +}
  28.778 +
  28.779 +static float nsvg__actualLength(NSVGparser* p)
  28.780 +{
  28.781 +	float w = nsvg__actualWidth(p), h = nsvg__actualHeight(p);
  28.782 +	return sqrtf(w*w + h*h) / sqrtf(2.0f);
  28.783 +}
  28.784 +
  28.785 +static float nsvg__convertToPixels(NSVGparser* p, NSVGcoordinate c, float orig, float length)
  28.786 +{
  28.787 +	NSVGattrib* attr = nsvg__getAttr(p);
  28.788 +	switch (c.units) {
  28.789 +		case NSVG_UNITS_USER:		return c.value;
  28.790 +		case NSVG_UNITS_PX:			return c.value;
  28.791 +		case NSVG_UNITS_PT:			return c.value / 72.0f * p->dpi;
  28.792 +		case NSVG_UNITS_PC:			return c.value / 6.0f * p->dpi;
  28.793 +		case NSVG_UNITS_MM:			return c.value / 25.4f * p->dpi;
  28.794 +		case NSVG_UNITS_CM:			return c.value / 2.54f * p->dpi;
  28.795 +		case NSVG_UNITS_IN:			return c.value * p->dpi;
  28.796 +		case NSVG_UNITS_EM:			return c.value * attr->fontSize;
  28.797 +		case NSVG_UNITS_EX:			return c.value * attr->fontSize * 0.52f; // x-height of Helvetica.
  28.798 +		case NSVG_UNITS_PERCENT:	return orig + c.value / 100.0f * length;
  28.799 +		default:					return c.value;
  28.800 +	}
  28.801 +	return c.value;
  28.802 +}
  28.803 +
  28.804 +static NSVGgradientData* nsvg__findGradientData(NSVGparser* p, const char* id)
  28.805 +{
  28.806 +	NSVGgradientData* grad = p->gradients;
  28.807 +	while (grad) {
  28.808 +		if (strcmp(grad->id, id) == 0)
  28.809 +			return grad;
  28.810 +		grad = grad->next;
  28.811 +	}
  28.812 +	return NULL;
  28.813 +}
  28.814 +
  28.815 +static NSVGgradient* nsvg__createGradient(NSVGparser* p, const char* id, const float* localBounds, char* paintType)
  28.816 +{
  28.817 +	NSVGattrib* attr = nsvg__getAttr(p);
  28.818 +	NSVGgradientData* data = NULL;
  28.819 +	NSVGgradientData* ref = NULL;
  28.820 +	NSVGgradientStop* stops = NULL;
  28.821 +	NSVGgradient* grad;
  28.822 +	float ox, oy, sw, sh, sl;
  28.823 +	int nstops = 0;
  28.824 +
  28.825 +	data = nsvg__findGradientData(p, id);
  28.826 +	if (data == NULL) return NULL;
  28.827 +
  28.828 +	// TODO: use ref to fill in all unset values too.
  28.829 +	ref = data;
  28.830 +	while (ref != NULL) {
  28.831 +		if (stops == NULL && ref->stops != NULL) {
  28.832 +			stops = ref->stops;
  28.833 +			nstops = ref->nstops;
  28.834 +			break;
  28.835 +		}
  28.836 +		ref = nsvg__findGradientData(p, ref->ref);
  28.837 +	}
  28.838 +	if (stops == NULL) return NULL;
  28.839 +
  28.840 +	grad = (NSVGgradient*)malloc(sizeof(NSVGgradient) + sizeof(NSVGgradientStop)*(nstops-1));
  28.841 +	if (grad == NULL) return NULL;
  28.842 +
  28.843 +	// The shape width and height.
  28.844 +	if (data->units == NSVG_OBJECT_SPACE) {
  28.845 +		ox = localBounds[0];
  28.846 +		oy = localBounds[1];
  28.847 +		sw = localBounds[2] - localBounds[0];
  28.848 +		sh = localBounds[3] - localBounds[1];
  28.849 +	} else {
  28.850 +		ox = nsvg__actualOrigX(p);
  28.851 +		oy = nsvg__actualOrigY(p);
  28.852 +		sw = nsvg__actualWidth(p);
  28.853 +		sh = nsvg__actualHeight(p);
  28.854 +	}
  28.855 +	sl = sqrtf(sw*sw + sh*sh) / sqrtf(2.0f);
  28.856 +
  28.857 +	if (data->type == NSVG_PAINT_LINEAR_GRADIENT) {
  28.858 +		float x1, y1, x2, y2, dx, dy;
  28.859 +		x1 = nsvg__convertToPixels(p, data->linear.x1, ox, sw);
  28.860 +		y1 = nsvg__convertToPixels(p, data->linear.y1, oy, sh);
  28.861 +		x2 = nsvg__convertToPixels(p, data->linear.x2, ox, sw);
  28.862 +		y2 = nsvg__convertToPixels(p, data->linear.y2, oy, sh);
  28.863 +		// Calculate transform aligned to the line
  28.864 +		dx = x2 - x1;
  28.865 +		dy = y2 - y1;
  28.866 +		grad->xform[0] = dy; grad->xform[1] = -dx;
  28.867 +		grad->xform[2] = dx; grad->xform[3] = dy;
  28.868 +		grad->xform[4] = x1; grad->xform[5] = y1;
  28.869 +	} else {
  28.870 +		float cx, cy, fx, fy, r;
  28.871 +		cx = nsvg__convertToPixels(p, data->radial.cx, ox, sw);
  28.872 +		cy = nsvg__convertToPixels(p, data->radial.cy, oy, sh);
  28.873 +		fx = nsvg__convertToPixels(p, data->radial.fx, ox, sw);
  28.874 +		fy = nsvg__convertToPixels(p, data->radial.fy, oy, sh);
  28.875 +		r = nsvg__convertToPixels(p, data->radial.r, 0, sl);
  28.876 +		// Calculate transform aligned to the circle
  28.877 +		grad->xform[0] = r; grad->xform[1] = 0;
  28.878 +		grad->xform[2] = 0; grad->xform[3] = r;
  28.879 +		grad->xform[4] = cx; grad->xform[5] = cy;
  28.880 +		grad->fx = fx / r;
  28.881 +		grad->fy = fy / r;
  28.882 +	}
  28.883 +
  28.884 +	nsvg__xformMultiply(grad->xform, data->xform);
  28.885 +	nsvg__xformMultiply(grad->xform, attr->xform);
  28.886 +
  28.887 +	grad->spread = data->spread;
  28.888 +	memcpy(grad->stops, stops, nstops*sizeof(NSVGgradientStop));
  28.889 +	grad->nstops = nstops;
  28.890 +
  28.891 +	*paintType = data->type;
  28.892 +
  28.893 +	return grad;
  28.894 +}
  28.895 +
  28.896 +static float nsvg__getAverageScale(float* t)
  28.897 +{
  28.898 +	float sx = sqrtf(t[0]*t[0] + t[2]*t[2]);
  28.899 +	float sy = sqrtf(t[1]*t[1] + t[3]*t[3]);
  28.900 +	return (sx + sy) * 0.5f;
  28.901 +}
  28.902 +
  28.903 +static void nsvg__getLocalBounds(float* bounds, NSVGshape *shape, float* xform)
  28.904 +{
  28.905 +	NSVGpath* path;
  28.906 +	float curve[4*2], curveBounds[4];
  28.907 +	int i, first = 1;
  28.908 +	for (path = shape->paths; path != NULL; path = path->next) {
  28.909 +		nsvg__xformPoint(&curve[0], &curve[1], path->pts[0], path->pts[1], xform);
  28.910 +		for (i = 0; i < path->npts-1; i += 3) {
  28.911 +			nsvg__xformPoint(&curve[2], &curve[3], path->pts[(i+1)*2], path->pts[(i+1)*2+1], xform);
  28.912 +			nsvg__xformPoint(&curve[4], &curve[5], path->pts[(i+2)*2], path->pts[(i+2)*2+1], xform);
  28.913 +			nsvg__xformPoint(&curve[6], &curve[7], path->pts[(i+3)*2], path->pts[(i+3)*2+1], xform);
  28.914 +			nsvg__curveBounds(curveBounds, curve);
  28.915 +			if (first) {
  28.916 +				bounds[0] = curveBounds[0];
  28.917 +				bounds[1] = curveBounds[1];
  28.918 +				bounds[2] = curveBounds[2];
  28.919 +				bounds[3] = curveBounds[3];
  28.920 +				first = 0;
  28.921 +			} else {
  28.922 +				bounds[0] = nsvg__minf(bounds[0], curveBounds[0]);
  28.923 +				bounds[1] = nsvg__minf(bounds[1], curveBounds[1]);
  28.924 +				bounds[2] = nsvg__maxf(bounds[2], curveBounds[2]);
  28.925 +				bounds[3] = nsvg__maxf(bounds[3], curveBounds[3]);
  28.926 +			}
  28.927 +			curve[0] = curve[6];
  28.928 +			curve[1] = curve[7];
  28.929 +		}
  28.930 +	}
  28.931 +}
  28.932 +
  28.933 +static void nsvg__addShape(NSVGparser* p)
  28.934 +{
  28.935 +	NSVGattrib* attr = nsvg__getAttr(p);
  28.936 +	float scale = 1.0f;
  28.937 +	NSVGshape* shape;
  28.938 +	NSVGpath* path;
  28.939 +	int i;
  28.940 +
  28.941 +	if (p->plist == NULL)
  28.942 +		return;
  28.943 +
  28.944 +	shape = (NSVGshape*)malloc(sizeof(NSVGshape));
  28.945 +	if (shape == NULL) goto error;
  28.946 +	memset(shape, 0, sizeof(NSVGshape));
  28.947 +
  28.948 +	memcpy(shape->id, attr->id, sizeof shape->id);
  28.949 +	scale = nsvg__getAverageScale(attr->xform);
  28.950 +	shape->strokeWidth = attr->strokeWidth * scale;
  28.951 +	shape->strokeDashOffset = attr->strokeDashOffset * scale;
  28.952 +	shape->strokeDashCount = (char)attr->strokeDashCount;
  28.953 +	for (i = 0; i < attr->strokeDashCount; i++)
  28.954 +		shape->strokeDashArray[i] = attr->strokeDashArray[i] * scale;
  28.955 +	shape->strokeLineJoin = attr->strokeLineJoin;
  28.956 +	shape->strokeLineCap = attr->strokeLineCap;
  28.957 +	shape->miterLimit = attr->miterLimit;
  28.958 +	shape->fillRule = attr->fillRule;
  28.959 +	shape->opacity = attr->opacity;
  28.960 +
  28.961 +	shape->paths = p->plist;
  28.962 +	p->plist = NULL;
  28.963 +
  28.964 +	// Calculate shape bounds
  28.965 +	shape->bounds[0] = shape->paths->bounds[0];
  28.966 +	shape->bounds[1] = shape->paths->bounds[1];
  28.967 +	shape->bounds[2] = shape->paths->bounds[2];
  28.968 +	shape->bounds[3] = shape->paths->bounds[3];
  28.969 +	for (path = shape->paths->next; path != NULL; path = path->next) {
  28.970 +		shape->bounds[0] = nsvg__minf(shape->bounds[0], path->bounds[0]);
  28.971 +		shape->bounds[1] = nsvg__minf(shape->bounds[1], path->bounds[1]);
  28.972 +		shape->bounds[2] = nsvg__maxf(shape->bounds[2], path->bounds[2]);
  28.973 +		shape->bounds[3] = nsvg__maxf(shape->bounds[3], path->bounds[3]);
  28.974 +	}
  28.975 +
  28.976 +	// Set fill
  28.977 +	if (attr->hasFill == 0) {
  28.978 +		shape->fill.type = NSVG_PAINT_NONE;
  28.979 +	} else if (attr->hasFill == 1) {
  28.980 +		shape->fill.type = NSVG_PAINT_COLOR;
  28.981 +		shape->fill.color = attr->fillColor;
  28.982 +		shape->fill.color |= (unsigned int)(attr->fillOpacity*255) << 24;
  28.983 +	} else if (attr->hasFill == 2) {
  28.984 +		float inv[6], localBounds[4];
  28.985 +		nsvg__xformInverse(inv, attr->xform);
  28.986 +		nsvg__getLocalBounds(localBounds, shape, inv);
  28.987 +		shape->fill.gradient = nsvg__createGradient(p, attr->fillGradient, localBounds, &shape->fill.type);
  28.988 +		if (shape->fill.gradient == NULL) {
  28.989 +			shape->fill.type = NSVG_PAINT_NONE;
  28.990 +		}
  28.991 +	}
  28.992 +
  28.993 +	// Set stroke
  28.994 +	if (attr->hasStroke == 0) {
  28.995 +		shape->stroke.type = NSVG_PAINT_NONE;
  28.996 +	} else if (attr->hasStroke == 1) {
  28.997 +		shape->stroke.type = NSVG_PAINT_COLOR;
  28.998 +		shape->stroke.color = attr->strokeColor;
  28.999 +		shape->stroke.color |= (unsigned int)(attr->strokeOpacity*255) << 24;
 28.1000 +	} else if (attr->hasStroke == 2) {
 28.1001 +		float inv[6], localBounds[4];
 28.1002 +		nsvg__xformInverse(inv, attr->xform);
 28.1003 +		nsvg__getLocalBounds(localBounds, shape, inv);
 28.1004 +		shape->stroke.gradient = nsvg__createGradient(p, attr->strokeGradient, localBounds, &shape->stroke.type);
 28.1005 +		if (shape->stroke.gradient == NULL)
 28.1006 +			shape->stroke.type = NSVG_PAINT_NONE;
 28.1007 +	}
 28.1008 +
 28.1009 +	// Set flags
 28.1010 +	shape->flags = (attr->visible ? NSVG_FLAGS_VISIBLE : 0x00);
 28.1011 +
 28.1012 +	// Add to tail
 28.1013 +	if (p->image->shapes == NULL)
 28.1014 +		p->image->shapes = shape;
 28.1015 +	else
 28.1016 +		p->shapesTail->next = shape;
 28.1017 +	p->shapesTail = shape;
 28.1018 +
 28.1019 +	return;
 28.1020 +
 28.1021 +error:
 28.1022 +	if (shape) free(shape);
 28.1023 +}
 28.1024 +
 28.1025 +static void nsvg__addPath(NSVGparser* p, char closed)
 28.1026 +{
 28.1027 +	NSVGattrib* attr = nsvg__getAttr(p);
 28.1028 +	NSVGpath* path = NULL;
 28.1029 +	float bounds[4];
 28.1030 +	float* curve;
 28.1031 +	int i;
 28.1032 +
 28.1033 +	if (p->npts < 4)
 28.1034 +		return;
 28.1035 +
 28.1036 +	if (closed)
 28.1037 +		nsvg__lineTo(p, p->pts[0], p->pts[1]);
 28.1038 +
 28.1039 +	path = (NSVGpath*)malloc(sizeof(NSVGpath));
 28.1040 +	if (path == NULL) goto error;
 28.1041 +	memset(path, 0, sizeof(NSVGpath));
 28.1042 +
 28.1043 +	path->pts = (float*)malloc(p->npts*2*sizeof(float));
 28.1044 +	if (path->pts == NULL) goto error;
 28.1045 +	path->closed = closed;
 28.1046 +	path->npts = p->npts;
 28.1047 +
 28.1048 +	// Transform path.
 28.1049 +	for (i = 0; i < p->npts; ++i)
 28.1050 +		nsvg__xformPoint(&path->pts[i*2], &path->pts[i*2+1], p->pts[i*2], p->pts[i*2+1], attr->xform);
 28.1051 +
 28.1052 +	// Find bounds
 28.1053 +	for (i = 0; i < path->npts-1; i += 3) {
 28.1054 +		curve = &path->pts[i*2];
 28.1055 +		nsvg__curveBounds(bounds, curve);
 28.1056 +		if (i == 0) {
 28.1057 +			path->bounds[0] = bounds[0];
 28.1058 +			path->bounds[1] = bounds[1];
 28.1059 +			path->bounds[2] = bounds[2];
 28.1060 +			path->bounds[3] = bounds[3];
 28.1061 +		} else {
 28.1062 +			path->bounds[0] = nsvg__minf(path->bounds[0], bounds[0]);
 28.1063 +			path->bounds[1] = nsvg__minf(path->bounds[1], bounds[1]);
 28.1064 +			path->bounds[2] = nsvg__maxf(path->bounds[2], bounds[2]);
 28.1065 +			path->bounds[3] = nsvg__maxf(path->bounds[3], bounds[3]);
 28.1066 +		}
 28.1067 +	}
 28.1068 +
 28.1069 +	path->next = p->plist;
 28.1070 +	p->plist = path;
 28.1071 +
 28.1072 +	return;
 28.1073 +
 28.1074 +error:
 28.1075 +	if (path != NULL) {
 28.1076 +		if (path->pts != NULL) free(path->pts);
 28.1077 +		free(path);
 28.1078 +	}
 28.1079 +}
 28.1080 +
 28.1081 +// We roll our own string to float because the std library one uses locale and messes things up.
 28.1082 +static double nsvg__atof(const char* s)
 28.1083 +{
 28.1084 +	char* cur = (char*)s;
 28.1085 +	char* end = NULL;
 28.1086 +	double res = 0.0, sign = 1.0;
 28.1087 +	long long intPart = 0, fracPart = 0;
 28.1088 +	char hasIntPart = 0, hasFracPart = 0;
 28.1089 +
 28.1090 +	// Parse optional sign
 28.1091 +	if (*cur == '+') {
 28.1092 +		cur++;
 28.1093 +	} else if (*cur == '-') {
 28.1094 +		sign = -1;
 28.1095 +		cur++;
 28.1096 +	}
 28.1097 +
 28.1098 +	// Parse integer part
 28.1099 +	if (nsvg__isdigit(*cur)) {
 28.1100 +		// Parse digit sequence
 28.1101 +		intPart = (double)strtoll(cur, &end, 10);
 28.1102 +		if (cur != end) {
 28.1103 +			res = (double)intPart;
 28.1104 +			hasIntPart = 1;
 28.1105 +			cur = end;
 28.1106 +		}
 28.1107 +	}
 28.1108 +
 28.1109 +	// Parse fractional part.
 28.1110 +	if (*cur == '.') {
 28.1111 +		cur++; // Skip '.'
 28.1112 +		if (nsvg__isdigit(*cur)) {
 28.1113 +			// Parse digit sequence
 28.1114 +			fracPart = strtoll(cur, &end, 10);
 28.1115 +			if (cur != end) {
 28.1116 +				res += (double)fracPart / pow(10.0, (double)(end - cur));
 28.1117 +				hasFracPart = 1;
 28.1118 +				cur = end;
 28.1119 +			}
 28.1120 +		}
 28.1121 +	}
 28.1122 +
 28.1123 +	// A valid number should have integer or fractional part.
 28.1124 +	if (!hasIntPart && !hasFracPart)
 28.1125 +		return 0.0;
 28.1126 +
 28.1127 +	// Parse optional exponent
 28.1128 +	if (*cur == 'e' || *cur == 'E') {
 28.1129 +		int expPart = 0;
 28.1130 +		cur++; // skip 'E'
 28.1131 +		expPart = strtol(cur, &end, 10); // Parse digit sequence with sign
 28.1132 +		if (cur != end) {
 28.1133 +			res *= pow(10.0, (double)expPart);
 28.1134 +		}
 28.1135 +	}
 28.1136 +
 28.1137 +	return res * sign;
 28.1138 +}
 28.1139 +
 28.1140 +
 28.1141 +static const char* nsvg__parseNumber(const char* s, char* it, const int size)
 28.1142 +{
 28.1143 +	const int last = size-1;
 28.1144 +	int i = 0;
 28.1145 +
 28.1146 +	// sign
 28.1147 +	if (*s == '-' || *s == '+') {
 28.1148 +		if (i < last) it[i++] = *s;
 28.1149 +		s++;
 28.1150 +	}
 28.1151 +	// integer part
 28.1152 +	while (*s && nsvg__isdigit(*s)) {
 28.1153 +		if (i < last) it[i++] = *s;
 28.1154 +		s++;
 28.1155 +	}
 28.1156 +	if (*s == '.') {
 28.1157 +		// decimal point
 28.1158 +		if (i < last) it[i++] = *s;
 28.1159 +		s++;
 28.1160 +		// fraction part
 28.1161 +		while (*s && nsvg__isdigit(*s)) {
 28.1162 +			if (i < last) it[i++] = *s;
 28.1163 +			s++;
 28.1164 +		}
 28.1165 +	}
 28.1166 +	// exponent
 28.1167 +	if (*s == 'e' || *s == 'E') {
 28.1168 +		if (i < last) it[i++] = *s;
 28.1169 +		s++;
 28.1170 +		if (*s == '-' || *s == '+') {
 28.1171 +			if (i < last) it[i++] = *s;
 28.1172 +			s++;
 28.1173 +		}
 28.1174 +		while (*s && nsvg__isdigit(*s)) {
 28.1175 +			if (i < last) it[i++] = *s;
 28.1176 +			s++;
 28.1177 +		}
 28.1178 +	}
 28.1179 +	it[i] = '\0';
 28.1180 +
 28.1181 +	return s;
 28.1182 +}
 28.1183 +
 28.1184 +static const char* nsvg__getNextPathItem(const char* s, char* it)
 28.1185 +{
 28.1186 +	it[0] = '\0';
 28.1187 +	// Skip white spaces and commas
 28.1188 +	while (*s && (nsvg__isspace(*s) || *s == ',')) s++;
 28.1189 +	if (!*s) return s;
 28.1190 +	if (*s == '-' || *s == '+' || *s == '.' || nsvg__isdigit(*s)) {
 28.1191 +		s = nsvg__parseNumber(s, it, 64);
 28.1192 +	} else {
 28.1193 +		// Parse command
 28.1194 +		it[0] = *s++;
 28.1195 +		it[1] = '\0';
 28.1196 +		return s;
 28.1197 +	}
 28.1198 +
 28.1199 +	return s;
 28.1200 +}
 28.1201 +
 28.1202 +static unsigned int nsvg__parseColorHex(const char* str)
 28.1203 +{
 28.1204 +	unsigned int c = 0, r = 0, g = 0, b = 0;
 28.1205 +	int n = 0;
 28.1206 +	str++; // skip #
 28.1207 +	// Calculate number of characters.
 28.1208 +	while(str[n] && !nsvg__isspace(str[n]))
 28.1209 +		n++;
 28.1210 +	if (n == 6) {
 28.1211 +		sscanf(str, "%x", &c);
 28.1212 +	} else if (n == 3) {
 28.1213 +		sscanf(str, "%x", &c);
 28.1214 +		c = (c&0xf) | ((c&0xf0) << 4) | ((c&0xf00) << 8);
 28.1215 +		c |= c<<4;
 28.1216 +	}
 28.1217 +	r = (c >> 16) & 0xff;
 28.1218 +	g = (c >> 8) & 0xff;
 28.1219 +	b = c & 0xff;
 28.1220 +	return NSVG_RGB(r,g,b);
 28.1221 +}
 28.1222 +
 28.1223 +static unsigned int nsvg__parseColorRGB(const char* str)
 28.1224 +{
 28.1225 +	int r = -1, g = -1, b = -1;
 28.1226 +	char s1[32]="", s2[32]="";
 28.1227 +	sscanf(str + 4, "%d%[%%, \t]%d%[%%, \t]%d", &r, s1, &g, s2, &b);
 28.1228 +	if (strchr(s1, '%')) {
 28.1229 +		return NSVG_RGB((r*255)/100,(g*255)/100,(b*255)/100);
 28.1230 +	} else {
 28.1231 +		return NSVG_RGB(r,g,b);
 28.1232 +	}
 28.1233 +}
 28.1234 +
 28.1235 +typedef struct NSVGNamedColor {
 28.1236 +	const char* name;
 28.1237 +	unsigned int color;
 28.1238 +} NSVGNamedColor;
 28.1239 +
 28.1240 +NSVGNamedColor nsvg__colors[] = {
 28.1241 +
 28.1242 +	{ "red", NSVG_RGB(255, 0, 0) },
 28.1243 +	{ "green", NSVG_RGB( 0, 128, 0) },
 28.1244 +	{ "blue", NSVG_RGB( 0, 0, 255) },
 28.1245 +	{ "yellow", NSVG_RGB(255, 255, 0) },
 28.1246 +	{ "cyan", NSVG_RGB( 0, 255, 255) },
 28.1247 +	{ "magenta", NSVG_RGB(255, 0, 255) },
 28.1248 +	{ "black", NSVG_RGB( 0, 0, 0) },
 28.1249 +	{ "grey", NSVG_RGB(128, 128, 128) },
 28.1250 +	{ "gray", NSVG_RGB(128, 128, 128) },
 28.1251 +	{ "white", NSVG_RGB(255, 255, 255) },
 28.1252 +
 28.1253 +#ifdef NANOSVG_ALL_COLOR_KEYWORDS
 28.1254 +	{ "aliceblue", NSVG_RGB(240, 248, 255) },
 28.1255 +	{ "antiquewhite", NSVG_RGB(250, 235, 215) },
 28.1256 +	{ "aqua", NSVG_RGB( 0, 255, 255) },
 28.1257 +	{ "aquamarine", NSVG_RGB(127, 255, 212) },
 28.1258 +	{ "azure", NSVG_RGB(240, 255, 255) },
 28.1259 +	{ "beige", NSVG_RGB(245, 245, 220) },
 28.1260 +	{ "bisque", NSVG_RGB(255, 228, 196) },
 28.1261 +	{ "blanchedalmond", NSVG_RGB(255, 235, 205) },
 28.1262 +	{ "blueviolet", NSVG_RGB(138, 43, 226) },
 28.1263 +	{ "brown", NSVG_RGB(165, 42, 42) },
 28.1264 +	{ "burlywood", NSVG_RGB(222, 184, 135) },
 28.1265 +	{ "cadetblue", NSVG_RGB( 95, 158, 160) },
 28.1266 +	{ "chartreuse", NSVG_RGB(127, 255, 0) },
 28.1267 +	{ "chocolate", NSVG_RGB(210, 105, 30) },
 28.1268 +	{ "coral", NSVG_RGB(255, 127, 80) },
 28.1269 +	{ "cornflowerblue", NSVG_RGB(100, 149, 237) },
 28.1270 +	{ "cornsilk", NSVG_RGB(255, 248, 220) },
 28.1271 +	{ "crimson", NSVG_RGB(220, 20, 60) },
 28.1272 +	{ "darkblue", NSVG_RGB( 0, 0, 139) },
 28.1273 +	{ "darkcyan", NSVG_RGB( 0, 139, 139) },
 28.1274 +	{ "darkgoldenrod", NSVG_RGB(184, 134, 11) },
 28.1275 +	{ "darkgray", NSVG_RGB(169, 169, 169) },
 28.1276 +	{ "darkgreen", NSVG_RGB( 0, 100, 0) },
 28.1277 +	{ "darkgrey", NSVG_RGB(169, 169, 169) },
 28.1278 +	{ "darkkhaki", NSVG_RGB(189, 183, 107) },
 28.1279 +	{ "darkmagenta", NSVG_RGB(139, 0, 139) },
 28.1280 +	{ "darkolivegreen", NSVG_RGB( 85, 107, 47) },
 28.1281 +	{ "darkorange", NSVG_RGB(255, 140, 0) },
 28.1282 +	{ "darkorchid", NSVG_RGB(153, 50, 204) },
 28.1283 +	{ "darkred", NSVG_RGB(139, 0, 0) },
 28.1284 +	{ "darksalmon", NSVG_RGB(233, 150, 122) },
 28.1285 +	{ "darkseagreen", NSVG_RGB(143, 188, 143) },
 28.1286 +	{ "darkslateblue", NSVG_RGB( 72, 61, 139) },
 28.1287 +	{ "darkslategray", NSVG_RGB( 47, 79, 79) },
 28.1288 +	{ "darkslategrey", NSVG_RGB( 47, 79, 79) },
 28.1289 +	{ "darkturquoise", NSVG_RGB( 0, 206, 209) },
 28.1290 +	{ "darkviolet", NSVG_RGB(148, 0, 211) },
 28.1291 +	{ "deeppink", NSVG_RGB(255, 20, 147) },
 28.1292 +	{ "deepskyblue", NSVG_RGB( 0, 191, 255) },
 28.1293 +	{ "dimgray", NSVG_RGB(105, 105, 105) },
 28.1294 +	{ "dimgrey", NSVG_RGB(105, 105, 105) },
 28.1295 +	{ "dodgerblue", NSVG_RGB( 30, 144, 255) },
 28.1296 +	{ "firebrick", NSVG_RGB(178, 34, 34) },
 28.1297 +	{ "floralwhite", NSVG_RGB(255, 250, 240) },
 28.1298 +	{ "forestgreen", NSVG_RGB( 34, 139, 34) },
 28.1299 +	{ "fuchsia", NSVG_RGB(255, 0, 255) },
 28.1300 +	{ "gainsboro", NSVG_RGB(220, 220, 220) },
 28.1301 +	{ "ghostwhite", NSVG_RGB(248, 248, 255) },
 28.1302 +	{ "gold", NSVG_RGB(255, 215, 0) },
 28.1303 +	{ "goldenrod", NSVG_RGB(218, 165, 32) },
 28.1304 +	{ "greenyellow", NSVG_RGB(173, 255, 47) },
 28.1305 +	{ "honeydew", NSVG_RGB(240, 255, 240) },
 28.1306 +	{ "hotpink", NSVG_RGB(255, 105, 180) },
 28.1307 +	{ "indianred", NSVG_RGB(205, 92, 92) },
 28.1308 +	{ "indigo", NSVG_RGB( 75, 0, 130) },
 28.1309 +	{ "ivory", NSVG_RGB(255, 255, 240) },
 28.1310 +	{ "khaki", NSVG_RGB(240, 230, 140) },
 28.1311 +	{ "lavender", NSVG_RGB(230, 230, 250) },
 28.1312 +	{ "lavenderblush", NSVG_RGB(255, 240, 245) },
 28.1313 +	{ "lawngreen", NSVG_RGB(124, 252, 0) },
 28.1314 +	{ "lemonchiffon", NSVG_RGB(255, 250, 205) },
 28.1315 +	{ "lightblue", NSVG_RGB(173, 216, 230) },
 28.1316 +	{ "lightcoral", NSVG_RGB(240, 128, 128) },
 28.1317 +	{ "lightcyan", NSVG_RGB(224, 255, 255) },
 28.1318 +	{ "lightgoldenrodyellow", NSVG_RGB(250, 250, 210) },
 28.1319 +	{ "lightgray", NSVG_RGB(211, 211, 211) },
 28.1320 +	{ "lightgreen", NSVG_RGB(144, 238, 144) },
 28.1321 +	{ "lightgrey", NSVG_RGB(211, 211, 211) },
 28.1322 +	{ "lightpink", NSVG_RGB(255, 182, 193) },
 28.1323 +	{ "lightsalmon", NSVG_RGB(255, 160, 122) },
 28.1324 +	{ "lightseagreen", NSVG_RGB( 32, 178, 170) },
 28.1325 +	{ "lightskyblue", NSVG_RGB(135, 206, 250) },
 28.1326 +	{ "lightslategray", NSVG_RGB(119, 136, 153) },
 28.1327 +	{ "lightslategrey", NSVG_RGB(119, 136, 153) },
 28.1328 +	{ "lightsteelblue", NSVG_RGB(176, 196, 222) },
 28.1329 +	{ "lightyellow", NSVG_RGB(255, 255, 224) },
 28.1330 +	{ "lime", NSVG_RGB( 0, 255, 0) },
 28.1331 +	{ "limegreen", NSVG_RGB( 50, 205, 50) },
 28.1332 +	{ "linen", NSVG_RGB(250, 240, 230) },
 28.1333 +	{ "maroon", NSVG_RGB(128, 0, 0) },
 28.1334 +	{ "mediumaquamarine", NSVG_RGB(102, 205, 170) },
 28.1335 +	{ "mediumblue", NSVG_RGB( 0, 0, 205) },
 28.1336 +	{ "mediumorchid", NSVG_RGB(186, 85, 211) },
 28.1337 +	{ "mediumpurple", NSVG_RGB(147, 112, 219) },
 28.1338 +	{ "mediumseagreen", NSVG_RGB( 60, 179, 113) },
 28.1339 +	{ "mediumslateblue", NSVG_RGB(123, 104, 238) },
 28.1340 +	{ "mediumspringgreen", NSVG_RGB( 0, 250, 154) },
 28.1341 +	{ "mediumturquoise", NSVG_RGB( 72, 209, 204) },
 28.1342 +	{ "mediumvioletred", NSVG_RGB(199, 21, 133) },
 28.1343 +	{ "midnightblue", NSVG_RGB( 25, 25, 112) },
 28.1344 +	{ "mintcream", NSVG_RGB(245, 255, 250) },
 28.1345 +	{ "mistyrose", NSVG_RGB(255, 228, 225) },
 28.1346 +	{ "moccasin", NSVG_RGB(255, 228, 181) },
 28.1347 +	{ "navajowhite", NSVG_RGB(255, 222, 173) },
 28.1348 +	{ "navy", NSVG_RGB( 0, 0, 128) },
 28.1349 +	{ "oldlace", NSVG_RGB(253, 245, 230) },
 28.1350 +	{ "olive", NSVG_RGB(128, 128, 0) },
 28.1351 +	{ "olivedrab", NSVG_RGB(107, 142, 35) },
 28.1352 +	{ "orange", NSVG_RGB(255, 165, 0) },
 28.1353 +	{ "orangered", NSVG_RGB(255, 69, 0) },
 28.1354 +	{ "orchid", NSVG_RGB(218, 112, 214) },
 28.1355 +	{ "palegoldenrod", NSVG_RGB(238, 232, 170) },
 28.1356 +	{ "palegreen", NSVG_RGB(152, 251, 152) },
 28.1357 +	{ "paleturquoise", NSVG_RGB(175, 238, 238) },
 28.1358 +	{ "palevioletred", NSVG_RGB(219, 112, 147) },
 28.1359 +	{ "papayawhip", NSVG_RGB(255, 239, 213) },
 28.1360 +	{ "peachpuff", NSVG_RGB(255, 218, 185) },
 28.1361 +	{ "peru", NSVG_RGB(205, 133, 63) },
 28.1362 +	{ "pink", NSVG_RGB(255, 192, 203) },
 28.1363 +	{ "plum", NSVG_RGB(221, 160, 221) },
 28.1364 +	{ "powderblue", NSVG_RGB(176, 224, 230) },
 28.1365 +	{ "purple", NSVG_RGB(128, 0, 128) },
 28.1366 +	{ "rosybrown", NSVG_RGB(188, 143, 143) },
 28.1367 +	{ "royalblue", NSVG_RGB( 65, 105, 225) },
 28.1368 +	{ "saddlebrown", NSVG_RGB(139, 69, 19) },
 28.1369 +	{ "salmon", NSVG_RGB(250, 128, 114) },
 28.1370 +	{ "sandybrown", NSVG_RGB(244, 164, 96) },
 28.1371 +	{ "seagreen", NSVG_RGB( 46, 139, 87) },
 28.1372 +	{ "seashell", NSVG_RGB(255, 245, 238) },
 28.1373 +	{ "sienna", NSVG_RGB(160, 82, 45) },
 28.1374 +	{ "silver", NSVG_RGB(192, 192, 192) },
 28.1375 +	{ "skyblue", NSVG_RGB(135, 206, 235) },
 28.1376 +	{ "slateblue", NSVG_RGB(106, 90, 205) },
 28.1377 +	{ "slategray", NSVG_RGB(112, 128, 144) },
 28.1378 +	{ "slategrey", NSVG_RGB(112, 128, 144) },
 28.1379 +	{ "snow", NSVG_RGB(255, 250, 250) },
 28.1380 +	{ "springgreen", NSVG_RGB( 0, 255, 127) },
 28.1381 +	{ "steelblue", NSVG_RGB( 70, 130, 180) },
 28.1382 +	{ "tan", NSVG_RGB(210, 180, 140) },
 28.1383 +	{ "teal", NSVG_RGB( 0, 128, 128) },
 28.1384 +	{ "thistle", NSVG_RGB(216, 191, 216) },
 28.1385 +	{ "tomato", NSVG_RGB(255, 99, 71) },
 28.1386 +	{ "turquoise", NSVG_RGB( 64, 224, 208) },
 28.1387 +	{ "violet", NSVG_RGB(238, 130, 238) },
 28.1388 +	{ "wheat", NSVG_RGB(245, 222, 179) },
 28.1389 +	{ "whitesmoke", NSVG_RGB(245, 245, 245) },
 28.1390 +	{ "yellowgreen", NSVG_RGB(154, 205, 50) },
 28.1391 +#endif
 28.1392 +};
 28.1393 +
 28.1394 +static unsigned int nsvg__parseColorName(const char* str)
 28.1395 +{
 28.1396 +	int i, ncolors = sizeof(nsvg__colors) / sizeof(NSVGNamedColor);
 28.1397 +
 28.1398 +	for (i = 0; i < ncolors; i++) {
 28.1399 +		if (strcmp(nsvg__colors[i].name, str) == 0) {
 28.1400 +			return nsvg__colors[i].color;
 28.1401 +		}
 28.1402 +	}
 28.1403 +
 28.1404 +	return NSVG_RGB(128, 128, 128);
 28.1405 +}
 28.1406 +
 28.1407 +static unsigned int nsvg__parseColor(const char* str)
 28.1408 +{
 28.1409 +	size_t len = 0;
 28.1410 +	while(*str == ' ') ++str;
 28.1411 +	len = strlen(str);
 28.1412 +	if (len >= 1 && *str == '#')
 28.1413 +		return nsvg__parseColorHex(str);
 28.1414 +	else if (len >= 4 && str[0] == 'r' && str[1] == 'g' && str[2] == 'b' && str[3] == '(')
 28.1415 +		return nsvg__parseColorRGB(str);
 28.1416 +	return nsvg__parseColorName(str);
 28.1417 +}
 28.1418 +
 28.1419 +static float nsvg__parseOpacity(const char* str)
 28.1420 +{
 28.1421 +	float val = 0;
 28.1422 +	sscanf(str, "%f", &val);
 28.1423 +	if (val < 0.0f) val = 0.0f;
 28.1424 +	if (val > 1.0f) val = 1.0f;
 28.1425 +	return val;
 28.1426 +}
 28.1427 +
 28.1428 +static float nsvg__parseMiterLimit(const char* str)
 28.1429 +{
 28.1430 +	float val = 0;
 28.1431 +	sscanf(str, "%f", &val);
 28.1432 +	if (val < 0.0f) val = 0.0f;
 28.1433 +	return val;
 28.1434 +}
 28.1435 +
 28.1436 +static int nsvg__parseUnits(const char* units)
 28.1437 +{
 28.1438 +	if (units[0] == 'p' && units[1] == 'x')
 28.1439 +		return NSVG_UNITS_PX;
 28.1440 +	else if (units[0] == 'p' && units[1] == 't')
 28.1441 +		return NSVG_UNITS_PT;
 28.1442 +	else if (units[0] == 'p' && units[1] == 'c')
 28.1443 +		return NSVG_UNITS_PC;
 28.1444 +	else if (units[0] == 'm' && units[1] == 'm')
 28.1445 +		return NSVG_UNITS_MM;
 28.1446 +	else if (units[0] == 'c' && units[1] == 'm')
 28.1447 +		return NSVG_UNITS_CM;
 28.1448 +	else if (units[0] == 'i' && units[1] == 'n')
 28.1449 +		return NSVG_UNITS_IN;
 28.1450 +	else if (units[0] == '%')
 28.1451 +		return NSVG_UNITS_PERCENT;
 28.1452 +	else if (units[0] == 'e' && units[1] == 'm')
 28.1453 +		return NSVG_UNITS_EM;
 28.1454 +	else if (units[0] == 'e' && units[1] == 'x')
 28.1455 +		return NSVG_UNITS_EX;
 28.1456 +	return NSVG_UNITS_USER;
 28.1457 +}
 28.1458 +
 28.1459 +static NSVGcoordinate nsvg__parseCoordinateRaw(const char* str)
 28.1460 +{
 28.1461 +	NSVGcoordinate coord = {0, NSVG_UNITS_USER};
 28.1462 +	char units[32]="";
 28.1463 +	sscanf(str, "%f%31s", &coord.value, units);
 28.1464 +	coord.units = nsvg__parseUnits(units);
 28.1465 +	return coord;
 28.1466 +}
 28.1467 +
 28.1468 +static NSVGcoordinate nsvg__coord(float v, int units)
 28.1469 +{
 28.1470 +	NSVGcoordinate coord = {v, units};
 28.1471 +	return coord;
 28.1472 +}
 28.1473 +
 28.1474 +static float nsvg__parseCoordinate(NSVGparser* p, const char* str, float orig, float length)
 28.1475 +{
 28.1476 +	NSVGcoordinate coord = nsvg__parseCoordinateRaw(str);
 28.1477 +	return nsvg__convertToPixels(p, coord, orig, length);
 28.1478 +}
 28.1479 +
 28.1480 +static int nsvg__parseTransformArgs(const char* str, float* args, int maxNa, int* na)
 28.1481 +{
 28.1482 +	const char* end;
 28.1483 +	const char* ptr;
 28.1484 +	char it[64];
 28.1485 +
 28.1486 +	*na = 0;
 28.1487 +	ptr = str;
 28.1488 +	while (*ptr && *ptr != '(') ++ptr;
 28.1489 +	if (*ptr == 0)
 28.1490 +		return 1;
 28.1491 +	end = ptr;
 28.1492 +	while (*end && *end != ')') ++end;
 28.1493 +	if (*end == 0)
 28.1494 +		return 1;
 28.1495 +
 28.1496 +	while (ptr < end) {
 28.1497 +		if (*ptr == '-' || *ptr == '+' || *ptr == '.' || nsvg__isdigit(*ptr)) {
 28.1498 +			if (*na >= maxNa) return 0;
 28.1499 +			ptr = nsvg__parseNumber(ptr, it, 64);
 28.1500 +			args[(*na)++] = (float)nsvg__atof(it);
 28.1501 +		} else {
 28.1502 +			++ptr;
 28.1503 +		}
 28.1504 +	}
 28.1505 +	return (int)(end - str);
 28.1506 +}
 28.1507 +
 28.1508 +
 28.1509 +static int nsvg__parseMatrix(float* xform, const char* str)
 28.1510 +{
 28.1511 +	float t[6];
 28.1512 +	int na = 0;
 28.1513 +	int len = nsvg__parseTransformArgs(str, t, 6, &na);
 28.1514 +	if (na != 6) return len;
 28.1515 +	memcpy(xform, t, sizeof(float)*6);
 28.1516 +	return len;
 28.1517 +}
 28.1518 +
 28.1519 +static int nsvg__parseTranslate(float* xform, const char* str)
 28.1520 +{
 28.1521 +	float args[2];
 28.1522 +	float t[6];
 28.1523 +	int na = 0;
 28.1524 +	int len = nsvg__parseTransformArgs(str, args, 2, &na);
 28.1525 +	if (na == 1) args[1] = 0.0;
 28.1526 +
 28.1527 +	nsvg__xformSetTranslation(t, args[0], args[1]);
 28.1528 +	memcpy(xform, t, sizeof(float)*6);
 28.1529 +	return len;
 28.1530 +}
 28.1531 +
 28.1532 +static int nsvg__parseScale(float* xform, const char* str)
 28.1533 +{
 28.1534 +	float args[2];
 28.1535 +	int na = 0;
 28.1536 +	float t[6];
 28.1537 +	int len = nsvg__parseTransformArgs(str, args, 2, &na);
 28.1538 +	if (na == 1) args[1] = args[0];
 28.1539 +	nsvg__xformSetScale(t, args[0], args[1]);
 28.1540 +	memcpy(xform, t, sizeof(float)*6);
 28.1541 +	return len;
 28.1542 +}
 28.1543 +
 28.1544 +static int nsvg__parseSkewX(float* xform, const char* str)
 28.1545 +{
 28.1546 +	float args[1];
 28.1547 +	int na = 0;
 28.1548 +	float t[6];
 28.1549 +	int len = nsvg__parseTransformArgs(str, args, 1, &na);
 28.1550 +	nsvg__xformSetSkewX(t, args[0]/180.0f*NSVG_PI);
 28.1551 +	memcpy(xform, t, sizeof(float)*6);
 28.1552 +	return len;
 28.1553 +}
 28.1554 +
 28.1555 +static int nsvg__parseSkewY(float* xform, const char* str)
 28.1556 +{
 28.1557 +	float args[1];
 28.1558 +	int na = 0;
 28.1559 +	float t[6];
 28.1560 +	int len = nsvg__parseTransformArgs(str, args, 1, &na);
 28.1561 +	nsvg__xformSetSkewY(t, args[0]/180.0f*NSVG_PI);
 28.1562 +	memcpy(xform, t, sizeof(float)*6);
 28.1563 +	return len;
 28.1564 +}
 28.1565 +
 28.1566 +static int nsvg__parseRotate(float* xform, const char* str)
 28.1567 +{
 28.1568 +	float args[3];
 28.1569 +	int na = 0;
 28.1570 +	float m[6];
 28.1571 +	float t[6];
 28.1572 +	int len = nsvg__parseTransformArgs(str, args, 3, &na);
 28.1573 +	if (na == 1)
 28.1574 +		args[1] = args[2] = 0.0f;
 28.1575 +	nsvg__xformIdentity(m);
 28.1576 +
 28.1577 +	if (na > 1) {
 28.1578 +		nsvg__xformSetTranslation(t, -args[1], -args[2]);
 28.1579 +		nsvg__xformMultiply(m, t);
 28.1580 +	}
 28.1581 +
 28.1582 +	nsvg__xformSetRotation(t, args[0]/180.0f*NSVG_PI);
 28.1583 +	nsvg__xformMultiply(m, t);
 28.1584 +
 28.1585 +	if (na > 1) {
 28.1586 +		nsvg__xformSetTranslation(t, args[1], args[2]);
 28.1587 +		nsvg__xformMultiply(m, t);
 28.1588 +	}
 28.1589 +
 28.1590 +	memcpy(xform, m, sizeof(float)*6);
 28.1591 +
 28.1592 +	return len;
 28.1593 +}
 28.1594 +
 28.1595 +static void nsvg__parseTransform(float* xform, const char* str)
 28.1596 +{
 28.1597 +	float t[6];
 28.1598 +	nsvg__xformIdentity(xform);
 28.1599 +	while (*str)
 28.1600 +	{
 28.1601 +		if (strncmp(str, "matrix", 6) == 0)
 28.1602 +			str += nsvg__parseMatrix(t, str);
 28.1603 +		else if (strncmp(str, "translate", 9) == 0)
 28.1604 +			str += nsvg__parseTranslate(t, str);
 28.1605 +		else if (strncmp(str, "scale", 5) == 0)
 28.1606 +			str += nsvg__parseScale(t, str);
 28.1607 +		else if (strncmp(str, "rotate", 6) == 0)
 28.1608 +			str += nsvg__parseRotate(t, str);
 28.1609 +		else if (strncmp(str, "skewX", 5) == 0)
 28.1610 +			str += nsvg__parseSkewX(t, str);
 28.1611 +		else if (strncmp(str, "skewY", 5) == 0)
 28.1612 +			str += nsvg__parseSkewY(t, str);
 28.1613 +		else{
 28.1614 +			++str;
 28.1615 +			continue;
 28.1616 +		}
 28.1617 +
 28.1618 +		nsvg__xformPremultiply(xform, t);
 28.1619 +	}
 28.1620 +}
 28.1621 +
 28.1622 +static void nsvg__parseUrl(char* id, const char* str)
 28.1623 +{
 28.1624 +	int i = 0;
 28.1625 +	str += 4; // "url(";
 28.1626 +	if (*str == '#')
 28.1627 +		str++;
 28.1628 +	while (i < 63 && *str != ')') {
 28.1629 +		id[i] = *str++;
 28.1630 +		i++;
 28.1631 +	}
 28.1632 +	id[i] = '\0';
 28.1633 +}
 28.1634 +
 28.1635 +static char nsvg__parseLineCap(const char* str)
 28.1636 +{
 28.1637 +	if (strcmp(str, "butt") == 0)
 28.1638 +		return NSVG_CAP_BUTT;
 28.1639 +	else if (strcmp(str, "round") == 0)
 28.1640 +		return NSVG_CAP_ROUND;
 28.1641 +	else if (strcmp(str, "square") == 0)
 28.1642 +		return NSVG_CAP_SQUARE;
 28.1643 +	// TODO: handle inherit.
 28.1644 +	return NSVG_CAP_BUTT;
 28.1645 +}
 28.1646 +
 28.1647 +static char nsvg__parseLineJoin(const char* str)
 28.1648 +{
 28.1649 +	if (strcmp(str, "miter") == 0)
 28.1650 +		return NSVG_JOIN_MITER;
 28.1651 +	else if (strcmp(str, "round") == 0)
 28.1652 +		return NSVG_JOIN_ROUND;
 28.1653 +	else if (strcmp(str, "bevel") == 0)
 28.1654 +		return NSVG_JOIN_BEVEL;
 28.1655 +	// TODO: handle inherit.
 28.1656 +	return NSVG_CAP_BUTT;
 28.1657 +}
 28.1658 +
 28.1659 +static char nsvg__parseFillRule(const char* str)
 28.1660 +{
 28.1661 +	if (strcmp(str, "nonzero") == 0)
 28.1662 +		return NSVG_FILLRULE_NONZERO;
 28.1663 +	else if (strcmp(str, "evenodd") == 0)
 28.1664 +		return NSVG_FILLRULE_EVENODD;
 28.1665 +	// TODO: handle inherit.
 28.1666 +	return NSVG_FILLRULE_NONZERO;
 28.1667 +}
 28.1668 +
 28.1669 +static const char* nsvg__getNextDashItem(const char* s, char* it)
 28.1670 +{
 28.1671 +	int n = 0;
 28.1672 +	it[0] = '\0';
 28.1673 +	// Skip white spaces and commas
 28.1674 +	while (*s && (nsvg__isspace(*s) || *s == ',')) s++;
 28.1675 +	// Advance until whitespace, comma or end.
 28.1676 +	while (*s && (!nsvg__isspace(*s) && *s != ',')) {
 28.1677 +		if (n < 63)
 28.1678 +			it[n++] = *s;
 28.1679 +		s++;
 28.1680 +	}
 28.1681 +	it[n++] = '\0';
 28.1682 +	return s;
 28.1683 +}
 28.1684 +
 28.1685 +static int nsvg__parseStrokeDashArray(NSVGparser* p, const char* str, float* strokeDashArray)
 28.1686 +{
 28.1687 +	char item[64];
 28.1688 +	int count = 0, i;
 28.1689 +	float sum = 0.0f;
 28.1690 +
 28.1691 +	// Handle "none"
 28.1692 +	if (str[0] == 'n')
 28.1693 +		return 0;
 28.1694 +
 28.1695 +	// Parse dashes
 28.1696 +	while (*str) {
 28.1697 +		str = nsvg__getNextDashItem(str, item);
 28.1698 +		if (!*item) break;
 28.1699 +		if (count < NSVG_MAX_DASHES)
 28.1700 +			strokeDashArray[count++] = fabsf(nsvg__parseCoordinate(p, item, 0.0f, nsvg__actualLength(p)));
 28.1701 +	}
 28.1702 +
 28.1703 +	for (i = 0; i < count; i++)
 28.1704 +		sum += strokeDashArray[i];
 28.1705 +	if (sum <= 1e-6f)
 28.1706 +		count = 0;
 28.1707 +
 28.1708 +	return count;
 28.1709 +}
 28.1710 +
 28.1711 +static void nsvg__parseStyle(NSVGparser* p, const char* str);
 28.1712 +
 28.1713 +static int nsvg__parseAttr(NSVGparser* p, const char* name, const char* value)
 28.1714 +{
 28.1715 +	float xform[6];
 28.1716 +	NSVGattrib* attr = nsvg__getAttr(p);
 28.1717 +	if (!attr) return 0;
 28.1718 +
 28.1719 +	if (strcmp(name, "style") == 0) {
 28.1720 +		nsvg__parseStyle(p, value);
 28.1721 +	} else if (strcmp(name, "display") == 0) {
 28.1722 +		if (strcmp(value, "none") == 0)
 28.1723 +			attr->visible = 0;
 28.1724 +		// Don't reset ->visible on display:inline, one display:none hides the whole subtree
 28.1725 +
 28.1726 +	} else if (strcmp(name, "fill") == 0) {
 28.1727 +		if (strcmp(value, "none") == 0) {
 28.1728 +			attr->hasFill = 0;
 28.1729 +		} else if (strncmp(value, "url(", 4) == 0) {
 28.1730 +			attr->hasFill = 2;
 28.1731 +			nsvg__parseUrl(attr->fillGradient, value);
 28.1732 +		} else {
 28.1733 +			attr->hasFill = 1;
 28.1734 +			attr->fillColor = nsvg__parseColor(value);
 28.1735 +		}
 28.1736 +	} else if (strcmp(name, "opacity") == 0) {
 28.1737 +		attr->opacity = nsvg__parseOpacity(value);
 28.1738 +	} else if (strcmp(name, "fill-opacity") == 0) {
 28.1739 +		attr->fillOpacity = nsvg__parseOpacity(value);
 28.1740 +	} else if (strcmp(name, "stroke") == 0) {
 28.1741 +		if (strcmp(value, "none") == 0) {
 28.1742 +			attr->hasStroke = 0;
 28.1743 +		} else if (strncmp(value, "url(", 4) == 0) {
 28.1744 +			attr->hasStroke = 2;
 28.1745 +			nsvg__parseUrl(attr->strokeGradient, value);
 28.1746 +		} else {
 28.1747 +			attr->hasStroke = 1;
 28.1748 +			attr->strokeColor = nsvg__parseColor(value);
 28.1749 +		}
 28.1750 +	} else if (strcmp(name, "stroke-width") == 0) {
 28.1751 +		attr->strokeWidth = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
 28.1752 +	} else if (strcmp(name, "stroke-dasharray") == 0) {
 28.1753 +		attr->strokeDashCount = nsvg__parseStrokeDashArray(p, value, attr->strokeDashArray);
 28.1754 +	} else if (strcmp(name, "stroke-dashoffset") == 0) {
 28.1755 +		attr->strokeDashOffset = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
 28.1756 +	} else if (strcmp(name, "stroke-opacity") == 0) {
 28.1757 +		attr->strokeOpacity = nsvg__parseOpacity(value);
 28.1758 +	} else if (strcmp(name, "stroke-linecap") == 0) {
 28.1759 +		attr->strokeLineCap = nsvg__parseLineCap(value);
 28.1760 +	} else if (strcmp(name, "stroke-linejoin") == 0) {
 28.1761 +		attr->strokeLineJoin = nsvg__parseLineJoin(value);
 28.1762 +	} else if (strcmp(name, "stroke-miterlimit") == 0) {
 28.1763 +		attr->miterLimit = nsvg__parseMiterLimit(value);
 28.1764 +	} else if (strcmp(name, "fill-rule") == 0) {
 28.1765 +		attr->fillRule = nsvg__parseFillRule(value);
 28.1766 +	} else if (strcmp(name, "font-size") == 0) {
 28.1767 +		attr->fontSize = nsvg__parseCoordinate(p, value, 0.0f, nsvg__actualLength(p));
 28.1768 +	} else if (strcmp(name, "transform") == 0) {
 28.1769 +		nsvg__parseTransform(xform, value);
 28.1770 +		nsvg__xformPremultiply(attr->xform, xform);
 28.1771 +	} else if (strcmp(name, "stop-color") == 0) {
 28.1772 +		attr->stopColor = nsvg__parseColor(value);
 28.1773 +	} else if (strcmp(name, "stop-opacity") == 0) {
 28.1774 +		attr->stopOpacity = nsvg__parseOpacity(value);
 28.1775 +	} else if (strcmp(name, "offset") == 0) {
 28.1776 +		attr->stopOffset = nsvg__parseCoordinate(p, value, 0.0f, 1.0f);
 28.1777 +	} else if (strcmp(name, "id") == 0) {
 28.1778 +		strncpy(attr->id, value, 63);
 28.1779 +		attr->id[63] = '\0';
 28.1780 +	} else {
 28.1781 +		return 0;
 28.1782 +	}
 28.1783 +	return 1;
 28.1784 +}
 28.1785 +
 28.1786 +static int nsvg__parseNameValue(NSVGparser* p, const char* start, const char* end)
 28.1787 +{
 28.1788 +	const char* str;
 28.1789 +	const char* val;
 28.1790 +	char name[512];
 28.1791 +	char value[512];
 28.1792 +	int n;
 28.1793 +
 28.1794 +	str = start;
 28.1795 +	while (str < end && *str != ':') ++str;
 28.1796 +
 28.1797 +	val = str;
 28.1798 +
 28.1799 +	// Right Trim
 28.1800 +	while (str > start &&  (*str == ':' || nsvg__isspace(*str))) --str;
 28.1801 +	++str;
 28.1802 +
 28.1803 +	n = (int)(str - start);
 28.1804 +	if (n > 511) n = 511;
 28.1805 +	if (n) memcpy(name, start, n);
 28.1806 +	name[n] = 0;
 28.1807 +
 28.1808 +	while (val < end && (*val == ':' || nsvg__isspace(*val))) ++val;
 28.1809 +
 28.1810 +	n = (int)(end - val);
 28.1811 +	if (n > 511) n = 511;
 28.1812 +	if (n) memcpy(value, val, n);
 28.1813 +	value[n] = 0;
 28.1814 +
 28.1815 +	return nsvg__parseAttr(p, name, value);
 28.1816 +}
 28.1817 +
 28.1818 +static void nsvg__parseStyle(NSVGparser* p, const char* str)
 28.1819 +{
 28.1820 +	const char* start;
 28.1821 +	const char* end;
 28.1822 +
 28.1823 +	while (*str) {
 28.1824 +		// Left Trim
 28.1825 +		while(*str && nsvg__isspace(*str)) ++str;
 28.1826 +		start = str;
 28.1827 +		while(*str && *str != ';') ++str;
 28.1828 +		end = str;
 28.1829 +
 28.1830 +		// Right Trim
 28.1831 +		while (end > start &&  (*end == ';' || nsvg__isspace(*end))) --end;
 28.1832 +		++end;
 28.1833 +
 28.1834 +		nsvg__parseNameValue(p, start, end);
 28.1835 +		if (*str) ++str;
 28.1836 +	}
 28.1837 +}
 28.1838 +
 28.1839 +static void nsvg__parseAttribs(NSVGparser* p, const char** attr)
 28.1840 +{
 28.1841 +	int i;
 28.1842 +	for (i = 0; attr[i]; i += 2)
 28.1843 +	{
 28.1844 +		if (strcmp(attr[i], "style") == 0)
 28.1845 +			nsvg__parseStyle(p, attr[i + 1]);
 28.1846 +		else
 28.1847 +			nsvg__parseAttr(p, attr[i], attr[i + 1]);
 28.1848 +	}
 28.1849 +}
 28.1850 +
 28.1851 +static int nsvg__getArgsPerElement(char cmd)
 28.1852 +{
 28.1853 +	switch (cmd) {
 28.1854 +		case 'v':
 28.1855 +		case 'V':
 28.1856 +		case 'h':
 28.1857 +		case 'H':
 28.1858 +			return 1;
 28.1859 +		case 'm':
 28.1860 +		case 'M':
 28.1861 +		case 'l':
 28.1862 +		case 'L':
 28.1863 +		case 't':
 28.1864 +		case 'T':
 28.1865 +			return 2;
 28.1866 +		case 'q':
 28.1867 +		case 'Q':
 28.1868 +		case 's':
 28.1869 +		case 'S':
 28.1870 +			return 4;
 28.1871 +		case 'c':
 28.1872 +		case 'C':
 28.1873 +			return 6;
 28.1874 +		case 'a':
 28.1875 +		case 'A':
 28.1876 +			return 7;
 28.1877 +	}
 28.1878 +	return 0;
 28.1879 +}
 28.1880 +
 28.1881 +static void nsvg__pathMoveTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
 28.1882 +{
 28.1883 +	if (rel) {
 28.1884 +		*cpx += args[0];
 28.1885 +		*cpy += args[1];
 28.1886 +	} else {
 28.1887 +		*cpx = args[0];
 28.1888 +		*cpy = args[1];
 28.1889 +	}
 28.1890 +	nsvg__moveTo(p, *cpx, *cpy);
 28.1891 +}
 28.1892 +
 28.1893 +static void nsvg__pathLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
 28.1894 +{
 28.1895 +	if (rel) {
 28.1896 +		*cpx += args[0];
 28.1897 +		*cpy += args[1];
 28.1898 +	} else {
 28.1899 +		*cpx = args[0];
 28.1900 +		*cpy = args[1];
 28.1901 +	}
 28.1902 +	nsvg__lineTo(p, *cpx, *cpy);
 28.1903 +}
 28.1904 +
 28.1905 +static void nsvg__pathHLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
 28.1906 +{
 28.1907 +	if (rel)
 28.1908 +		*cpx += args[0];
 28.1909 +	else
 28.1910 +		*cpx = args[0];
 28.1911 +	nsvg__lineTo(p, *cpx, *cpy);
 28.1912 +}
 28.1913 +
 28.1914 +static void nsvg__pathVLineTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
 28.1915 +{
 28.1916 +	if (rel)
 28.1917 +		*cpy += args[0];
 28.1918 +	else
 28.1919 +		*cpy = args[0];
 28.1920 +	nsvg__lineTo(p, *cpx, *cpy);
 28.1921 +}
 28.1922 +
 28.1923 +static void nsvg__pathCubicBezTo(NSVGparser* p, float* cpx, float* cpy,
 28.1924 +								 float* cpx2, float* cpy2, float* args, int rel)
 28.1925 +{
 28.1926 +	float x2, y2, cx1, cy1, cx2, cy2;
 28.1927 +
 28.1928 +	if (rel) {
 28.1929 +		cx1 = *cpx + args[0];
 28.1930 +		cy1 = *cpy + args[1];
 28.1931 +		cx2 = *cpx + args[2];
 28.1932 +		cy2 = *cpy + args[3];
 28.1933 +		x2 = *cpx + args[4];
 28.1934 +		y2 = *cpy + args[5];
 28.1935 +	} else {
 28.1936 +		cx1 = args[0];
 28.1937 +		cy1 = args[1];
 28.1938 +		cx2 = args[2];
 28.1939 +		cy2 = args[3];
 28.1940 +		x2 = args[4];
 28.1941 +		y2 = args[5];
 28.1942 +	}
 28.1943 +
 28.1944 +	nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
 28.1945 +
 28.1946 +	*cpx2 = cx2;
 28.1947 +	*cpy2 = cy2;
 28.1948 +	*cpx = x2;
 28.1949 +	*cpy = y2;
 28.1950 +}
 28.1951 +
 28.1952 +static void nsvg__pathCubicBezShortTo(NSVGparser* p, float* cpx, float* cpy,
 28.1953 +									  float* cpx2, float* cpy2, float* args, int rel)
 28.1954 +{
 28.1955 +	float x1, y1, x2, y2, cx1, cy1, cx2, cy2;
 28.1956 +
 28.1957 +	x1 = *cpx;
 28.1958 +	y1 = *cpy;
 28.1959 +	if (rel) {
 28.1960 +		cx2 = *cpx + args[0];
 28.1961 +		cy2 = *cpy + args[1];
 28.1962 +		x2 = *cpx + args[2];
 28.1963 +		y2 = *cpy + args[3];
 28.1964 +	} else {
 28.1965 +		cx2 = args[0];
 28.1966 +		cy2 = args[1];
 28.1967 +		x2 = args[2];
 28.1968 +		y2 = args[3];
 28.1969 +	}
 28.1970 +
 28.1971 +	cx1 = 2*x1 - *cpx2;
 28.1972 +	cy1 = 2*y1 - *cpy2;
 28.1973 +
 28.1974 +	nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
 28.1975 +
 28.1976 +	*cpx2 = cx2;
 28.1977 +	*cpy2 = cy2;
 28.1978 +	*cpx = x2;
 28.1979 +	*cpy = y2;
 28.1980 +}
 28.1981 +
 28.1982 +static void nsvg__pathQuadBezTo(NSVGparser* p, float* cpx, float* cpy,
 28.1983 +								float* cpx2, float* cpy2, float* args, int rel)
 28.1984 +{
 28.1985 +	float x1, y1, x2, y2, cx, cy;
 28.1986 +	float cx1, cy1, cx2, cy2;
 28.1987 +
 28.1988 +	x1 = *cpx;
 28.1989 +	y1 = *cpy;
 28.1990 +	if (rel) {
 28.1991 +		cx = *cpx + args[0];
 28.1992 +		cy = *cpy + args[1];
 28.1993 +		x2 = *cpx + args[2];
 28.1994 +		y2 = *cpy + args[3];
 28.1995 +	} else {
 28.1996 +		cx = args[0];
 28.1997 +		cy = args[1];
 28.1998 +		x2 = args[2];
 28.1999 +		y2 = args[3];
 28.2000 +	}
 28.2001 +
 28.2002 +	// Convert to cubic bezier
 28.2003 +	cx1 = x1 + 2.0f/3.0f*(cx - x1);
 28.2004 +	cy1 = y1 + 2.0f/3.0f*(cy - y1);
 28.2005 +	cx2 = x2 + 2.0f/3.0f*(cx - x2);
 28.2006 +	cy2 = y2 + 2.0f/3.0f*(cy - y2);
 28.2007 +
 28.2008 +	nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
 28.2009 +
 28.2010 +	*cpx2 = cx;
 28.2011 +	*cpy2 = cy;
 28.2012 +	*cpx = x2;
 28.2013 +	*cpy = y2;
 28.2014 +}
 28.2015 +
 28.2016 +static void nsvg__pathQuadBezShortTo(NSVGparser* p, float* cpx, float* cpy,
 28.2017 +									 float* cpx2, float* cpy2, float* args, int rel)
 28.2018 +{
 28.2019 +	float x1, y1, x2, y2, cx, cy;
 28.2020 +	float cx1, cy1, cx2, cy2;
 28.2021 +
 28.2022 +	x1 = *cpx;
 28.2023 +	y1 = *cpy;
 28.2024 +	if (rel) {
 28.2025 +		x2 = *cpx + args[0];
 28.2026 +		y2 = *cpy + args[1];
 28.2027 +	} else {
 28.2028 +		x2 = args[0];
 28.2029 +		y2 = args[1];
 28.2030 +	}
 28.2031 +
 28.2032 +	cx = 2*x1 - *cpx2;
 28.2033 +	cy = 2*y1 - *cpy2;
 28.2034 +
 28.2035 +	// Convert to cubix bezier
 28.2036 +	cx1 = x1 + 2.0f/3.0f*(cx - x1);
 28.2037 +	cy1 = y1 + 2.0f/3.0f*(cy - y1);
 28.2038 +	cx2 = x2 + 2.0f/3.0f*(cx - x2);
 28.2039 +	cy2 = y2 + 2.0f/3.0f*(cy - y2);
 28.2040 +
 28.2041 +	nsvg__cubicBezTo(p, cx1,cy1, cx2,cy2, x2,y2);
 28.2042 +
 28.2043 +	*cpx2 = cx;
 28.2044 +	*cpy2 = cy;
 28.2045 +	*cpx = x2;
 28.2046 +	*cpy = y2;
 28.2047 +}
 28.2048 +
 28.2049 +static float nsvg__sqr(float x) { return x*x; }
 28.2050 +static float nsvg__vmag(float x, float y) { return sqrtf(x*x + y*y); }
 28.2051 +
 28.2052 +static float nsvg__vecrat(float ux, float uy, float vx, float vy)
 28.2053 +{
 28.2054 +	return (ux*vx + uy*vy) / (nsvg__vmag(ux,uy) * nsvg__vmag(vx,vy));
 28.2055 +}
 28.2056 +
 28.2057 +static float nsvg__vecang(float ux, float uy, float vx, float vy)
 28.2058 +{
 28.2059 +	float r = nsvg__vecrat(ux,uy, vx,vy);
 28.2060 +	if (r < -1.0f) r = -1.0f;
 28.2061 +	if (r > 1.0f) r = 1.0f;
 28.2062 +	return ((ux*vy < uy*vx) ? -1.0f : 1.0f) * acosf(r);
 28.2063 +}
 28.2064 +
 28.2065 +static void nsvg__pathArcTo(NSVGparser* p, float* cpx, float* cpy, float* args, int rel)
 28.2066 +{
 28.2067 +	// Ported from canvg (https://code.google.com/p/canvg/)
 28.2068 +	float rx, ry, rotx;
 28.2069 +	float x1, y1, x2, y2, cx, cy, dx, dy, d;
 28.2070 +	float x1p, y1p, cxp, cyp, s, sa, sb;
 28.2071 +	float ux, uy, vx, vy, a1, da;
 28.2072 +	float x, y, tanx, tany, a, px = 0, py = 0, ptanx = 0, ptany = 0, t[6];
 28.2073 +	float sinrx, cosrx;
 28.2074 +	int fa, fs;
 28.2075 +	int i, ndivs;
 28.2076 +	float hda, kappa;
 28.2077 +
 28.2078 +	rx = fabsf(args[0]);				// y radius
 28.2079 +	ry = fabsf(args[1]);				// x radius
 28.2080 +	rotx = args[2] / 180.0f * NSVG_PI;		// x rotation angle
 28.2081 +	fa = fabsf(args[3]) > 1e-6 ? 1 : 0;	// Large arc
 28.2082 +	fs = fabsf(args[4]) > 1e-6 ? 1 : 0;	// Sweep direction
 28.2083 +	x1 = *cpx;							// start point
 28.2084 +	y1 = *cpy;
 28.2085 +	if (rel) {							// end point
 28.2086 +		x2 = *cpx + args[5];
 28.2087 +		y2 = *cpy + args[6];
 28.2088 +	} else {
 28.2089 +		x2 = args[5];
 28.2090 +		y2 = args[6];
 28.2091 +	}
 28.2092 +
 28.2093 +	dx = x1 - x2;
 28.2094 +	dy = y1 - y2;
 28.2095 +	d = sqrtf(dx*dx + dy*dy);
 28.2096 +	if (d < 1e-6f || rx < 1e-6f || ry < 1e-6f) {
 28.2097 +		// The arc degenerates to a line
 28.2098 +		nsvg__lineTo(p, x2, y2);
 28.2099 +		*cpx = x2;
 28.2100 +		*cpy = y2;
 28.2101 +		return;
 28.2102 +	}
 28.2103 +
 28.2104 +	sinrx = sinf(rotx);
 28.2105 +	cosrx = cosf(rotx);
 28.2106 +
 28.2107 +	// Convert to center point parameterization.
 28.2108 +	// http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes
 28.2109 +	// 1) Compute x1', y1'
 28.2110 +	x1p = cosrx * dx / 2.0f + sinrx * dy / 2.0f;
 28.2111 +	y1p = -sinrx * dx / 2.0f + cosrx * dy / 2.0f;
 28.2112 +	d = nsvg__sqr(x1p)/nsvg__sqr(rx) + nsvg__sqr(y1p)/nsvg__sqr(ry);
 28.2113 +	if (d > 1) {
 28.2114 +		d = sqrtf(d);
 28.2115 +		rx *= d;
 28.2116 +		ry *= d;
 28.2117 +	}
 28.2118 +	// 2) Compute cx', cy'
 28.2119 +	s = 0.0f;
 28.2120 +	sa = nsvg__sqr(rx)*nsvg__sqr(ry) - nsvg__sqr(rx)*nsvg__sqr(y1p) - nsvg__sqr(ry)*nsvg__sqr(x1p);
 28.2121 +	sb = nsvg__sqr(rx)*nsvg__sqr(y1p) + nsvg__sqr(ry)*nsvg__sqr(x1p);
 28.2122 +	if (sa < 0.0f) sa = 0.0f;
 28.2123 +	if (sb > 0.0f)
 28.2124 +		s = sqrtf(sa / sb);
 28.2125 +	if (fa == fs)
 28.2126 +		s = -s;
 28.2127 +	cxp = s * rx * y1p / ry;
 28.2128 +	cyp = s * -ry * x1p / rx;
 28.2129 +
 28.2130 +	// 3) Compute cx,cy from cx',cy'
 28.2131 +	cx = (x1 + x2)/2.0f + cosrx*cxp - sinrx*cyp;
 28.2132 +	cy = (y1 + y2)/2.0f + sinrx*cxp + cosrx*cyp;
 28.2133 +
 28.2134 +	// 4) Calculate theta1, and delta theta.
 28.2135 +	ux = (x1p - cxp) / rx;
 28.2136 +	uy = (y1p - cyp) / ry;
 28.2137 +	vx = (-x1p - cxp) / rx;
 28.2138 +	vy = (-y1p - cyp) / ry;
 28.2139 +	a1 = nsvg__vecang(1.0f,0.0f, ux,uy);	// Initial angle
 28.2140 +	da = nsvg__vecang(ux,uy, vx,vy);		// Delta angle
 28.2141 +
 28.2142 +//	if (vecrat(ux,uy,vx,vy) <= -1.0f) da = NSVG_PI;
 28.2143 +//	if (vecrat(ux,uy,vx,vy) >= 1.0f) da = 0;
 28.2144 +
 28.2145 +	if (fs == 0 && da > 0)
 28.2146 +		da -= 2 * NSVG_PI;
 28.2147 +	else if (fs == 1 && da < 0)
 28.2148 +		da += 2 * NSVG_PI;
 28.2149 +
 28.2150 +	// Approximate the arc using cubic spline segments.
 28.2151 +	t[0] = cosrx; t[1] = sinrx;
 28.2152 +	t[2] = -sinrx; t[3] = cosrx;
 28.2153 +	t[4] = cx; t[5] = cy;
 28.2154 +
 28.2155 +	// Split arc into max 90 degree segments.
 28.2156 +	// The loop assumes an iteration per end point (including start and end), this +1.
 28.2157 +	ndivs = (int)(fabsf(da) / (NSVG_PI*0.5f) + 1.0f);
 28.2158 +	hda = (da / (float)ndivs) / 2.0f;
 28.2159 +	kappa = fabsf(4.0f / 3.0f * (1.0f - cosf(hda)) / sinf(hda));
 28.2160 +	if (da < 0.0f)
 28.2161 +		kappa = -kappa;
 28.2162 +
 28.2163 +	for (i = 0; i <= ndivs; i++) {
 28.2164 +		a = a1 + da * ((float)i/(float)ndivs);
 28.2165 +		dx = cosf(a);
 28.2166 +		dy = sinf(a);
 28.2167 +		nsvg__xformPoint(&x, &y, dx*rx, dy*ry, t); // position
 28.2168 +		nsvg__xformVec(&tanx, &tany, -dy*rx * kappa, dx*ry * kappa, t); // tangent
 28.2169 +		if (i > 0)
 28.2170 +			nsvg__cubicBezTo(p, px+ptanx,py+ptany, x-tanx, y-tany, x, y);
 28.2171 +		px = x;
 28.2172 +		py = y;
 28.2173 +		ptanx = tanx;
 28.2174 +		ptany = tany;
 28.2175 +	}
 28.2176 +
 28.2177 +	*cpx = x2;
 28.2178 +	*cpy = y2;
 28.2179 +}
 28.2180 +
 28.2181 +static void nsvg__parsePath(NSVGparser* p, const char** attr)
 28.2182 +{
 28.2183 +	const char* s = NULL;
 28.2184 +	char cmd = '\0';
 28.2185 +	float args[10];
 28.2186 +	int nargs;
 28.2187 +	int rargs = 0;
 28.2188 +	float cpx, cpy, cpx2, cpy2;
 28.2189 +	const char* tmp[4];
 28.2190 +	char closedFlag;
 28.2191 +	int i;
 28.2192 +	char item[64];
 28.2193 +
 28.2194 +	for (i = 0; attr[i]; i += 2) {
 28.2195 +		if (strcmp(attr[i], "d") == 0) {
 28.2196 +			s = attr[i + 1];
 28.2197 +		} else {
 28.2198 +			tmp[0] = attr[i];
 28.2199 +			tmp[1] = attr[i + 1];
 28.2200 +			tmp[2] = 0;
 28.2201 +			tmp[3] = 0;
 28.2202 +			nsvg__parseAttribs(p, tmp);
 28.2203 +		}
 28.2204 +	}
 28.2205 +
 28.2206 +	if (s) {
 28.2207 +		nsvg__resetPath(p);
 28.2208 +		cpx = 0; cpy = 0;
 28.2209 +		cpx2 = 0; cpy2 = 0;
 28.2210 +		closedFlag = 0;
 28.2211 +		nargs = 0;
 28.2212 +
 28.2213 +		while (*s) {
 28.2214 +			s = nsvg__getNextPathItem(s, item);
 28.2215 +			if (!*item) break;
 28.2216 +			if (nsvg__isnum(item[0])) {
 28.2217 +				if (nargs < 10)
 28.2218 +					args[nargs++] = (float)nsvg__atof(item);
 28.2219 +				if (nargs >= rargs) {
 28.2220 +					switch (cmd) {
 28.2221 +						case 'm':
 28.2222 +						case 'M':
 28.2223 +							nsvg__pathMoveTo(p, &cpx, &cpy, args, cmd == 'm' ? 1 : 0);
 28.2224 +							// Moveto can be followed by multiple coordinate pairs,
 28.2225 +							// which should be treated as linetos.
 28.2226 +							cmd = (cmd == 'm') ? 'l' : 'L';
 28.2227 +							rargs = nsvg__getArgsPerElement(cmd);
 28.2228 +							cpx2 = cpx; cpy2 = cpy;
 28.2229 +							break;
 28.2230 +						case 'l':
 28.2231 +						case 'L':
 28.2232 +							nsvg__pathLineTo(p, &cpx, &cpy, args, cmd == 'l' ? 1 : 0);
 28.2233 +							cpx2 = cpx; cpy2 = cpy;
 28.2234 +							break;
 28.2235 +						case 'H':
 28.2236 +						case 'h':
 28.2237 +							nsvg__pathHLineTo(p, &cpx, &cpy, args, cmd == 'h' ? 1 : 0);
 28.2238 +							cpx2 = cpx; cpy2 = cpy;
 28.2239 +							break;
 28.2240 +						case 'V':
 28.2241 +						case 'v':
 28.2242 +							nsvg__pathVLineTo(p, &cpx, &cpy, args, cmd == 'v' ? 1 : 0);
 28.2243 +							cpx2 = cpx; cpy2 = cpy;
 28.2244 +							break;
 28.2245 +						case 'C':
 28.2246 +						case 'c':
 28.2247 +							nsvg__pathCubicBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'c' ? 1 : 0);
 28.2248 +							break;
 28.2249 +						case 'S':
 28.2250 +						case 's':
 28.2251 +							nsvg__pathCubicBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 's' ? 1 : 0);
 28.2252 +							break;
 28.2253 +						case 'Q':
 28.2254 +						case 'q':
 28.2255 +							nsvg__pathQuadBezTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 'q' ? 1 : 0);
 28.2256 +							break;
 28.2257 +						case 'T':
 28.2258 +						case 't':
 28.2259 +							nsvg__pathQuadBezShortTo(p, &cpx, &cpy, &cpx2, &cpy2, args, cmd == 't' ? 1 : 0);
 28.2260 +							break;
 28.2261 +						case 'A':
 28.2262 +						case 'a':
 28.2263 +							nsvg__pathArcTo(p, &cpx, &cpy, args, cmd == 'a' ? 1 : 0);
 28.2264 +							cpx2 = cpx; cpy2 = cpy;
 28.2265 +							break;
 28.2266 +						default:
 28.2267 +							if (nargs >= 2) {
 28.2268 +								cpx = args[nargs-2];
 28.2269 +								cpy = args[nargs-1];
 28.2270 +								cpx2 = cpx; cpy2 = cpy;
 28.2271 +							}
 28.2272 +							break;
 28.2273 +					}
 28.2274 +					nargs = 0;
 28.2275 +				}
 28.2276 +			} else {
 28.2277 +				cmd = item[0];
 28.2278 +				rargs = nsvg__getArgsPerElement(cmd);
 28.2279 +				if (cmd == 'M' || cmd == 'm') {
 28.2280 +					// Commit path.
 28.2281 +					if (p->npts > 0)
 28.2282 +						nsvg__addPath(p, closedFlag);
 28.2283 +					// Start new subpath.
 28.2284 +					nsvg__resetPath(p);
 28.2285 +					closedFlag = 0;
 28.2286 +					nargs = 0;
 28.2287 +				} else if (cmd == 'Z' || cmd == 'z') {
 28.2288 +					closedFlag = 1;
 28.2289 +					// Commit path.
 28.2290 +					if (p->npts > 0) {
 28.2291 +						// Move current point to first point
 28.2292 +						cpx = p->pts[0];
 28.2293 +						cpy = p->pts[1];
 28.2294 +						cpx2 = cpx; cpy2 = cpy;
 28.2295 +						nsvg__addPath(p, closedFlag);
 28.2296 +					}
 28.2297 +					// Start new subpath.
 28.2298 +					nsvg__resetPath(p);
 28.2299 +					nsvg__moveTo(p, cpx, cpy);
 28.2300 +					closedFlag = 0;
 28.2301 +					nargs = 0;
 28.2302 +				}
 28.2303 +			}
 28.2304 +		}
 28.2305 +		// Commit path.
 28.2306 +		if (p->npts)
 28.2307 +			nsvg__addPath(p, closedFlag);
 28.2308 +	}
 28.2309 +
 28.2310 +	nsvg__addShape(p);
 28.2311 +}
 28.2312 +
 28.2313 +static void nsvg__parseRect(NSVGparser* p, const char** attr)
 28.2314 +{
 28.2315 +	float x = 0.0f;
 28.2316 +	float y = 0.0f;
 28.2317 +	float w = 0.0f;
 28.2318 +	float h = 0.0f;
 28.2319 +	float rx = -1.0f; // marks not set
 28.2320 +	float ry = -1.0f;
 28.2321 +	int i;
 28.2322 +
 28.2323 +	for (i = 0; attr[i]; i += 2) {
 28.2324 +		if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 28.2325 +			if (strcmp(attr[i], "x") == 0) x = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
 28.2326 +			if (strcmp(attr[i], "y") == 0) y = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
 28.2327 +			if (strcmp(attr[i], "width") == 0) w = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p));
 28.2328 +			if (strcmp(attr[i], "height") == 0) h = nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p));
 28.2329 +			if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
 28.2330 +			if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
 28.2331 +		}
 28.2332 +	}
 28.2333 +
 28.2334 +	if (rx < 0.0f && ry > 0.0f) rx = ry;
 28.2335 +	if (ry < 0.0f && rx > 0.0f) ry = rx;
 28.2336 +	if (rx < 0.0f) rx = 0.0f;
 28.2337 +	if (ry < 0.0f) ry = 0.0f;
 28.2338 +	if (rx > w/2.0f) rx = w/2.0f;
 28.2339 +	if (ry > h/2.0f) ry = h/2.0f;
 28.2340 +
 28.2341 +	if (w != 0.0f && h != 0.0f) {
 28.2342 +		nsvg__resetPath(p);
 28.2343 +
 28.2344 +		if (rx < 0.00001f || ry < 0.0001f) {
 28.2345 +			nsvg__moveTo(p, x, y);
 28.2346 +			nsvg__lineTo(p, x+w, y);
 28.2347 +			nsvg__lineTo(p, x+w, y+h);
 28.2348 +			nsvg__lineTo(p, x, y+h);
 28.2349 +		} else {
 28.2350 +			// Rounded rectangle
 28.2351 +			nsvg__moveTo(p, x+rx, y);
 28.2352 +			nsvg__lineTo(p, x+w-rx, y);
 28.2353 +			nsvg__cubicBezTo(p, x+w-rx*(1-NSVG_KAPPA90), y, x+w, y+ry*(1-NSVG_KAPPA90), x+w, y+ry);
 28.2354 +			nsvg__lineTo(p, x+w, y+h-ry);
 28.2355 +			nsvg__cubicBezTo(p, x+w, y+h-ry*(1-NSVG_KAPPA90), x+w-rx*(1-NSVG_KAPPA90), y+h, x+w-rx, y+h);
 28.2356 +			nsvg__lineTo(p, x+rx, y+h);
 28.2357 +			nsvg__cubicBezTo(p, x+rx*(1-NSVG_KAPPA90), y+h, x, y+h-ry*(1-NSVG_KAPPA90), x, y+h-ry);
 28.2358 +			nsvg__lineTo(p, x, y+ry);
 28.2359 +			nsvg__cubicBezTo(p, x, y+ry*(1-NSVG_KAPPA90), x+rx*(1-NSVG_KAPPA90), y, x+rx, y);
 28.2360 +		}
 28.2361 +
 28.2362 +		nsvg__addPath(p, 1);
 28.2363 +
 28.2364 +		nsvg__addShape(p);
 28.2365 +	}
 28.2366 +}
 28.2367 +
 28.2368 +static void nsvg__parseCircle(NSVGparser* p, const char** attr)
 28.2369 +{
 28.2370 +	float cx = 0.0f;
 28.2371 +	float cy = 0.0f;
 28.2372 +	float r = 0.0f;
 28.2373 +	int i;
 28.2374 +
 28.2375 +	for (i = 0; attr[i]; i += 2) {
 28.2376 +		if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 28.2377 +			if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
 28.2378 +			if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
 28.2379 +			if (strcmp(attr[i], "r") == 0) r = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualLength(p)));
 28.2380 +		}
 28.2381 +	}
 28.2382 +
 28.2383 +	if (r > 0.0f) {
 28.2384 +		nsvg__resetPath(p);
 28.2385 +
 28.2386 +		nsvg__moveTo(p, cx+r, cy);
 28.2387 +		nsvg__cubicBezTo(p, cx+r, cy+r*NSVG_KAPPA90, cx+r*NSVG_KAPPA90, cy+r, cx, cy+r);
 28.2388 +		nsvg__cubicBezTo(p, cx-r*NSVG_KAPPA90, cy+r, cx-r, cy+r*NSVG_KAPPA90, cx-r, cy);
 28.2389 +		nsvg__cubicBezTo(p, cx-r, cy-r*NSVG_KAPPA90, cx-r*NSVG_KAPPA90, cy-r, cx, cy-r);
 28.2390 +		nsvg__cubicBezTo(p, cx+r*NSVG_KAPPA90, cy-r, cx+r, cy-r*NSVG_KAPPA90, cx+r, cy);
 28.2391 +
 28.2392 +		nsvg__addPath(p, 1);
 28.2393 +
 28.2394 +		nsvg__addShape(p);
 28.2395 +	}
 28.2396 +}
 28.2397 +
 28.2398 +static void nsvg__parseEllipse(NSVGparser* p, const char** attr)
 28.2399 +{
 28.2400 +	float cx = 0.0f;
 28.2401 +	float cy = 0.0f;
 28.2402 +	float rx = 0.0f;
 28.2403 +	float ry = 0.0f;
 28.2404 +	int i;
 28.2405 +
 28.2406 +	for (i = 0; attr[i]; i += 2) {
 28.2407 +		if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 28.2408 +			if (strcmp(attr[i], "cx") == 0) cx = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
 28.2409 +			if (strcmp(attr[i], "cy") == 0) cy = nsvg__parseCoordinate(p, attr[i+1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
 28.2410 +			if (strcmp(attr[i], "rx") == 0) rx = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualWidth(p)));
 28.2411 +			if (strcmp(attr[i], "ry") == 0) ry = fabsf(nsvg__parseCoordinate(p, attr[i+1], 0.0f, nsvg__actualHeight(p)));
 28.2412 +		}
 28.2413 +	}
 28.2414 +
 28.2415 +	if (rx > 0.0f && ry > 0.0f) {
 28.2416 +
 28.2417 +		nsvg__resetPath(p);
 28.2418 +
 28.2419 +		nsvg__moveTo(p, cx+rx, cy);
 28.2420 +		nsvg__cubicBezTo(p, cx+rx, cy+ry*NSVG_KAPPA90, cx+rx*NSVG_KAPPA90, cy+ry, cx, cy+ry);
 28.2421 +		nsvg__cubicBezTo(p, cx-rx*NSVG_KAPPA90, cy+ry, cx-rx, cy+ry*NSVG_KAPPA90, cx-rx, cy);
 28.2422 +		nsvg__cubicBezTo(p, cx-rx, cy-ry*NSVG_KAPPA90, cx-rx*NSVG_KAPPA90, cy-ry, cx, cy-ry);
 28.2423 +		nsvg__cubicBezTo(p, cx+rx*NSVG_KAPPA90, cy-ry, cx+rx, cy-ry*NSVG_KAPPA90, cx+rx, cy);
 28.2424 +
 28.2425 +		nsvg__addPath(p, 1);
 28.2426 +
 28.2427 +		nsvg__addShape(p);
 28.2428 +	}
 28.2429 +}
 28.2430 +
 28.2431 +static void nsvg__parseLine(NSVGparser* p, const char** attr)
 28.2432 +{
 28.2433 +	float x1 = 0.0;
 28.2434 +	float y1 = 0.0;
 28.2435 +	float x2 = 0.0;
 28.2436 +	float y2 = 0.0;
 28.2437 +	int i;
 28.2438 +
 28.2439 +	for (i = 0; attr[i]; i += 2) {
 28.2440 +		if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 28.2441 +			if (strcmp(attr[i], "x1") == 0) x1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
 28.2442 +			if (strcmp(attr[i], "y1") == 0) y1 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
 28.2443 +			if (strcmp(attr[i], "x2") == 0) x2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigX(p), nsvg__actualWidth(p));
 28.2444 +			if (strcmp(attr[i], "y2") == 0) y2 = nsvg__parseCoordinate(p, attr[i + 1], nsvg__actualOrigY(p), nsvg__actualHeight(p));
 28.2445 +		}
 28.2446 +	}
 28.2447 +
 28.2448 +	nsvg__resetPath(p);
 28.2449 +
 28.2450 +	nsvg__moveTo(p, x1, y1);
 28.2451 +	nsvg__lineTo(p, x2, y2);
 28.2452 +
 28.2453 +	nsvg__addPath(p, 0);
 28.2454 +
 28.2455 +	nsvg__addShape(p);
 28.2456 +}
 28.2457 +
 28.2458 +static void nsvg__parsePoly(NSVGparser* p, const char** attr, int closeFlag)
 28.2459 +{
 28.2460 +	int i;
 28.2461 +	const char* s;
 28.2462 +	float args[2];
 28.2463 +	int nargs, npts = 0;
 28.2464 +	char item[64];
 28.2465 +
 28.2466 +	nsvg__resetPath(p);
 28.2467 +
 28.2468 +	for (i = 0; attr[i]; i += 2) {
 28.2469 +		if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 28.2470 +			if (strcmp(attr[i], "points") == 0) {
 28.2471 +				s = attr[i + 1];
 28.2472 +				nargs = 0;
 28.2473 +				while (*s) {
 28.2474 +					s = nsvg__getNextPathItem(s, item);
 28.2475 +					args[nargs++] = (float)nsvg__atof(item);
 28.2476 +					if (nargs >= 2) {
 28.2477 +						if (npts == 0)
 28.2478 +							nsvg__moveTo(p, args[0], args[1]);
 28.2479 +						else
 28.2480 +							nsvg__lineTo(p, args[0], args[1]);
 28.2481 +						nargs = 0;
 28.2482 +						npts++;
 28.2483 +					}
 28.2484 +				}
 28.2485 +			}
 28.2486 +		}
 28.2487 +	}
 28.2488 +
 28.2489 +	nsvg__addPath(p, (char)closeFlag);
 28.2490 +
 28.2491 +	nsvg__addShape(p);
 28.2492 +}
 28.2493 +
 28.2494 +static void nsvg__parseSVG(NSVGparser* p, const char** attr)
 28.2495 +{
 28.2496 +	int i;
 28.2497 +	for (i = 0; attr[i]; i += 2) {
 28.2498 +		if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 28.2499 +			if (strcmp(attr[i], "width") == 0) {
 28.2500 +				p->image->width = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 1.0f);
 28.2501 +			} else if (strcmp(attr[i], "height") == 0) {
 28.2502 +				p->image->height = nsvg__parseCoordinate(p, attr[i + 1], 0.0f, 1.0f);
 28.2503 +			} else if (strcmp(attr[i], "viewBox") == 0) {
 28.2504 +				sscanf(attr[i + 1], "%f%*[%%, \t]%f%*[%%, \t]%f%*[%%, \t]%f", &p->viewMinx, &p->viewMiny, &p->viewWidth, &p->viewHeight);
 28.2505 +			} else if (strcmp(attr[i], "preserveAspectRatio") == 0) {
 28.2506 +				if (strstr(attr[i + 1], "none") != 0) {
 28.2507 +					// No uniform scaling
 28.2508 +					p->alignType = NSVG_ALIGN_NONE;
 28.2509 +				} else {
 28.2510 +					// Parse X align
 28.2511 +					if (strstr(attr[i + 1], "xMin") != 0)
 28.2512 +						p->alignX = NSVG_ALIGN_MIN;
 28.2513 +					else if (strstr(attr[i + 1], "xMid") != 0)
 28.2514 +						p->alignX = NSVG_ALIGN_MID;
 28.2515 +					else if (strstr(attr[i + 1], "xMax") != 0)
 28.2516 +						p->alignX = NSVG_ALIGN_MAX;
 28.2517 +					// Parse X align
 28.2518 +					if (strstr(attr[i + 1], "yMin") != 0)
 28.2519 +						p->alignY = NSVG_ALIGN_MIN;
 28.2520 +					else if (strstr(attr[i + 1], "yMid") != 0)
 28.2521 +						p->alignY = NSVG_ALIGN_MID;
 28.2522 +					else if (strstr(attr[i + 1], "yMax") != 0)
 28.2523 +						p->alignY = NSVG_ALIGN_MAX;
 28.2524 +					// Parse meet/slice
 28.2525 +					p->alignType = NSVG_ALIGN_MEET;
 28.2526 +					if (strstr(attr[i + 1], "slice") != 0)
 28.2527 +						p->alignType = NSVG_ALIGN_SLICE;
 28.2528 +				}
 28.2529 +			}
 28.2530 +		}
 28.2531 +	}
 28.2532 +}
 28.2533 +
 28.2534 +static void nsvg__parseGradient(NSVGparser* p, const char** attr, char type)
 28.2535 +{
 28.2536 +	int i;
 28.2537 +	NSVGgradientData* grad = (NSVGgradientData*)malloc(sizeof(NSVGgradientData));
 28.2538 +	if (grad == NULL) return;
 28.2539 +	memset(grad, 0, sizeof(NSVGgradientData));
 28.2540 +	grad->units = NSVG_OBJECT_SPACE;
 28.2541 +	grad->type = type;
 28.2542 +	if (grad->type == NSVG_PAINT_LINEAR_GRADIENT) {
 28.2543 +		grad->linear.x1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
 28.2544 +		grad->linear.y1 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
 28.2545 +		grad->linear.x2 = nsvg__coord(100.0f, NSVG_UNITS_PERCENT);
 28.2546 +		grad->linear.y2 = nsvg__coord(0.0f, NSVG_UNITS_PERCENT);
 28.2547 +	} else if (grad->type == NSVG_PAINT_RADIAL_GRADIENT) {
 28.2548 +		grad->radial.cx = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
 28.2549 +		grad->radial.cy = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
 28.2550 +		grad->radial.r = nsvg__coord(50.0f, NSVG_UNITS_PERCENT);
 28.2551 +	}
 28.2552 +
 28.2553 +	nsvg__xformIdentity(grad->xform);
 28.2554 +
 28.2555 +	for (i = 0; attr[i]; i += 2) {
 28.2556 +		if (strcmp(attr[i], "id") == 0) {
 28.2557 +			strncpy(grad->id, attr[i+1], 63);
 28.2558 +			grad->id[63] = '\0';
 28.2559 +		} else if (!nsvg__parseAttr(p, attr[i], attr[i + 1])) {
 28.2560 +			if (strcmp(attr[i], "gradientUnits") == 0) {
 28.2561 +				if (strcmp(attr[i+1], "objectBoundingBox") == 0)
 28.2562 +					grad->units = NSVG_OBJECT_SPACE;
 28.2563 +				else
 28.2564 +					grad->units = NSVG_USER_SPACE;
 28.2565 +			} else if (strcmp(attr[i], "gradientTransform") == 0) {
 28.2566 +				nsvg__parseTransform(grad->xform, attr[i + 1]);
 28.2567 +			} else if (strcmp(attr[i], "cx") == 0) {
 28.2568 +				grad->radial.cx = nsvg__parseCoordinateRaw(attr[i + 1]);
 28.2569 +			} else if (strcmp(attr[i], "cy") == 0) {
 28.2570 +				grad->radial.cy = nsvg__parseCoordinateRaw(attr[i + 1]);
 28.2571 +			} else if (strcmp(attr[i], "r") == 0) {
 28.2572 +				grad->radial.r = nsvg__parseCoordinateRaw(attr[i + 1]);
 28.2573 +			} else if (strcmp(attr[i], "fx") == 0) {
 28.2574 +				grad->radial.fx = nsvg__parseCoordinateRaw(attr[i + 1]);
 28.2575 +			} else if (strcmp(attr[i], "fy") == 0) {
 28.2576 +				grad->radial.fy = nsvg__parseCoordinateRaw(attr[i + 1]);
 28.2577 +			} else if (strcmp(attr[i], "x1") == 0) {
 28.2578 +				grad->linear.x1 = nsvg__parseCoordinateRaw(attr[i + 1]);
 28.2579 +			} else if (strcmp(attr[i], "y1") == 0) {
 28.2580 +				grad->linear.y1 = nsvg__parseCoordinateRaw(attr[i + 1]);
 28.2581 +			} else if (strcmp(attr[i], "x2") == 0) {
 28.2582 +				grad->linear.x2 = nsvg__parseCoordinateRaw(attr[i + 1]);
 28.2583 +			} else if (strcmp(attr[i], "y2") == 0) {
 28.2584 +				grad->linear.y2 = nsvg__parseCoordinateRaw(attr[i + 1]);
 28.2585 +			} else if (strcmp(attr[i], "spreadMethod") == 0) {
 28.2586 +				if (strcmp(attr[i+1], "pad") == 0)
 28.2587 +					grad->spread = NSVG_SPREAD_PAD;
 28.2588 +				else if (strcmp(attr[i+1], "reflect") == 0)
 28.2589 +					grad->spread = NSVG_SPREAD_REFLECT;
 28.2590 +				else if (strcmp(attr[i+1], "repeat") == 0)
 28.2591 +					grad->spread = NSVG_SPREAD_REPEAT;
 28.2592 +			} else if (strcmp(attr[i], "xlink:href") == 0) {
 28.2593 +				const char *href = attr[i+1];
 28.2594 +				strncpy(grad->ref, href+1, 62);
 28.2595 +				grad->ref[62] = '\0';
 28.2596 +			}
 28.2597 +		}
 28.2598 +	}
 28.2599 +
 28.2600 +	grad->next = p->gradients;
 28.2601 +	p->gradients = grad;
 28.2602 +}
 28.2603 +
 28.2604 +static void nsvg__parseGradientStop(NSVGparser* p, const char** attr)
 28.2605 +{
 28.2606 +	NSVGattrib* curAttr = nsvg__getAttr(p);
 28.2607 +	NSVGgradientData* grad;
 28.2608 +	NSVGgradientStop* stop;
 28.2609 +	int i, idx;
 28.2610 +
 28.2611 +	curAttr->stopOffset = 0;
 28.2612 +	curAttr->stopColor = 0;
 28.2613 +	curAttr->stopOpacity = 1.0f;
 28.2614 +
 28.2615 +	for (i = 0; attr[i]; i += 2) {
 28.2616 +		nsvg__parseAttr(p, attr[i], attr[i + 1]);
 28.2617 +	}
 28.2618 +
 28.2619 +	// Add stop to the last gradient.
 28.2620 +	grad = p->gradients;
 28.2621 +	if (grad == NULL) return;
 28.2622 +
 28.2623 +	grad->nstops++;
 28.2624 +	grad->stops = (NSVGgradientStop*)realloc(grad->stops, sizeof(NSVGgradientStop)*grad->nstops);
 28.2625 +	if (grad->stops == NULL) return;
 28.2626 +
 28.2627 +	// Insert
 28.2628 +	idx = grad->nstops-1;
 28.2629 +	for (i = 0; i < grad->nstops-1; i++) {
 28.2630 +		if (curAttr->stopOffset < grad->stops[i].offset) {
 28.2631 +			idx = i;
 28.2632 +			break;
 28.2633 +		}
 28.2634 +	}
 28.2635 +	if (idx != grad->nstops-1) {
 28.2636 +		for (i = grad->nstops-1; i > idx; i--)
 28.2637 +			grad->stops[i] = grad->stops[i-1];
 28.2638 +	}
 28.2639 +
 28.2640 +	stop = &grad->stops[idx];
 28.2641 +	stop->color = curAttr->stopColor;
 28.2642 +	stop->color |= (unsigned int)(curAttr->stopOpacity*255) << 24;
 28.2643 +	stop->offset = curAttr->stopOffset;
 28.2644 +}
 28.2645 +
 28.2646 +static void nsvg__startElement(void* ud, const char* el, const char** attr)
 28.2647 +{
 28.2648 +	NSVGparser* p = (NSVGparser*)ud;
 28.2649 +
 28.2650 +	if (p->defsFlag) {
 28.2651 +		// Skip everything but gradients in defs
 28.2652 +		if (strcmp(el, "linearGradient") == 0) {
 28.2653 +			nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
 28.2654 +		} else if (strcmp(el, "radialGradient") == 0) {
 28.2655 +			nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
 28.2656 +		} else if (strcmp(el, "stop") == 0) {
 28.2657 +			nsvg__parseGradientStop(p, attr);
 28.2658 +		}
 28.2659 +		return;
 28.2660 +	}
 28.2661 +
 28.2662 +	if (strcmp(el, "g") == 0) {
 28.2663 +		nsvg__pushAttr(p);
 28.2664 +		nsvg__parseAttribs(p, attr);
 28.2665 +	} else if (strcmp(el, "path") == 0) {
 28.2666 +		if (p->pathFlag)	// Do not allow nested paths.
 28.2667 +			return;
 28.2668 +		nsvg__pushAttr(p);
 28.2669 +		nsvg__parsePath(p, attr);
 28.2670 +		nsvg__popAttr(p);
 28.2671 +	} else if (strcmp(el, "rect") == 0) {
 28.2672 +		nsvg__pushAttr(p);
 28.2673 +		nsvg__parseRect(p, attr);
 28.2674 +		nsvg__popAttr(p);
 28.2675 +	} else if (strcmp(el, "circle") == 0) {
 28.2676 +		nsvg__pushAttr(p);
 28.2677 +		nsvg__parseCircle(p, attr);
 28.2678 +		nsvg__popAttr(p);
 28.2679 +	} else if (strcmp(el, "ellipse") == 0) {
 28.2680 +		nsvg__pushAttr(p);
 28.2681 +		nsvg__parseEllipse(p, attr);
 28.2682 +		nsvg__popAttr(p);
 28.2683 +	} else if (strcmp(el, "line") == 0)  {
 28.2684 +		nsvg__pushAttr(p);
 28.2685 +		nsvg__parseLine(p, attr);
 28.2686 +		nsvg__popAttr(p);
 28.2687 +	} else if (strcmp(el, "polyline") == 0)  {
 28.2688 +		nsvg__pushAttr(p);
 28.2689 +		nsvg__parsePoly(p, attr, 0);
 28.2690 +		nsvg__popAttr(p);
 28.2691 +	} else if (strcmp(el, "polygon") == 0)  {
 28.2692 +		nsvg__pushAttr(p);
 28.2693 +		nsvg__parsePoly(p, attr, 1);
 28.2694 +		nsvg__popAttr(p);
 28.2695 +	} else  if (strcmp(el, "linearGradient") == 0) {
 28.2696 +		nsvg__parseGradient(p, attr, NSVG_PAINT_LINEAR_GRADIENT);
 28.2697 +	} else if (strcmp(el, "radialGradient") == 0) {
 28.2698 +		nsvg__parseGradient(p, attr, NSVG_PAINT_RADIAL_GRADIENT);
 28.2699 +	} else if (strcmp(el, "stop") == 0) {
 28.2700 +		nsvg__parseGradientStop(p, attr);
 28.2701 +	} else if (strcmp(el, "defs") == 0) {
 28.2702 +		p->defsFlag = 1;
 28.2703 +	} else if (strcmp(el, "svg") == 0) {
 28.2704 +		nsvg__parseSVG(p, attr);
 28.2705 +	}
 28.2706 +}
 28.2707 +
 28.2708 +static void nsvg__endElement(void* ud, const char* el)
 28.2709 +{
 28.2710 +	NSVGparser* p = (NSVGparser*)ud;
 28.2711 +
 28.2712 +	if (strcmp(el, "g") == 0) {
 28.2713 +		nsvg__popAttr(p);
 28.2714 +	} else if (strcmp(el, "path") == 0) {
 28.2715 +		p->pathFlag = 0;
 28.2716 +	} else if (strcmp(el, "defs") == 0) {
 28.2717 +		p->defsFlag = 0;
 28.2718 +	}
 28.2719 +}
 28.2720 +
 28.2721 +static void nsvg__content(void* ud, const char* s)
 28.2722 +{
 28.2723 +	NSVG_NOTUSED(ud);
 28.2724 +	NSVG_NOTUSED(s);
 28.2725 +	// empty
 28.2726 +}
 28.2727 +
 28.2728 +static void nsvg__imageBounds(NSVGparser* p, float* bounds)
 28.2729 +{
 28.2730 +	NSVGshape* shape;
 28.2731 +	shape = p->image->shapes;
 28.2732 +	if (shape == NULL) {
 28.2733 +		bounds[0] = bounds[1] = bounds[2] = bounds[3] = 0.0;
 28.2734 +		return;
 28.2735 +	}
 28.2736 +	bounds[0] = shape->bounds[0];
 28.2737 +	bounds[1] = shape->bounds[1];
 28.2738 +	bounds[2] = shape->bounds[2];
 28.2739 +	bounds[3] = shape->bounds[3];
 28.2740 +	for (shape = shape->next; shape != NULL; shape = shape->next) {
 28.2741 +		bounds[0] = nsvg__minf(bounds[0], shape->bounds[0]);
 28.2742 +		bounds[1] = nsvg__minf(bounds[1], shape->bounds[1]);
 28.2743 +		bounds[2] = nsvg__maxf(bounds[2], shape->bounds[2]);
 28.2744 +		bounds[3] = nsvg__maxf(bounds[3], shape->bounds[3]);
 28.2745 +	}
 28.2746 +}
 28.2747 +
 28.2748 +static float nsvg__viewAlign(float content, float container, int type)
 28.2749 +{
 28.2750 +	if (type == NSVG_ALIGN_MIN)
 28.2751 +		return 0;
 28.2752 +	else if (type == NSVG_ALIGN_MAX)
 28.2753 +		return container - content;
 28.2754 +	// mid
 28.2755 +	return (container - content) * 0.5f;
 28.2756 +}
 28.2757 +
 28.2758 +static void nsvg__scaleGradient(NSVGgradient* grad, float tx, float ty, float sx, float sy)
 28.2759 +{
 28.2760 +	float t[6];
 28.2761 +	nsvg__xformSetTranslation(t, tx, ty);
 28.2762 +	nsvg__xformMultiply (grad->xform, t);
 28.2763 +
 28.2764 +	nsvg__xformSetScale(t, sx, sy);
 28.2765 +	nsvg__xformMultiply (grad->xform, t);
 28.2766 +}
 28.2767 +
 28.2768 +static void nsvg__scaleToViewbox(NSVGparser* p, const char* units)
 28.2769 +{
 28.2770 +	NSVGshape* shape;
 28.2771 +	NSVGpath* path;
 28.2772 +	float tx, ty, sx, sy, us, bounds[4], t[6], avgs;
 28.2773 +	int i;
 28.2774 +	float* pt;
 28.2775 +
 28.2776 +	// Guess image size if not set completely.
 28.2777 +	nsvg__imageBounds(p, bounds);
 28.2778 +
 28.2779 +	if (p->viewWidth == 0) {
 28.2780 +		if (p->image->width > 0) {
 28.2781 +			p->viewWidth = p->image->width;
 28.2782 +		} else {
 28.2783 +			p->viewMinx = bounds[0];
 28.2784 +			p->viewWidth = bounds[2] - bounds[0];
 28.2785 +		}
 28.2786 +	}
 28.2787 +	if (p->viewHeight == 0) {
 28.2788 +		if (p->image->height > 0) {
 28.2789 +			p->viewHeight = p->image->height;
 28.2790 +		} else {
 28.2791 +			p->viewMiny = bounds[1];
 28.2792 +			p->viewHeight = bounds[3] - bounds[1];
 28.2793 +		}
 28.2794 +	}
 28.2795 +	if (p->image->width == 0)
 28.2796 +		p->image->width = p->viewWidth;
 28.2797 +	if (p->image->height == 0)
 28.2798 +		p->image->height = p->viewHeight;
 28.2799 +
 28.2800 +	tx = -p->viewMinx;
 28.2801 +	ty = -p->viewMiny;
 28.2802 +	sx = p->viewWidth > 0 ? p->image->width / p->viewWidth : 0;
 28.2803 +	sy = p->viewHeight > 0 ? p->image->height / p->viewHeight : 0;
 28.2804 +	// Unit scaling
 28.2805 +	us = 1.0f / nsvg__convertToPixels(p, nsvg__coord(1.0f, nsvg__parseUnits(units)), 0.0f, 1.0f);
 28.2806 +
 28.2807 +	// Fix aspect ratio
 28.2808 +	if (p->alignType == NSVG_ALIGN_MEET) {
 28.2809 +		// fit whole image into viewbox
 28.2810 +		sx = sy = nsvg__minf(sx, sy);
 28.2811 +		tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx;
 28.2812 +		ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy;
 28.2813 +	} else if (p->alignType == NSVG_ALIGN_SLICE) {
 28.2814 +		// fill whole viewbox with image
 28.2815 +		sx = sy = nsvg__maxf(sx, sy);
 28.2816 +		tx += nsvg__viewAlign(p->viewWidth*sx, p->image->width, p->alignX) / sx;
 28.2817 +		ty += nsvg__viewAlign(p->viewHeight*sy, p->image->height, p->alignY) / sy;
 28.2818 +	}
 28.2819 +
 28.2820 +	// Transform
 28.2821 +	sx *= us;
 28.2822 +	sy *= us;
 28.2823 +	avgs = (sx+sy) / 2.0f;
 28.2824 +	for (shape = p->image->shapes; shape != NULL; shape = shape->next) {
 28.2825 +		shape->bounds[0] = (shape->bounds[0] + tx) * sx;
 28.2826 +		shape->bounds[1] = (shape->bounds[1] + ty) * sy;
 28.2827 +		shape->bounds[2] = (shape->bounds[2] + tx) * sx;
 28.2828 +		shape->bounds[3] = (shape->bounds[3] + ty) * sy;
 28.2829 +		for (path = shape->paths; path != NULL; path = path->next) {
 28.2830 +			path->bounds[0] = (path->bounds[0] + tx) * sx;
 28.2831 +			path->bounds[1] = (path->bounds[1] + ty) * sy;
 28.2832 +			path->bounds[2] = (path->bounds[2] + tx) * sx;
 28.2833 +			path->bounds[3] = (path->bounds[3] + ty) * sy;
 28.2834 +			for (i =0; i < path->npts; i++) {
 28.2835 +				pt = &path->pts[i*2];
 28.2836 +				pt[0] = (pt[0] + tx) * sx;
 28.2837 +				pt[1] = (pt[1] + ty) * sy;
 28.2838 +			}
 28.2839 +		}
 28.2840 +
 28.2841 +		if (shape->fill.type == NSVG_PAINT_LINEAR_GRADIENT || shape->fill.type == NSVG_PAINT_RADIAL_GRADIENT) {
 28.2842 +			nsvg__scaleGradient(shape->fill.gradient, tx,ty, sx,sy);
 28.2843 +			memcpy(t, shape->fill.gradient->xform, sizeof(float)*6);
 28.2844 +			nsvg__xformInverse(shape->fill.gradient->xform, t);
 28.2845 +		}
 28.2846 +		if (shape->stroke.type == NSVG_PAINT_LINEAR_GRADIENT || shape->stroke.type == NSVG_PAINT_RADIAL_GRADIENT) {
 28.2847 +			nsvg__scaleGradient(shape->stroke.gradient, tx,ty, sx,sy);
 28.2848 +			memcpy(t, shape->stroke.gradient->xform, sizeof(float)*6);
 28.2849 +			nsvg__xformInverse(shape->stroke.gradient->xform, t);
 28.2850 +		}
 28.2851 +
 28.2852 +		shape->strokeWidth *= avgs;
 28.2853 +		shape->strokeDashOffset *= avgs;
 28.2854 +		for (i = 0; i < shape->strokeDashCount; i++)
 28.2855 +			shape->strokeDashArray[i] *= avgs;
 28.2856 +	}
 28.2857 +}
 28.2858 +
 28.2859 +NSVGimage* nsvgParse(char* input, const char* units, float dpi)
 28.2860 +{
 28.2861 +	NSVGparser* p;
 28.2862 +	NSVGimage* ret = 0;
 28.2863 +
 28.2864 +	p = nsvg__createParser();
 28.2865 +	if (p == NULL) {
 28.2866 +		return NULL;
 28.2867 +	}
 28.2868 +	p->dpi = dpi;
 28.2869 +
 28.2870 +	nsvg__parseXML(input, nsvg__startElement, nsvg__endElement, nsvg__content, p);
 28.2871 +
 28.2872 +	// Scale to viewBox
 28.2873 +	nsvg__scaleToViewbox(p, units);
 28.2874 +
 28.2875 +	ret = p->image;
 28.2876 +	p->image = NULL;
 28.2877 +
 28.2878 +	nsvg__deleteParser(p);
 28.2879 +
 28.2880 +	return ret;
 28.2881 +}
 28.2882 +
 28.2883 +NSVGimage* nsvgParseFromFile(const char* filename, const char* units, float dpi)
 28.2884 +{
 28.2885 +	FILE* fp = NULL;
 28.2886 +	size_t size;
 28.2887 +	char* data = NULL;
 28.2888 +	NSVGimage* image = NULL;
 28.2889 +
 28.2890 +	fp = fopen(filename, "rb");
 28.2891 +	if (!fp) goto error;
 28.2892 +	fseek(fp, 0, SEEK_END);
 28.2893 +	size = ftell(fp);
 28.2894 +	fseek(fp, 0, SEEK_SET);
 28.2895 +	data = (char*)malloc(size+1);
 28.2896 +	if (data == NULL) goto error;
 28.2897 +	if (fread(data, 1, size, fp) != size) goto error;
 28.2898 +	data[size] = '\0';	// Must be null terminated.
 28.2899 +	fclose(fp);
 28.2900 +	image = nsvgParse(data, units, dpi);
 28.2901 +	free(data);
 28.2902 +
 28.2903 +	return image;
 28.2904 +
 28.2905 +error:
 28.2906 +	if (fp) fclose(fp);
 28.2907 +	if (data) free(data);
 28.2908 +	if (image) nsvgDelete(image);
 28.2909 +	return NULL;
 28.2910 +}
 28.2911 +
 28.2912 +void nsvgDelete(NSVGimage* image)
 28.2913 +{
 28.2914 +	NSVGshape *snext, *shape;
 28.2915 +	if (image == NULL) return;
 28.2916 +	shape = image->shapes;
 28.2917 +	while (shape != NULL) {
 28.2918 +		snext = shape->next;
 28.2919 +		nsvg__deletePaths(shape->paths);
 28.2920 +		nsvg__deletePaint(&shape->fill);
 28.2921 +		nsvg__deletePaint(&shape->stroke);
 28.2922 +		free(shape);
 28.2923 +		shape = snext;
 28.2924 +	}
 28.2925 +	free(image);
 28.2926 +}
 28.2927 +
 28.2928 +#endif
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/nanosvgrast.h	Sun Oct 22 00:36:06 2017 -0700
    29.3 @@ -0,0 +1,1447 @@
    29.4 +/*
    29.5 + * Copyright (c) 2013-14 Mikko Mononen memon@inside.org
    29.6 + *
    29.7 + * This software is provided 'as-is', without any express or implied
    29.8 + * warranty.  In no event will the authors be held liable for any damages
    29.9 + * arising from the use of this software.
   29.10 + *
   29.11 + * Permission is granted to anyone to use this software for any purpose,
   29.12 + * including commercial applications, and to alter it and redistribute it
   29.13 + * freely, subject to the following restrictions:
   29.14 + *
   29.15 + * 1. The origin of this software must not be misrepresented; you must not
   29.16 + * claim that you wrote the original software. If you use this software
   29.17 + * in a product, an acknowledgment in the product documentation would be
   29.18 + * appreciated but is not required.
   29.19 + * 2. Altered source versions must be plainly marked as such, and must not be
   29.20 + * misrepresented as being the original software.
   29.21 + * 3. This notice may not be removed or altered from any source distribution.
   29.22 + *
   29.23 + * The polygon rasterization is heavily based on stb_truetype rasterizer
   29.24 + * by Sean Barrett - http://nothings.org/
   29.25 + *
   29.26 + */
   29.27 +
   29.28 +#ifndef NANOSVGRAST_H
   29.29 +#define NANOSVGRAST_H
   29.30 +
   29.31 +#ifdef __cplusplus
   29.32 +extern "C" {
   29.33 +#endif
   29.34 +
   29.35 +typedef struct NSVGrasterizer NSVGrasterizer;
   29.36 +
   29.37 +/* Example Usage:
   29.38 +	// Load SVG
   29.39 +	struct SNVGImage* image = nsvgParseFromFile("test.svg.");
   29.40 +
   29.41 +	// Create rasterizer (can be used to render multiple images).
   29.42 +	struct NSVGrasterizer* rast = nsvgCreateRasterizer();
   29.43 +	// Allocate memory for image
   29.44 +	unsigned char* img = malloc(w*h*4);
   29.45 +	// Rasterize
   29.46 +	nsvgRasterize(rast, image, 0,0,1, img, w, h, w*4);
   29.47 +*/
   29.48 +
   29.49 +// Allocated rasterizer context.
   29.50 +NSVGrasterizer* nsvgCreateRasterizer();
   29.51 +
   29.52 +// Rasterizes SVG image, returns RGBA image (non-premultiplied alpha)
   29.53 +//   r - pointer to rasterizer context
   29.54 +//   image - pointer to image to rasterize
   29.55 +//   tx,ty - image offset (applied after scaling)
   29.56 +//   scale - image scale
   29.57 +//   dst - pointer to destination image data, 4 bytes per pixel (RGBA)
   29.58 +//   w - width of the image to render
   29.59 +//   h - height of the image to render
   29.60 +//   stride - number of bytes per scaleline in the destination buffer
   29.61 +void nsvgRasterize(NSVGrasterizer* r,
   29.62 +				   NSVGimage* image, float tx, float ty, float scale,
   29.63 +				   unsigned char* dst, int w, int h, int stride);
   29.64 +
   29.65 +// Deletes rasterizer context.
   29.66 +void nsvgDeleteRasterizer(NSVGrasterizer*);
   29.67 +
   29.68 +
   29.69 +#ifdef __cplusplus
   29.70 +}
   29.71 +#endif
   29.72 +
   29.73 +#endif // NANOSVGRAST_H
   29.74 +
   29.75 +#ifdef NANOSVGRAST_IMPLEMENTATION
   29.76 +
   29.77 +#include <math.h>
   29.78 +
   29.79 +#define NSVG__SUBSAMPLES	5
   29.80 +#define NSVG__FIXSHIFT		10
   29.81 +#define NSVG__FIX			(1 << NSVG__FIXSHIFT)
   29.82 +#define NSVG__FIXMASK		(NSVG__FIX-1)
   29.83 +#define NSVG__MEMPAGE_SIZE	1024
   29.84 +
   29.85 +typedef struct NSVGedge {
   29.86 +	float x0,y0, x1,y1;
   29.87 +	int dir;
   29.88 +	struct NSVGedge* next;
   29.89 +} NSVGedge;
   29.90 +
   29.91 +typedef struct NSVGpoint {
   29.92 +	float x, y;
   29.93 +	float dx, dy;
   29.94 +	float len;
   29.95 +	float dmx, dmy;
   29.96 +	unsigned char flags;
   29.97 +} NSVGpoint;
   29.98 +
   29.99 +typedef struct NSVGactiveEdge {
  29.100 +	int x,dx;
  29.101 +	float ey;
  29.102 +	int dir;
  29.103 +	struct NSVGactiveEdge *next;
  29.104 +} NSVGactiveEdge;
  29.105 +
  29.106 +typedef struct NSVGmemPage {
  29.107 +	unsigned char mem[NSVG__MEMPAGE_SIZE];
  29.108 +	int size;
  29.109 +	struct NSVGmemPage* next;
  29.110 +} NSVGmemPage;
  29.111 +
  29.112 +typedef struct NSVGcachedPaint {
  29.113 +	char type;
  29.114 +	char spread;
  29.115 +	float xform[6];
  29.116 +	unsigned int colors[256];
  29.117 +} NSVGcachedPaint;
  29.118 +
  29.119 +struct NSVGrasterizer
  29.120 +{
  29.121 +	float px, py;
  29.122 +
  29.123 +	float tessTol;
  29.124 +	float distTol;
  29.125 +
  29.126 +	NSVGedge* edges;
  29.127 +	int nedges;
  29.128 +	int cedges;
  29.129 +
  29.130 +	NSVGpoint* points;
  29.131 +	int npoints;
  29.132 +	int cpoints;
  29.133 +
  29.134 +	NSVGpoint* points2;
  29.135 +	int npoints2;
  29.136 +	int cpoints2;
  29.137 +
  29.138 +	NSVGactiveEdge* freelist;
  29.139 +	NSVGmemPage* pages;
  29.140 +	NSVGmemPage* curpage;
  29.141 +
  29.142 +	unsigned char* scanline;
  29.143 +	int cscanline;
  29.144 +
  29.145 +	unsigned char* bitmap;
  29.146 +	int width, height, stride;
  29.147 +};
  29.148 +
  29.149 +NSVGrasterizer* nsvgCreateRasterizer()
  29.150 +{
  29.151 +	NSVGrasterizer* r = (NSVGrasterizer*)malloc(sizeof(NSVGrasterizer));
  29.152 +	if (r == NULL) goto error;
  29.153 +	memset(r, 0, sizeof(NSVGrasterizer));
  29.154 +
  29.155 +	r->tessTol = 0.25f;
  29.156 +	r->distTol = 0.01f;
  29.157 +
  29.158 +	return r;
  29.159 +
  29.160 +error:
  29.161 +	nsvgDeleteRasterizer(r);
  29.162 +	return NULL;
  29.163 +}
  29.164 +
  29.165 +void nsvgDeleteRasterizer(NSVGrasterizer* r)
  29.166 +{
  29.167 +	NSVGmemPage* p;
  29.168 +
  29.169 +	if (r == NULL) return;
  29.170 +
  29.171 +	p = r->pages;
  29.172 +	while (p != NULL) {
  29.173 +		NSVGmemPage* next = p->next;
  29.174 +		free(p);
  29.175 +		p = next;
  29.176 +	}
  29.177 +
  29.178 +	if (r->edges) free(r->edges);
  29.179 +	if (r->points) free(r->points);
  29.180 +	if (r->points2) free(r->points2);
  29.181 +	if (r->scanline) free(r->scanline);
  29.182 +
  29.183 +	free(r);
  29.184 +}
  29.185 +
  29.186 +static NSVGmemPage* nsvg__nextPage(NSVGrasterizer* r, NSVGmemPage* cur)
  29.187 +{
  29.188 +	NSVGmemPage *newp;
  29.189 +
  29.190 +	// If using existing chain, return the next page in chain
  29.191 +	if (cur != NULL && cur->next != NULL) {
  29.192 +		return cur->next;
  29.193 +	}
  29.194 +
  29.195 +	// Alloc new page
  29.196 +	newp = (NSVGmemPage*)malloc(sizeof(NSVGmemPage));
  29.197 +	if (newp == NULL) return NULL;
  29.198 +	memset(newp, 0, sizeof(NSVGmemPage));
  29.199 +
  29.200 +	// Add to linked list
  29.201 +	if (cur != NULL)
  29.202 +		cur->next = newp;
  29.203 +	else
  29.204 +		r->pages = newp;
  29.205 +
  29.206 +	return newp;
  29.207 +}
  29.208 +
  29.209 +static void nsvg__resetPool(NSVGrasterizer* r)
  29.210 +{
  29.211 +	NSVGmemPage* p = r->pages;
  29.212 +	while (p != NULL) {
  29.213 +		p->size = 0;
  29.214 +		p = p->next;
  29.215 +	}
  29.216 +	r->curpage = r->pages;
  29.217 +}
  29.218 +
  29.219 +static unsigned char* nsvg__alloc(NSVGrasterizer* r, int size)
  29.220 +{
  29.221 +	unsigned char* buf;
  29.222 +	if (size > NSVG__MEMPAGE_SIZE) return NULL;
  29.223 +	if (r->curpage == NULL || r->curpage->size+size > NSVG__MEMPAGE_SIZE) {
  29.224 +		r->curpage = nsvg__nextPage(r, r->curpage);
  29.225 +	}
  29.226 +	buf = &r->curpage->mem[r->curpage->size];
  29.227 +	r->curpage->size += size;
  29.228 +	return buf;
  29.229 +}
  29.230 +
  29.231 +static int nsvg__ptEquals(float x1, float y1, float x2, float y2, float tol)
  29.232 +{
  29.233 +	float dx = x2 - x1;
  29.234 +	float dy = y2 - y1;
  29.235 +	return dx*dx + dy*dy < tol*tol;
  29.236 +}
  29.237 +
  29.238 +static void nsvg__addPathPoint(NSVGrasterizer* r, float x, float y, int flags)
  29.239 +{
  29.240 +	NSVGpoint* pt;
  29.241 +
  29.242 +	if (r->npoints > 0) {
  29.243 +		pt = &r->points[r->npoints-1];
  29.244 +		if (nsvg__ptEquals(pt->x,pt->y, x,y, r->distTol)) {
  29.245 +			pt->flags = (unsigned char)(pt->flags | flags);
  29.246 +			return;
  29.247 +		}
  29.248 +	}
  29.249 +
  29.250 +	if (r->npoints+1 > r->cpoints) {
  29.251 +		r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;
  29.252 +		r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints);
  29.253 +		if (r->points == NULL) return;
  29.254 +	}
  29.255 +
  29.256 +	pt = &r->points[r->npoints];
  29.257 +	pt->x = x;
  29.258 +	pt->y = y;
  29.259 +	pt->flags = (unsigned char)flags;
  29.260 +	r->npoints++;
  29.261 +}
  29.262 +
  29.263 +static void nsvg__appendPathPoint(NSVGrasterizer* r, NSVGpoint pt)
  29.264 +{
  29.265 +	if (r->npoints+1 > r->cpoints) {
  29.266 +		r->cpoints = r->cpoints > 0 ? r->cpoints * 2 : 64;
  29.267 +		r->points = (NSVGpoint*)realloc(r->points, sizeof(NSVGpoint) * r->cpoints);
  29.268 +		if (r->points == NULL) return;
  29.269 +	}
  29.270 +	r->points[r->npoints] = pt;
  29.271 +	r->npoints++;
  29.272 +}
  29.273 +
  29.274 +static void nsvg__duplicatePoints(NSVGrasterizer* r)
  29.275 +{
  29.276 +	if (r->npoints > r->cpoints2) {
  29.277 +		r->cpoints2 = r->npoints;
  29.278 +		r->points2 = (NSVGpoint*)realloc(r->points2, sizeof(NSVGpoint) * r->cpoints2);
  29.279 +		if (r->points2 == NULL) return;
  29.280 +	}
  29.281 +
  29.282 +	memcpy(r->points2, r->points, sizeof(NSVGpoint) * r->npoints);
  29.283 +	r->npoints2 = r->npoints;
  29.284 +}
  29.285 +
  29.286 +static void nsvg__addEdge(NSVGrasterizer* r, float x0, float y0, float x1, float y1)
  29.287 +{
  29.288 +	NSVGedge* e;
  29.289 +
  29.290 +	// Skip horizontal edges
  29.291 +	if (y0 == y1)
  29.292 +		return;
  29.293 +
  29.294 +	if (r->nedges+1 > r->cedges) {
  29.295 +		r->cedges = r->cedges > 0 ? r->cedges * 2 : 64;
  29.296 +		r->edges = (NSVGedge*)realloc(r->edges, sizeof(NSVGedge) * r->cedges);
  29.297 +		if (r->edges == NULL) return;
  29.298 +	}
  29.299 +
  29.300 +	e = &r->edges[r->nedges];
  29.301 +	r->nedges++;
  29.302 +
  29.303 +	if (y0 < y1) {
  29.304 +		e->x0 = x0;
  29.305 +		e->y0 = y0;
  29.306 +		e->x1 = x1;
  29.307 +		e->y1 = y1;
  29.308 +		e->dir = 1;
  29.309 +	} else {
  29.310 +		e->x0 = x1;
  29.311 +		e->y0 = y1;
  29.312 +		e->x1 = x0;
  29.313 +		e->y1 = y0;
  29.314 +		e->dir = -1;
  29.315 +	}
  29.316 +}
  29.317 +
  29.318 +static float nsvg__normalize(float *x, float* y)
  29.319 +{
  29.320 +	float d = sqrtf((*x)*(*x) + (*y)*(*y));
  29.321 +	if (d > 1e-6f) {
  29.322 +		float id = 1.0f / d;
  29.323 +		*x *= id;
  29.324 +		*y *= id;
  29.325 +	}
  29.326 +	return d;
  29.327 +}
  29.328 +
  29.329 +static float nsvg__absf(float x) { return x < 0 ? -x : x; }
  29.330 +
  29.331 +static void nsvg__flattenCubicBez(NSVGrasterizer* r,
  29.332 +								  float x1, float y1, float x2, float y2,
  29.333 +								  float x3, float y3, float x4, float y4,
  29.334 +								  int level, int type)
  29.335 +{
  29.336 +	float x12,y12,x23,y23,x34,y34,x123,y123,x234,y234,x1234,y1234;
  29.337 +	float dx,dy,d2,d3;
  29.338 +
  29.339 +	if (level > 10) return;
  29.340 +
  29.341 +	x12 = (x1+x2)*0.5f;
  29.342 +	y12 = (y1+y2)*0.5f;
  29.343 +	x23 = (x2+x3)*0.5f;
  29.344 +	y23 = (y2+y3)*0.5f;
  29.345 +	x34 = (x3+x4)*0.5f;
  29.346 +	y34 = (y3+y4)*0.5f;
  29.347 +	x123 = (x12+x23)*0.5f;
  29.348 +	y123 = (y12+y23)*0.5f;
  29.349 +
  29.350 +	dx = x4 - x1;
  29.351 +	dy = y4 - y1;
  29.352 +	d2 = nsvg__absf(((x2 - x4) * dy - (y2 - y4) * dx));
  29.353 +	d3 = nsvg__absf(((x3 - x4) * dy - (y3 - y4) * dx));
  29.354 +
  29.355 +	if ((d2 + d3)*(d2 + d3) < r->tessTol * (dx*dx + dy*dy)) {
  29.356 +		nsvg__addPathPoint(r, x4, y4, type);
  29.357 +		return;
  29.358 +	}
  29.359 +
  29.360 +	x234 = (x23+x34)*0.5f;
  29.361 +	y234 = (y23+y34)*0.5f;
  29.362 +	x1234 = (x123+x234)*0.5f;
  29.363 +	y1234 = (y123+y234)*0.5f;
  29.364 +
  29.365 +	nsvg__flattenCubicBez(r, x1,y1, x12,y12, x123,y123, x1234,y1234, level+1, 0);
  29.366 +	nsvg__flattenCubicBez(r, x1234,y1234, x234,y234, x34,y34, x4,y4, level+1, type);
  29.367 +}
  29.368 +
  29.369 +static void nsvg__flattenShape(NSVGrasterizer* r, NSVGshape* shape, float scale)
  29.370 +{
  29.371 +	int i, j;
  29.372 +	NSVGpath* path;
  29.373 +
  29.374 +	for (path = shape->paths; path != NULL; path = path->next) {
  29.375 +		r->npoints = 0;
  29.376 +		// Flatten path
  29.377 +		nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0);
  29.378 +		for (i = 0; i < path->npts-1; i += 3) {
  29.379 +			float* p = &path->pts[i*2];
  29.380 +			nsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, 0);
  29.381 +		}
  29.382 +		// Close path
  29.383 +		nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, 0);
  29.384 +		// Build edges
  29.385 +		for (i = 0, j = r->npoints-1; i < r->npoints; j = i++)
  29.386 +			nsvg__addEdge(r, r->points[j].x, r->points[j].y, r->points[i].x, r->points[i].y);
  29.387 +	}
  29.388 +}
  29.389 +
  29.390 +enum NSVGpointFlags
  29.391 +{
  29.392 +	NSVG_PT_CORNER = 0x01,
  29.393 +	NSVG_PT_BEVEL = 0x02,
  29.394 +	NSVG_PT_LEFT = 0x04
  29.395 +};
  29.396 +
  29.397 +static void nsvg__initClosed(NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
  29.398 +{
  29.399 +	float w = lineWidth * 0.5f;
  29.400 +	float dx = p1->x - p0->x;
  29.401 +	float dy = p1->y - p0->y;
  29.402 +	float len = nsvg__normalize(&dx, &dy);
  29.403 +	float px = p0->x + dx*len*0.5f, py = p0->y + dy*len*0.5f;
  29.404 +	float dlx = dy, dly = -dx;
  29.405 +	float lx = px - dlx*w, ly = py - dly*w;
  29.406 +	float rx = px + dlx*w, ry = py + dly*w;
  29.407 +	left->x = lx; left->y = ly;
  29.408 +	right->x = rx; right->y = ry;
  29.409 +}
  29.410 +
  29.411 +static void nsvg__buttCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect)
  29.412 +{
  29.413 +	float w = lineWidth * 0.5f;
  29.414 +	float px = p->x, py = p->y;
  29.415 +	float dlx = dy, dly = -dx;
  29.416 +	float lx = px - dlx*w, ly = py - dly*w;
  29.417 +	float rx = px + dlx*w, ry = py + dly*w;
  29.418 +
  29.419 +	nsvg__addEdge(r, lx, ly, rx, ry);
  29.420 +
  29.421 +	if (connect) {
  29.422 +		nsvg__addEdge(r, left->x, left->y, lx, ly);
  29.423 +		nsvg__addEdge(r, rx, ry, right->x, right->y);
  29.424 +	}
  29.425 +	left->x = lx; left->y = ly;
  29.426 +	right->x = rx; right->y = ry;
  29.427 +}
  29.428 +
  29.429 +static void nsvg__squareCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int connect)
  29.430 +{
  29.431 +	float w = lineWidth * 0.5f;
  29.432 +	float px = p->x - dx*w, py = p->y - dy*w;
  29.433 +	float dlx = dy, dly = -dx;
  29.434 +	float lx = px - dlx*w, ly = py - dly*w;
  29.435 +	float rx = px + dlx*w, ry = py + dly*w;
  29.436 +
  29.437 +	nsvg__addEdge(r, lx, ly, rx, ry);
  29.438 +
  29.439 +	if (connect) {
  29.440 +		nsvg__addEdge(r, left->x, left->y, lx, ly);
  29.441 +		nsvg__addEdge(r, rx, ry, right->x, right->y);
  29.442 +	}
  29.443 +	left->x = lx; left->y = ly;
  29.444 +	right->x = rx; right->y = ry;
  29.445 +}
  29.446 +
  29.447 +#ifndef NSVG_PI
  29.448 +#define NSVG_PI (3.14159265358979323846264338327f)
  29.449 +#endif
  29.450 +
  29.451 +static void nsvg__roundCap(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p, float dx, float dy, float lineWidth, int ncap, int connect)
  29.452 +{
  29.453 +	int i;
  29.454 +	float w = lineWidth * 0.5f;
  29.455 +	float px = p->x, py = p->y;
  29.456 +	float dlx = dy, dly = -dx;
  29.457 +	float lx = 0, ly = 0, rx = 0, ry = 0, prevx = 0, prevy = 0;
  29.458 +
  29.459 +	for (i = 0; i < ncap; i++) {
  29.460 +		float a = (float)i/(float)(ncap-1)*NSVG_PI;
  29.461 +		float ax = cosf(a) * w, ay = sinf(a) * w;
  29.462 +		float x = px - dlx*ax - dx*ay;
  29.463 +		float y = py - dly*ax - dy*ay;
  29.464 +
  29.465 +		if (i > 0)
  29.466 +			nsvg__addEdge(r, prevx, prevy, x, y);
  29.467 +
  29.468 +		prevx = x;
  29.469 +		prevy = y;
  29.470 +
  29.471 +		if (i == 0) {
  29.472 +			lx = x; ly = y;
  29.473 +		} else if (i == ncap-1) {
  29.474 +			rx = x; ry = y;
  29.475 +		}
  29.476 +	}
  29.477 +
  29.478 +	if (connect) {
  29.479 +		nsvg__addEdge(r, left->x, left->y, lx, ly);
  29.480 +		nsvg__addEdge(r, rx, ry, right->x, right->y);
  29.481 +	}
  29.482 +
  29.483 +	left->x = lx; left->y = ly;
  29.484 +	right->x = rx; right->y = ry;
  29.485 +}
  29.486 +
  29.487 +static void nsvg__bevelJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
  29.488 +{
  29.489 +	float w = lineWidth * 0.5f;
  29.490 +	float dlx0 = p0->dy, dly0 = -p0->dx;
  29.491 +	float dlx1 = p1->dy, dly1 = -p1->dx;
  29.492 +	float lx0 = p1->x - (dlx0 * w), ly0 = p1->y - (dly0 * w);
  29.493 +	float rx0 = p1->x + (dlx0 * w), ry0 = p1->y + (dly0 * w);
  29.494 +	float lx1 = p1->x - (dlx1 * w), ly1 = p1->y - (dly1 * w);
  29.495 +	float rx1 = p1->x + (dlx1 * w), ry1 = p1->y + (dly1 * w);
  29.496 +
  29.497 +	nsvg__addEdge(r, lx0, ly0, left->x, left->y);
  29.498 +	nsvg__addEdge(r, lx1, ly1, lx0, ly0);
  29.499 +
  29.500 +	nsvg__addEdge(r, right->x, right->y, rx0, ry0);
  29.501 +	nsvg__addEdge(r, rx0, ry0, rx1, ry1);
  29.502 +
  29.503 +	left->x = lx1; left->y = ly1;
  29.504 +	right->x = rx1; right->y = ry1;
  29.505 +}
  29.506 +
  29.507 +static void nsvg__miterJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth)
  29.508 +{
  29.509 +	float w = lineWidth * 0.5f;
  29.510 +	float dlx0 = p0->dy, dly0 = -p0->dx;
  29.511 +	float dlx1 = p1->dy, dly1 = -p1->dx;
  29.512 +	float lx0, rx0, lx1, rx1;
  29.513 +	float ly0, ry0, ly1, ry1;
  29.514 +
  29.515 +	if (p1->flags & NSVG_PT_LEFT) {
  29.516 +		lx0 = lx1 = p1->x - p1->dmx * w;
  29.517 +		ly0 = ly1 = p1->y - p1->dmy * w;
  29.518 +		nsvg__addEdge(r, lx1, ly1, left->x, left->y);
  29.519 +
  29.520 +		rx0 = p1->x + (dlx0 * w);
  29.521 +		ry0 = p1->y + (dly0 * w);
  29.522 +		rx1 = p1->x + (dlx1 * w);
  29.523 +		ry1 = p1->y + (dly1 * w);
  29.524 +		nsvg__addEdge(r, right->x, right->y, rx0, ry0);
  29.525 +		nsvg__addEdge(r, rx0, ry0, rx1, ry1);
  29.526 +	} else {
  29.527 +		lx0 = p1->x - (dlx0 * w);
  29.528 +		ly0 = p1->y - (dly0 * w);
  29.529 +		lx1 = p1->x - (dlx1 * w);
  29.530 +		ly1 = p1->y - (dly1 * w);
  29.531 +		nsvg__addEdge(r, lx0, ly0, left->x, left->y);
  29.532 +		nsvg__addEdge(r, lx1, ly1, lx0, ly0);
  29.533 +
  29.534 +		rx0 = rx1 = p1->x + p1->dmx * w;
  29.535 +		ry0 = ry1 = p1->y + p1->dmy * w;
  29.536 +		nsvg__addEdge(r, right->x, right->y, rx1, ry1);
  29.537 +	}
  29.538 +
  29.539 +	left->x = lx1; left->y = ly1;
  29.540 +	right->x = rx1; right->y = ry1;
  29.541 +}
  29.542 +
  29.543 +static void nsvg__roundJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p0, NSVGpoint* p1, float lineWidth, int ncap)
  29.544 +{
  29.545 +	int i, n;
  29.546 +	float w = lineWidth * 0.5f;
  29.547 +	float dlx0 = p0->dy, dly0 = -p0->dx;
  29.548 +	float dlx1 = p1->dy, dly1 = -p1->dx;
  29.549 +	float a0 = atan2f(dly0, dlx0);
  29.550 +	float a1 = atan2f(dly1, dlx1);
  29.551 +	float da = a1 - a0;
  29.552 +	float lx, ly, rx, ry;
  29.553 +
  29.554 +	if (da < NSVG_PI) da += NSVG_PI*2;
  29.555 +	if (da > NSVG_PI) da -= NSVG_PI*2;
  29.556 +
  29.557 +	n = (int)ceilf((nsvg__absf(da) / NSVG_PI) * (float)ncap);
  29.558 +	if (n < 2) n = 2;
  29.559 +	if (n > ncap) n = ncap;
  29.560 +
  29.561 +	lx = left->x;
  29.562 +	ly = left->y;
  29.563 +	rx = right->x;
  29.564 +	ry = right->y;
  29.565 +
  29.566 +	for (i = 0; i < n; i++) {
  29.567 +		float u = (float)i/(float)(n-1);
  29.568 +		float a = a0 + u*da;
  29.569 +		float ax = cosf(a) * w, ay = sinf(a) * w;
  29.570 +		float lx1 = p1->x - ax, ly1 = p1->y - ay;
  29.571 +		float rx1 = p1->x + ax, ry1 = p1->y + ay;
  29.572 +
  29.573 +		nsvg__addEdge(r, lx1, ly1, lx, ly);
  29.574 +		nsvg__addEdge(r, rx, ry, rx1, ry1);
  29.575 +
  29.576 +		lx = lx1; ly = ly1;
  29.577 +		rx = rx1; ry = ry1;
  29.578 +	}
  29.579 +
  29.580 +	left->x = lx; left->y = ly;
  29.581 +	right->x = rx; right->y = ry;
  29.582 +}
  29.583 +
  29.584 +static void nsvg__straightJoin(NSVGrasterizer* r, NSVGpoint* left, NSVGpoint* right, NSVGpoint* p1, float lineWidth)
  29.585 +{
  29.586 +	float w = lineWidth * 0.5f;
  29.587 +	float lx = p1->x - (p1->dmx * w), ly = p1->y - (p1->dmy * w);
  29.588 +	float rx = p1->x + (p1->dmx * w), ry = p1->y + (p1->dmy * w);
  29.589 +
  29.590 +	nsvg__addEdge(r, lx, ly, left->x, left->y);
  29.591 +	nsvg__addEdge(r, right->x, right->y, rx, ry);
  29.592 +
  29.593 +	left->x = lx; left->y = ly;
  29.594 +	right->x = rx; right->y = ry;
  29.595 +}
  29.596 +
  29.597 +static int nsvg__curveDivs(float r, float arc, float tol)
  29.598 +{
  29.599 +	float da = acosf(r / (r + tol)) * 2.0f;
  29.600 +	int divs = (int)ceilf(arc / da);
  29.601 +	if (divs < 2) divs = 2;
  29.602 +	return divs;
  29.603 +}
  29.604 +
  29.605 +static void nsvg__expandStroke(NSVGrasterizer* r, NSVGpoint* points, int npoints, int closed, int lineJoin, int lineCap, float lineWidth)
  29.606 +{
  29.607 +	int ncap = nsvg__curveDivs(lineWidth*0.5f, NSVG_PI, r->tessTol);	// Calculate divisions per half circle.
  29.608 +	NSVGpoint left = {0,0,0,0,0,0,0,0}, right = {0,0,0,0,0,0,0,0}, firstLeft = {0,0,0,0,0,0,0,0}, firstRight = {0,0,0,0,0,0,0,0};
  29.609 +	NSVGpoint* p0, *p1;
  29.610 +	int j, s, e;
  29.611 +
  29.612 +	// Build stroke edges
  29.613 +	if (closed) {
  29.614 +		// Looping
  29.615 +		p0 = &points[npoints-1];
  29.616 +		p1 = &points[0];
  29.617 +		s = 0;
  29.618 +		e = npoints;
  29.619 +	} else {
  29.620 +		// Add cap
  29.621 +		p0 = &points[0];
  29.622 +		p1 = &points[1];
  29.623 +		s = 1;
  29.624 +		e = npoints-1;
  29.625 +	}
  29.626 +
  29.627 +	if (closed) {
  29.628 +		nsvg__initClosed(&left, &right, p0, p1, lineWidth);
  29.629 +		firstLeft = left;
  29.630 +		firstRight = right;
  29.631 +	} else {
  29.632 +		// Add cap
  29.633 +		float dx = p1->x - p0->x;
  29.634 +		float dy = p1->y - p0->y;
  29.635 +		nsvg__normalize(&dx, &dy);
  29.636 +		if (lineCap == NSVG_CAP_BUTT)
  29.637 +			nsvg__buttCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
  29.638 +		else if (lineCap == NSVG_CAP_SQUARE)
  29.639 +			nsvg__squareCap(r, &left, &right, p0, dx, dy, lineWidth, 0);
  29.640 +		else if (lineCap == NSVG_CAP_ROUND)
  29.641 +			nsvg__roundCap(r, &left, &right, p0, dx, dy, lineWidth, ncap, 0);
  29.642 +	}
  29.643 +
  29.644 +	for (j = s; j < e; ++j) {
  29.645 +		if (p1->flags & NSVG_PT_CORNER) {
  29.646 +			if (lineJoin == NSVG_JOIN_ROUND)
  29.647 +				nsvg__roundJoin(r, &left, &right, p0, p1, lineWidth, ncap);
  29.648 +			else if (lineJoin == NSVG_JOIN_BEVEL || (p1->flags & NSVG_PT_BEVEL))
  29.649 +				nsvg__bevelJoin(r, &left, &right, p0, p1, lineWidth);
  29.650 +			else
  29.651 +				nsvg__miterJoin(r, &left, &right, p0, p1, lineWidth);
  29.652 +		} else {
  29.653 +			nsvg__straightJoin(r, &left, &right, p1, lineWidth);
  29.654 +		}
  29.655 +		p0 = p1++;
  29.656 +	}
  29.657 +
  29.658 +	if (closed) {
  29.659 +		// Loop it
  29.660 +		nsvg__addEdge(r, firstLeft.x, firstLeft.y, left.x, left.y);
  29.661 +		nsvg__addEdge(r, right.x, right.y, firstRight.x, firstRight.y);
  29.662 +	} else {
  29.663 +		// Add cap
  29.664 +		float dx = p1->x - p0->x;
  29.665 +		float dy = p1->y - p0->y;
  29.666 +		nsvg__normalize(&dx, &dy);
  29.667 +		if (lineCap == NSVG_CAP_BUTT)
  29.668 +			nsvg__buttCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
  29.669 +		else if (lineCap == NSVG_CAP_SQUARE)
  29.670 +			nsvg__squareCap(r, &right, &left, p1, -dx, -dy, lineWidth, 1);
  29.671 +		else if (lineCap == NSVG_CAP_ROUND)
  29.672 +			nsvg__roundCap(r, &right, &left, p1, -dx, -dy, lineWidth, ncap, 1);
  29.673 +	}
  29.674 +}
  29.675 +
  29.676 +static void nsvg__prepareStroke(NSVGrasterizer* r, float miterLimit, int lineJoin)
  29.677 +{
  29.678 +	int i, j;
  29.679 +	NSVGpoint* p0, *p1;
  29.680 +
  29.681 +	p0 = &r->points[r->npoints-1];
  29.682 +	p1 = &r->points[0];
  29.683 +	for (i = 0; i < r->npoints; i++) {
  29.684 +		// Calculate segment direction and length
  29.685 +		p0->dx = p1->x - p0->x;
  29.686 +		p0->dy = p1->y - p0->y;
  29.687 +		p0->len = nsvg__normalize(&p0->dx, &p0->dy);
  29.688 +		// Advance
  29.689 +		p0 = p1++;
  29.690 +	}
  29.691 +
  29.692 +	// calculate joins
  29.693 +	p0 = &r->points[r->npoints-1];
  29.694 +	p1 = &r->points[0];
  29.695 +	for (j = 0; j < r->npoints; j++) {
  29.696 +		float dlx0, dly0, dlx1, dly1, dmr2, cross;
  29.697 +		dlx0 = p0->dy;
  29.698 +		dly0 = -p0->dx;
  29.699 +		dlx1 = p1->dy;
  29.700 +		dly1 = -p1->dx;
  29.701 +		// Calculate extrusions
  29.702 +		p1->dmx = (dlx0 + dlx1) * 0.5f;
  29.703 +		p1->dmy = (dly0 + dly1) * 0.5f;
  29.704 +		dmr2 = p1->dmx*p1->dmx + p1->dmy*p1->dmy;
  29.705 +		if (dmr2 > 0.000001f) {
  29.706 +			float s2 = 1.0f / dmr2;
  29.707 +			if (s2 > 600.0f) {
  29.708 +				s2 = 600.0f;
  29.709 +			}
  29.710 +			p1->dmx *= s2;
  29.711 +			p1->dmy *= s2;
  29.712 +		}
  29.713 +
  29.714 +		// Clear flags, but keep the corner.
  29.715 +		p1->flags = (p1->flags & NSVG_PT_CORNER) ? NSVG_PT_CORNER : 0;
  29.716 +
  29.717 +		// Keep track of left turns.
  29.718 +		cross = p1->dx * p0->dy - p0->dx * p1->dy;
  29.719 +		if (cross > 0.0f)
  29.720 +			p1->flags |= NSVG_PT_LEFT;
  29.721 +
  29.722 +		// Check to see if the corner needs to be beveled.
  29.723 +		if (p1->flags & NSVG_PT_CORNER) {
  29.724 +			if ((dmr2 * miterLimit*miterLimit) < 1.0f || lineJoin == NSVG_JOIN_BEVEL || lineJoin == NSVG_JOIN_ROUND) {
  29.725 +				p1->flags |= NSVG_PT_BEVEL;
  29.726 +			}
  29.727 +		}
  29.728 +
  29.729 +		p0 = p1++;
  29.730 +	}
  29.731 +}
  29.732 +
  29.733 +static void nsvg__flattenShapeStroke(NSVGrasterizer* r, NSVGshape* shape, float scale)
  29.734 +{
  29.735 +	int i, j, closed;
  29.736 +	NSVGpath* path;
  29.737 +	NSVGpoint* p0, *p1;
  29.738 +	float miterLimit = shape->miterLimit;
  29.739 +	int lineJoin = shape->strokeLineJoin;
  29.740 +	int lineCap = shape->strokeLineCap;
  29.741 +	float lineWidth = shape->strokeWidth * scale;
  29.742 +
  29.743 +	for (path = shape->paths; path != NULL; path = path->next) {
  29.744 +		// Flatten path
  29.745 +		r->npoints = 0;
  29.746 +		nsvg__addPathPoint(r, path->pts[0]*scale, path->pts[1]*scale, NSVG_PT_CORNER);
  29.747 +		for (i = 0; i < path->npts-1; i += 3) {
  29.748 +			float* p = &path->pts[i*2];
  29.749 +			nsvg__flattenCubicBez(r, p[0]*scale,p[1]*scale, p[2]*scale,p[3]*scale, p[4]*scale,p[5]*scale, p[6]*scale,p[7]*scale, 0, NSVG_PT_CORNER);
  29.750 +		}
  29.751 +		if (r->npoints < 2)
  29.752 +			continue;
  29.753 +
  29.754 +		closed = path->closed;
  29.755 +
  29.756 +		// If the first and last points are the same, remove the last, mark as closed path.
  29.757 +		p0 = &r->points[r->npoints-1];
  29.758 +		p1 = &r->points[0];
  29.759 +		if (nsvg__ptEquals(p0->x,p0->y, p1->x,p1->y, r->distTol)) {
  29.760 +			r->npoints--;
  29.761 +			p0 = &r->points[r->npoints-1];
  29.762 +			closed = 1;
  29.763 +		}
  29.764 +
  29.765 +		if (shape->strokeDashCount > 0) {
  29.766 +			int idash = 0, dashState = 1;
  29.767 +			float totalDist = 0, dashLen, allDashLen, dashOffset;
  29.768 +			NSVGpoint cur;
  29.769 +
  29.770 +			if (closed)
  29.771 +				nsvg__appendPathPoint(r, r->points[0]);
  29.772 +
  29.773 +			// Duplicate points -> points2.
  29.774 +			nsvg__duplicatePoints(r);
  29.775 +
  29.776 +			r->npoints = 0;
  29.777 + 			cur = r->points2[0];
  29.778 +			nsvg__appendPathPoint(r, cur);
  29.779 +
  29.780 +			// Figure out dash offset.
  29.781 +			allDashLen = 0;
  29.782 +			for (j = 0; j < shape->strokeDashCount; j++)
  29.783 +				allDashLen += shape->strokeDashArray[j];
  29.784 +			if (shape->strokeDashCount & 1)
  29.785 +				allDashLen *= 2.0f;
  29.786 +			// Find location inside pattern
  29.787 +			dashOffset = fmodf(shape->strokeDashOffset, allDashLen);
  29.788 +			if (dashOffset < 0.0f)
  29.789 +				dashOffset += allDashLen;
  29.790 +
  29.791 +			while (dashOffset > shape->strokeDashArray[idash]) {
  29.792 +				dashOffset -= shape->strokeDashArray[idash];
  29.793 +				idash = (idash + 1) % shape->strokeDashCount;
  29.794 +			}
  29.795 +			dashLen = (shape->strokeDashArray[idash] - dashOffset) * scale;
  29.796 +
  29.797 +			for (j = 1; j < r->npoints2; ) {
  29.798 +				float dx = r->points2[j].x - cur.x;
  29.799 +				float dy = r->points2[j].y - cur.y;
  29.800 +				float dist = sqrtf(dx*dx + dy*dy);
  29.801 +
  29.802 +				if ((totalDist + dist) > dashLen) {
  29.803 +					// Calculate intermediate point
  29.804 +					float d = (dashLen - totalDist) / dist;
  29.805 +					float x = cur.x + dx * d;
  29.806 +					float y = cur.y + dy * d;
  29.807 +					nsvg__addPathPoint(r, x, y, NSVG_PT_CORNER);
  29.808 +
  29.809 +					// Stroke
  29.810 +					if (r->npoints > 1 && dashState) {
  29.811 +						nsvg__prepareStroke(r, miterLimit, lineJoin);
  29.812 +						nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
  29.813 +					}
  29.814 +					// Advance dash pattern
  29.815 +					dashState = !dashState;
  29.816 +					idash = (idash+1) % shape->strokeDashCount;
  29.817 +					dashLen = shape->strokeDashArray[idash] * scale;
  29.818 +					// Restart
  29.819 +					cur.x = x;
  29.820 +					cur.y = y;
  29.821 +					cur.flags = NSVG_PT_CORNER;
  29.822 +					totalDist = 0.0f;
  29.823 +					r->npoints = 0;
  29.824 +					nsvg__appendPathPoint(r, cur);
  29.825 +				} else {
  29.826 +					totalDist += dist;
  29.827 +					cur = r->points2[j];
  29.828 +					nsvg__appendPathPoint(r, cur);
  29.829 +					j++;
  29.830 +				}
  29.831 +			}
  29.832 +			// Stroke any leftover path
  29.833 +			if (r->npoints > 1 && dashState)
  29.834 +				nsvg__expandStroke(r, r->points, r->npoints, 0, lineJoin, lineCap, lineWidth);
  29.835 +		} else {
  29.836 +			nsvg__prepareStroke(r, miterLimit, lineJoin);
  29.837 +			nsvg__expandStroke(r, r->points, r->npoints, closed, lineJoin, lineCap, lineWidth);
  29.838 +		}
  29.839 +	}
  29.840 +}
  29.841 +
  29.842 +static int nsvg__cmpEdge(const void *p, const void *q)
  29.843 +{
  29.844 +	const NSVGedge* a = (const NSVGedge*)p;
  29.845 +	const NSVGedge* b = (const NSVGedge*)q;
  29.846 +
  29.847 +	if (a->y0 < b->y0) return -1;
  29.848 +	if (a->y0 > b->y0) return  1;
  29.849 +	return 0;
  29.850 +}
  29.851 +
  29.852 +
  29.853 +static NSVGactiveEdge* nsvg__addActive(NSVGrasterizer* r, NSVGedge* e, float startPoint)
  29.854 +{
  29.855 +	 NSVGactiveEdge* z;
  29.856 +
  29.857 +	if (r->freelist != NULL) {
  29.858 +		// Restore from freelist.
  29.859 +		z = r->freelist;
  29.860 +		r->freelist = z->next;
  29.861 +	} else {
  29.862 +		// Alloc new edge.
  29.863 +		z = (NSVGactiveEdge*)nsvg__alloc(r, sizeof(NSVGactiveEdge));
  29.864 +		if (z == NULL) return NULL;
  29.865 +	}
  29.866 +
  29.867 +	float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
  29.868 +//	STBTT_assert(e->y0 <= start_point);
  29.869 +	// round dx down to avoid going too far
  29.870 +	if (dxdy < 0)
  29.871 +		z->dx = (int)(-floorf(NSVG__FIX * -dxdy));
  29.872 +	else
  29.873 +		z->dx = (int)floorf(NSVG__FIX * dxdy);
  29.874 +	z->x = (int)floorf(NSVG__FIX * (e->x0 + dxdy * (startPoint - e->y0)));
  29.875 +//	z->x -= off_x * FIX;
  29.876 +	z->ey = e->y1;
  29.877 +	z->next = 0;
  29.878 +	z->dir = e->dir;
  29.879 +
  29.880 +	return z;
  29.881 +}
  29.882 +
  29.883 +static void nsvg__freeActive(NSVGrasterizer* r, NSVGactiveEdge* z)
  29.884 +{
  29.885 +	z->next = r->freelist;
  29.886 +	r->freelist = z;
  29.887 +}
  29.888 +
  29.889 +static void nsvg__fillScanline(unsigned char* scanline, int len, int x0, int x1, int maxWeight, int* xmin, int* xmax)
  29.890 +{
  29.891 +	int i = x0 >> NSVG__FIXSHIFT;
  29.892 +	int j = x1 >> NSVG__FIXSHIFT;
  29.893 +	if (i < *xmin) *xmin = i;
  29.894 +	if (j > *xmax) *xmax = j;
  29.895 +	if (i < len && j >= 0) {
  29.896 +		if (i == j) {
  29.897 +			// x0,x1 are the same pixel, so compute combined coverage
  29.898 +			scanline[i] = (unsigned char)(scanline[i] + ((x1 - x0) * maxWeight >> NSVG__FIXSHIFT));
  29.899 +		} else {
  29.900 +			if (i >= 0) // add antialiasing for x0
  29.901 +				scanline[i] = (unsigned char)(scanline[i] + (((NSVG__FIX - (x0 & NSVG__FIXMASK)) * maxWeight) >> NSVG__FIXSHIFT));
  29.902 +			else
  29.903 +				i = -1; // clip
  29.904 +
  29.905 +			if (j < len) // add antialiasing for x1
  29.906 +				scanline[j] = (unsigned char)(scanline[j] + (((x1 & NSVG__FIXMASK) * maxWeight) >> NSVG__FIXSHIFT));
  29.907 +			else
  29.908 +				j = len; // clip
  29.909 +
  29.910 +			for (++i; i < j; ++i) // fill pixels between x0 and x1
  29.911 +				scanline[i] = (unsigned char)(scanline[i] + maxWeight);
  29.912 +		}
  29.913 +	}
  29.914 +}
  29.915 +
  29.916 +// note: this routine clips fills that extend off the edges... ideally this
  29.917 +// wouldn't happen, but it could happen if the truetype glyph bounding boxes
  29.918 +// are wrong, or if the user supplies a too-small bitmap
  29.919 +static void nsvg__fillActiveEdges(unsigned char* scanline, int len, NSVGactiveEdge* e, int maxWeight, int* xmin, int* xmax, char fillRule)
  29.920 +{
  29.921 +	// non-zero winding fill
  29.922 +	int x0 = 0, w = 0;
  29.923 +
  29.924 +	if (fillRule == NSVG_FILLRULE_NONZERO) {
  29.925 +		// Non-zero
  29.926 +		while (e != NULL) {
  29.927 +			if (w == 0) {
  29.928 +				// if we're currently at zero, we need to record the edge start point
  29.929 +				x0 = e->x; w += e->dir;
  29.930 +			} else {
  29.931 +				int x1 = e->x; w += e->dir;
  29.932 +				// if we went to zero, we need to draw
  29.933 +				if (w == 0)
  29.934 +					nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);
  29.935 +			}
  29.936 +			e = e->next;
  29.937 +		}
  29.938 +	} else if (fillRule == NSVG_FILLRULE_EVENODD) {
  29.939 +		// Even-odd
  29.940 +		while (e != NULL) {
  29.941 +			if (w == 0) {
  29.942 +				// if we're currently at zero, we need to record the edge start point
  29.943 +				x0 = e->x; w = 1;
  29.944 +			} else {
  29.945 +				int x1 = e->x; w = 0;
  29.946 +				nsvg__fillScanline(scanline, len, x0, x1, maxWeight, xmin, xmax);
  29.947 +			}
  29.948 +			e = e->next;
  29.949 +		}
  29.950 +	}
  29.951 +}
  29.952 +
  29.953 +static float nsvg__clampf(float a, float mn, float mx) { return a < mn ? mn : (a > mx ? mx : a); }
  29.954 +
  29.955 +static unsigned int nsvg__RGBA(unsigned char r, unsigned char g, unsigned char b, unsigned char a)
  29.956 +{
  29.957 +	return (r) | (g << 8) | (b << 16) | (a << 24);
  29.958 +}
  29.959 +
  29.960 +static unsigned int nsvg__lerpRGBA(unsigned int c0, unsigned int c1, float u)
  29.961 +{
  29.962 +	int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
  29.963 +	int r = (((c0) & 0xff)*(256-iu) + (((c1) & 0xff)*iu)) >> 8;
  29.964 +	int g = (((c0>>8) & 0xff)*(256-iu) + (((c1>>8) & 0xff)*iu)) >> 8;
  29.965 +	int b = (((c0>>16) & 0xff)*(256-iu) + (((c1>>16) & 0xff)*iu)) >> 8;
  29.966 +	int a = (((c0>>24) & 0xff)*(256-iu) + (((c1>>24) & 0xff)*iu)) >> 8;
  29.967 +	return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);
  29.968 +}
  29.969 +
  29.970 +static unsigned int nsvg__applyOpacity(unsigned int c, float u)
  29.971 +{
  29.972 +	int iu = (int)(nsvg__clampf(u, 0.0f, 1.0f) * 256.0f);
  29.973 +	int r = (c) & 0xff;
  29.974 +	int g = (c>>8) & 0xff;
  29.975 +	int b = (c>>16) & 0xff;
  29.976 +	int a = (((c>>24) & 0xff)*iu) >> 8;
  29.977 +	return nsvg__RGBA((unsigned char)r, (unsigned char)g, (unsigned char)b, (unsigned char)a);
  29.978 +}
  29.979 +
  29.980 +static inline int nsvg__div255(int x)
  29.981 +{
  29.982 +    return ((x+1) * 257) >> 16;
  29.983 +}
  29.984 +
  29.985 +static void nsvg__scanlineSolid(unsigned char* dst, int count, unsigned char* cover, int x, int y,
  29.986 +								float tx, float ty, float scale, NSVGcachedPaint* cache)
  29.987 +{
  29.988 +
  29.989 +	if (cache->type == NSVG_PAINT_COLOR) {
  29.990 +		int i, cr, cg, cb, ca;
  29.991 +		cr = cache->colors[0] & 0xff;
  29.992 +		cg = (cache->colors[0] >> 8) & 0xff;
  29.993 +		cb = (cache->colors[0] >> 16) & 0xff;
  29.994 +		ca = (cache->colors[0] >> 24) & 0xff;
  29.995 +
  29.996 +		for (i = 0; i < count; i++) {
  29.997 +			int r,g,b;
  29.998 +			int a = nsvg__div255((int)cover[0] * ca);
  29.999 +			int ia = 255 - a;
 29.1000 +			// Premultiply
 29.1001 +			r = nsvg__div255(cr * a);
 29.1002 +			g = nsvg__div255(cg * a);
 29.1003 +			b = nsvg__div255(cb * a);
 29.1004 +
 29.1005 +			// Blend over
 29.1006 +			r += nsvg__div255(ia * (int)dst[0]);
 29.1007 +			g += nsvg__div255(ia * (int)dst[1]);
 29.1008 +			b += nsvg__div255(ia * (int)dst[2]);
 29.1009 +			a += nsvg__div255(ia * (int)dst[3]);
 29.1010 +
 29.1011 +			dst[0] = (unsigned char)r;
 29.1012 +			dst[1] = (unsigned char)g;
 29.1013 +			dst[2] = (unsigned char)b;
 29.1014 +			dst[3] = (unsigned char)a;
 29.1015 +
 29.1016 +			cover++;
 29.1017 +			dst += 4;
 29.1018 +		}
 29.1019 +	} else if (cache->type == NSVG_PAINT_LINEAR_GRADIENT) {
 29.1020 +		// TODO: spread modes.
 29.1021 +		// TODO: plenty of opportunities to optimize.
 29.1022 +		float fx, fy, dx, gy;
 29.1023 +		float* t = cache->xform;
 29.1024 +		int i, cr, cg, cb, ca;
 29.1025 +		unsigned int c;
 29.1026 +
 29.1027 +		fx = ((float)x - tx) / scale;
 29.1028 +		fy = ((float)y - ty) / scale;
 29.1029 +		dx = 1.0f / scale;
 29.1030 +
 29.1031 +		for (i = 0; i < count; i++) {
 29.1032 +			int r,g,b,a,ia;
 29.1033 +			gy = fx*t[1] + fy*t[3] + t[5];
 29.1034 +			c = cache->colors[(int)nsvg__clampf(gy*255.0f, 0, 255.0f)];
 29.1035 +			cr = (c) & 0xff;
 29.1036 +			cg = (c >> 8) & 0xff;
 29.1037 +			cb = (c >> 16) & 0xff;
 29.1038 +			ca = (c >> 24) & 0xff;
 29.1039 +
 29.1040 +			a = nsvg__div255((int)cover[0] * ca);
 29.1041 +			ia = 255 - a;
 29.1042 +
 29.1043 +			// Premultiply
 29.1044 +			r = nsvg__div255(cr * a);
 29.1045 +			g = nsvg__div255(cg * a);
 29.1046 +			b = nsvg__div255(cb * a);
 29.1047 +
 29.1048 +			// Blend over
 29.1049 +			r += nsvg__div255(ia * (int)dst[0]);
 29.1050 +			g += nsvg__div255(ia * (int)dst[1]);
 29.1051 +			b += nsvg__div255(ia * (int)dst[2]);
 29.1052 +			a += nsvg__div255(ia * (int)dst[3]);
 29.1053 +
 29.1054 +			dst[0] = (unsigned char)r;
 29.1055 +			dst[1] = (unsigned char)g;
 29.1056 +			dst[2] = (unsigned char)b;
 29.1057 +			dst[3] = (unsigned char)a;
 29.1058 +
 29.1059 +			cover++;
 29.1060 +			dst += 4;
 29.1061 +			fx += dx;
 29.1062 +		}
 29.1063 +	} else if (cache->type == NSVG_PAINT_RADIAL_GRADIENT) {
 29.1064 +		// TODO: spread modes.
 29.1065 +		// TODO: plenty of opportunities to optimize.
 29.1066 +		// TODO: focus (fx,fy)
 29.1067 +		float fx, fy, dx, gx, gy, gd;
 29.1068 +		float* t = cache->xform;
 29.1069 +		int i, cr, cg, cb, ca;
 29.1070 +		unsigned int c;
 29.1071 +
 29.1072 +		fx = ((float)x - tx) / scale;
 29.1073 +		fy = ((float)y - ty) / scale;
 29.1074 +		dx = 1.0f / scale;
 29.1075 +
 29.1076 +		for (i = 0; i < count; i++) {
 29.1077 +			int r,g,b,a,ia;
 29.1078 +			gx = fx*t[0] + fy*t[2] + t[4];
 29.1079 +			gy = fx*t[1] + fy*t[3] + t[5];
 29.1080 +			gd = sqrtf(gx*gx + gy*gy);
 29.1081 +			c = cache->colors[(int)nsvg__clampf(gd*255.0f, 0, 255.0f)];
 29.1082 +			cr = (c) & 0xff;
 29.1083 +			cg = (c >> 8) & 0xff;
 29.1084 +			cb = (c >> 16) & 0xff;
 29.1085 +			ca = (c >> 24) & 0xff;
 29.1086 +
 29.1087 +			a = nsvg__div255((int)cover[0] * ca);
 29.1088 +			ia = 255 - a;
 29.1089 +
 29.1090 +			// Premultiply
 29.1091 +			r = nsvg__div255(cr * a);
 29.1092 +			g = nsvg__div255(cg * a);
 29.1093 +			b = nsvg__div255(cb * a);
 29.1094 +
 29.1095 +			// Blend over
 29.1096 +			r += nsvg__div255(ia * (int)dst[0]);
 29.1097 +			g += nsvg__div255(ia * (int)dst[1]);
 29.1098 +			b += nsvg__div255(ia * (int)dst[2]);
 29.1099 +			a += nsvg__div255(ia * (int)dst[3]);
 29.1100 +
 29.1101 +			dst[0] = (unsigned char)r;
 29.1102 +			dst[1] = (unsigned char)g;
 29.1103 +			dst[2] = (unsigned char)b;
 29.1104 +			dst[3] = (unsigned char)a;
 29.1105 +
 29.1106 +			cover++;
 29.1107 +			dst += 4;
 29.1108 +			fx += dx;
 29.1109 +		}
 29.1110 +	}
 29.1111 +}
 29.1112 +
 29.1113 +static void nsvg__rasterizeSortedEdges(NSVGrasterizer *r, float tx, float ty, float scale, NSVGcachedPaint* cache, char fillRule)
 29.1114 +{
 29.1115 +	NSVGactiveEdge *active = NULL;
 29.1116 +	int y, s;
 29.1117 +	int e = 0;
 29.1118 +	int maxWeight = (255 / NSVG__SUBSAMPLES);  // weight per vertical scanline
 29.1119 +	int xmin, xmax;
 29.1120 +
 29.1121 +	for (y = 0; y < r->height; y++) {
 29.1122 +		memset(r->scanline, 0, r->width);
 29.1123 +		xmin = r->width;
 29.1124 +		xmax = 0;
 29.1125 +		for (s = 0; s < NSVG__SUBSAMPLES; ++s) {
 29.1126 +			// find center of pixel for this scanline
 29.1127 +			float scany = (float)(y*NSVG__SUBSAMPLES + s) + 0.5f;
 29.1128 +			NSVGactiveEdge **step = &active;
 29.1129 +
 29.1130 +			// update all active edges;
 29.1131 +			// remove all active edges that terminate before the center of this scanline
 29.1132 +			while (*step) {
 29.1133 +				NSVGactiveEdge *z = *step;
 29.1134 +				if (z->ey <= scany) {
 29.1135 +					*step = z->next; // delete from list
 29.1136 +//					NSVG__assert(z->valid);
 29.1137 +					nsvg__freeActive(r, z);
 29.1138 +				} else {
 29.1139 +					z->x += z->dx; // advance to position for current scanline
 29.1140 +					step = &((*step)->next); // advance through list
 29.1141 +				}
 29.1142 +			}
 29.1143 +
 29.1144 +			// resort the list if needed
 29.1145 +			for (;;) {
 29.1146 +				int changed = 0;
 29.1147 +				step = &active;
 29.1148 +				while (*step && (*step)->next) {
 29.1149 +					if ((*step)->x > (*step)->next->x) {
 29.1150 +						NSVGactiveEdge* t = *step;
 29.1151 +						NSVGactiveEdge* q = t->next;
 29.1152 +						t->next = q->next;
 29.1153 +						q->next = t;
 29.1154 +						*step = q;
 29.1155 +						changed = 1;
 29.1156 +					}
 29.1157 +					step = &(*step)->next;
 29.1158 +				}
 29.1159 +				if (!changed) break;
 29.1160 +			}
 29.1161 +
 29.1162 +			// insert all edges that start before the center of this scanline -- omit ones that also end on this scanline
 29.1163 +			while (e < r->nedges && r->edges[e].y0 <= scany) {
 29.1164 +				if (r->edges[e].y1 > scany) {
 29.1165 +					NSVGactiveEdge* z = nsvg__addActive(r, &r->edges[e], scany);
 29.1166 +					if (z == NULL) break;
 29.1167 +					// find insertion point
 29.1168 +					if (active == NULL) {
 29.1169 +						active = z;
 29.1170 +					} else if (z->x < active->x) {
 29.1171 +						// insert at front
 29.1172 +						z->next = active;
 29.1173 +						active = z;
 29.1174 +					} else {
 29.1175 +						// find thing to insert AFTER
 29.1176 +						NSVGactiveEdge* p = active;
 29.1177 +						while (p->next && p->next->x < z->x)
 29.1178 +							p = p->next;
 29.1179 +						// at this point, p->next->x is NOT < z->x
 29.1180 +						z->next = p->next;
 29.1181 +						p->next = z;
 29.1182 +					}
 29.1183 +				}
 29.1184 +				e++;
 29.1185 +			}
 29.1186 +
 29.1187 +			// now process all active edges in non-zero fashion
 29.1188 +			if (active != NULL)
 29.1189 +				nsvg__fillActiveEdges(r->scanline, r->width, active, maxWeight, &xmin, &xmax, fillRule);
 29.1190 +		}
 29.1191 +		// Blit
 29.1192 +		if (xmin < 0) xmin = 0;
 29.1193 +		if (xmax > r->width-1) xmax = r->width-1;
 29.1194 +		if (xmin <= xmax) {
 29.1195 +			nsvg__scanlineSolid(&r->bitmap[y * r->stride] + xmin*4, xmax-xmin+1, &r->scanline[xmin], xmin, y, tx,ty, scale, cache);
 29.1196 +		}
 29.1197 +	}
 29.1198 +
 29.1199 +}
 29.1200 +
 29.1201 +static void nsvg__unpremultiplyAlpha(unsigned char* image, int w, int h, int stride)
 29.1202 +{
 29.1203 +	int x,y;
 29.1204 +
 29.1205 +	// Unpremultiply
 29.1206 +	for (y = 0; y < h; y++) {
 29.1207 +		unsigned char *row = &image[y*stride];
 29.1208 +		for (x = 0; x < w; x++) {
 29.1209 +			int r = row[0], g = row[1], b = row[2], a = row[3];
 29.1210 +			if (a != 0) {
 29.1211 +				row[0] = (unsigned char)(r*255/a);
 29.1212 +				row[1] = (unsigned char)(g*255/a);
 29.1213 +				row[2] = (unsigned char)(b*255/a);
 29.1214 +			}
 29.1215 +			row += 4;
 29.1216 +		}
 29.1217 +	}
 29.1218 +
 29.1219 +	// Defringe
 29.1220 +	for (y = 0; y < h; y++) {
 29.1221 +		unsigned char *row = &image[y*stride];
 29.1222 +		for (x = 0; x < w; x++) {
 29.1223 +			int r = 0, g = 0, b = 0, a = row[3], n = 0;
 29.1224 +			if (a == 0) {
 29.1225 +				if (x-1 > 0 && row[-1] != 0) {
 29.1226 +					r += row[-4];
 29.1227 +					g += row[-3];
 29.1228 +					b += row[-2];
 29.1229 +					n++;
 29.1230 +				}
 29.1231 +				if (x+1 < w && row[7] != 0) {
 29.1232 +					r += row[4];
 29.1233 +					g += row[5];
 29.1234 +					b += row[6];
 29.1235 +					n++;
 29.1236 +				}
 29.1237 +				if (y-1 > 0 && row[-stride+3] != 0) {
 29.1238 +					r += row[-stride];
 29.1239 +					g += row[-stride+1];
 29.1240 +					b += row[-stride+2];
 29.1241 +					n++;
 29.1242 +				}
 29.1243 +				if (y+1 < h && row[stride+3] != 0) {
 29.1244 +					r += row[stride];
 29.1245 +					g += row[stride+1];
 29.1246 +					b += row[stride+2];
 29.1247 +					n++;
 29.1248 +				}
 29.1249 +				if (n > 0) {
 29.1250 +					row[0] = (unsigned char)(r/n);
 29.1251 +					row[1] = (unsigned char)(g/n);
 29.1252 +					row[2] = (unsigned char)(b/n);
 29.1253 +				}
 29.1254 +			}
 29.1255 +			row += 4;
 29.1256 +		}
 29.1257 +	}
 29.1258 +}
 29.1259 +
 29.1260 +
 29.1261 +static void nsvg__initPaint(NSVGcachedPaint* cache, NSVGpaint* paint, float opacity)
 29.1262 +{
 29.1263 +	int i, j;
 29.1264 +	NSVGgradient* grad;
 29.1265 +
 29.1266 +	cache->type = paint->type;
 29.1267 +
 29.1268 +	if (paint->type == NSVG_PAINT_COLOR) {
 29.1269 +		cache->colors[0] = nsvg__applyOpacity(paint->color, opacity);
 29.1270 +		return;
 29.1271 +	}
 29.1272 +
 29.1273 +	grad = paint->gradient;
 29.1274 +
 29.1275 +	cache->spread = grad->spread;
 29.1276 +	memcpy(cache->xform, grad->xform, sizeof(float)*6);
 29.1277 +
 29.1278 +	if (grad->nstops == 0) {
 29.1279 +		for (i = 0; i < 256; i++)
 29.1280 +			cache->colors[i] = 0;
 29.1281 +	} if (grad->nstops == 1) {
 29.1282 +		for (i = 0; i < 256; i++)
 29.1283 +			cache->colors[i] = nsvg__applyOpacity(grad->stops[i].color, opacity);
 29.1284 +	} else {
 29.1285 +		unsigned int ca, cb = 0;
 29.1286 +		float ua, ub, du, u;
 29.1287 +		int ia, ib, count;
 29.1288 +
 29.1289 +		ca = nsvg__applyOpacity(grad->stops[0].color, opacity);
 29.1290 +		ua = nsvg__clampf(grad->stops[0].offset, 0, 1);
 29.1291 +		ub = nsvg__clampf(grad->stops[grad->nstops-1].offset, ua, 1);
 29.1292 +		ia = (int)(ua * 255.0f);
 29.1293 +		ib = (int)(ub * 255.0f);
 29.1294 +		for (i = 0; i < ia; i++) {
 29.1295 +			cache->colors[i] = ca;
 29.1296 +		}
 29.1297 +
 29.1298 +		for (i = 0; i < grad->nstops-1; i++) {
 29.1299 +			ca = nsvg__applyOpacity(grad->stops[i].color, opacity);
 29.1300 +			cb = nsvg__applyOpacity(grad->stops[i+1].color, opacity);
 29.1301 +			ua = nsvg__clampf(grad->stops[i].offset, 0, 1);
 29.1302 +			ub = nsvg__clampf(grad->stops[i+1].offset, 0, 1);
 29.1303 +			ia = (int)(ua * 255.0f);
 29.1304 +			ib = (int)(ub * 255.0f);
 29.1305 +			count = ib - ia;
 29.1306 +			if (count <= 0) continue;
 29.1307 +			u = 0;
 29.1308 +			du = 1.0f / (float)count;
 29.1309 +			for (j = 0; j < count; j++) {
 29.1310 +				cache->colors[ia+j] = nsvg__lerpRGBA(ca,cb,u);
 29.1311 +				u += du;
 29.1312 +			}
 29.1313 +		}
 29.1314 +
 29.1315 +		for (i = ib; i < 256; i++)
 29.1316 +			cache->colors[i] = cb;
 29.1317 +	}
 29.1318 +
 29.1319 +}
 29.1320 +
 29.1321 +/*
 29.1322 +static void dumpEdges(NSVGrasterizer* r, const char* name)
 29.1323 +{
 29.1324 +	float xmin = 0, xmax = 0, ymin = 0, ymax = 0;
 29.1325 +	NSVGedge *e = NULL;
 29.1326 +	int i;
 29.1327 +	if (r->nedges == 0) return;
 29.1328 +	FILE* fp = fopen(name, "w");
 29.1329 +	if (fp == NULL) return;
 29.1330 +
 29.1331 +	xmin = xmax = r->edges[0].x0;
 29.1332 +	ymin = ymax = r->edges[0].y0;
 29.1333 +	for (i = 0; i < r->nedges; i++) {
 29.1334 +		e = &r->edges[i];
 29.1335 +		xmin = nsvg__minf(xmin, e->x0);
 29.1336 +		xmin = nsvg__minf(xmin, e->x1);
 29.1337 +		xmax = nsvg__maxf(xmax, e->x0);
 29.1338 +		xmax = nsvg__maxf(xmax, e->x1);
 29.1339 +		ymin = nsvg__minf(ymin, e->y0);
 29.1340 +		ymin = nsvg__minf(ymin, e->y1);
 29.1341 +		ymax = nsvg__maxf(ymax, e->y0);
 29.1342 +		ymax = nsvg__maxf(ymax, e->y1);
 29.1343 +	}
 29.1344 +
 29.1345 +	fprintf(fp, "<svg viewBox=\"%f %f %f %f\" xmlns=\"http://www.w3.org/2000/svg\">", xmin, ymin, (xmax - xmin), (ymax - ymin));
 29.1346 +
 29.1347 +	for (i = 0; i < r->nedges; i++) {
 29.1348 +		e = &r->edges[i];
 29.1349 +		fprintf(fp ,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:#000;\" />", e->x0,e->y0, e->x1,e->y1);
 29.1350 +	}
 29.1351 +
 29.1352 +	for (i = 0; i < r->npoints; i++) {
 29.1353 +		if (i+1 < r->npoints)
 29.1354 +			fprintf(fp ,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" style=\"stroke:#f00;\" />", r->points[i].x, r->points[i].y, r->points[i+1].x, r->points[i+1].y);
 29.1355 +		fprintf(fp ,"<circle cx=\"%f\" cy=\"%f\" r=\"1\" style=\"fill:%s;\" />", r->points[i].x, r->points[i].y, r->points[i].flags == 0 ? "#f00" : "#0f0");
 29.1356 +	}
 29.1357 +
 29.1358 +	fprintf(fp, "</svg>");
 29.1359 +	fclose(fp);
 29.1360 +}
 29.1361 +*/
 29.1362 +
 29.1363 +void nsvgRasterize(NSVGrasterizer* r,
 29.1364 +				   NSVGimage* image, float tx, float ty, float scale,
 29.1365 +				   unsigned char* dst, int w, int h, int stride)
 29.1366 +{
 29.1367 +	NSVGshape *shape = NULL;
 29.1368 +	NSVGedge *e = NULL;
 29.1369 +	NSVGcachedPaint cache;
 29.1370 +	int i;
 29.1371 +
 29.1372 +	r->bitmap = dst;
 29.1373 +	r->width = w;
 29.1374 +	r->height = h;
 29.1375 +	r->stride = stride;
 29.1376 +
 29.1377 +	if (w > r->cscanline) {
 29.1378 +		r->cscanline = w;
 29.1379 +		r->scanline = (unsigned char*)realloc(r->scanline, w);
 29.1380 +		if (r->scanline == NULL) return;
 29.1381 +	}
 29.1382 +
 29.1383 +	for (i = 0; i < h; i++)
 29.1384 +		memset(&dst[i*stride], 0, w*4);
 29.1385 +
 29.1386 +	for (shape = image->shapes; shape != NULL; shape = shape->next) {
 29.1387 +		if (!(shape->flags & NSVG_FLAGS_VISIBLE))
 29.1388 +			continue;
 29.1389 +
 29.1390 +		if (shape->fill.type != NSVG_PAINT_NONE) {
 29.1391 +			nsvg__resetPool(r);
 29.1392 +			r->freelist = NULL;
 29.1393 +			r->nedges = 0;
 29.1394 +
 29.1395 +			nsvg__flattenShape(r, shape, scale);
 29.1396 +
 29.1397 +			// Scale and translate edges
 29.1398 +			for (i = 0; i < r->nedges; i++) {
 29.1399 +				e = &r->edges[i];
 29.1400 +				e->x0 = tx + e->x0;
 29.1401 +				e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
 29.1402 +				e->x1 = tx + e->x1;
 29.1403 +				e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
 29.1404 +			}
 29.1405 +
 29.1406 +			// Rasterize edges
 29.1407 +			qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);
 29.1408 +
 29.1409 +			// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
 29.1410 +			nsvg__initPaint(&cache, &shape->fill, shape->opacity);
 29.1411 +
 29.1412 +			nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, shape->fillRule);
 29.1413 +		}
 29.1414 +		if (shape->stroke.type != NSVG_PAINT_NONE && (shape->strokeWidth * scale) > 0.01f) {
 29.1415 +			nsvg__resetPool(r);
 29.1416 +			r->freelist = NULL;
 29.1417 +			r->nedges = 0;
 29.1418 +
 29.1419 +			nsvg__flattenShapeStroke(r, shape, scale);
 29.1420 +
 29.1421 +//			dumpEdges(r, "edge.svg");
 29.1422 +
 29.1423 +			// Scale and translate edges
 29.1424 +			for (i = 0; i < r->nedges; i++) {
 29.1425 +				e = &r->edges[i];
 29.1426 +				e->x0 = tx + e->x0;
 29.1427 +				e->y0 = (ty + e->y0) * NSVG__SUBSAMPLES;
 29.1428 +				e->x1 = tx + e->x1;
 29.1429 +				e->y1 = (ty + e->y1) * NSVG__SUBSAMPLES;
 29.1430 +			}
 29.1431 +
 29.1432 +			// Rasterize edges
 29.1433 +			qsort(r->edges, r->nedges, sizeof(NSVGedge), nsvg__cmpEdge);
 29.1434 +
 29.1435 +			// now, traverse the scanlines and find the intersections on each scanline, use non-zero rule
 29.1436 +			nsvg__initPaint(&cache, &shape->stroke, shape->opacity);
 29.1437 +
 29.1438 +			nsvg__rasterizeSortedEdges(r, tx,ty,scale, &cache, NSVG_FILLRULE_NONZERO);
 29.1439 +		}
 29.1440 +	}
 29.1441 +
 29.1442 +	nsvg__unpremultiplyAlpha(dst, w, h, stride);
 29.1443 +
 29.1444 +	r->bitmap = NULL;
 29.1445 +	r->width = 0;
 29.1446 +	r->height = 0;
 29.1447 +	r->stride = 0;
 29.1448 +}
 29.1449 +
 29.1450 +#endif