Hello community,

here is the log from the commit of package librsvg for openSUSE:Factory checked 
in at 2016-01-12 16:11:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/librsvg (Old)
 and      /work/SRC/openSUSE:Factory/.librsvg.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "librsvg"

Changes:
--------
--- /work/SRC/openSUSE:Factory/librsvg/librsvg.changes  2015-12-09 
19:32:35.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.librsvg.new/librsvg.changes     2016-01-12 
16:11:31.000000000 +0100
@@ -1,0 +2,10 @@
+Fri Jan  8 19:20:06 UTC 2016 - zai...@opensuse.org
+
+- Update to version 2.40.13:
+  + Fixed the Windows build.
+  + Added basic support for the "baseline-shift" attribute in text
+    objects (bgo#340047).
+  + Fixed some duplicate logic when rendering paths (bgo#749415).
+  + Rewrote the markers engine (bgo#685906, bgo#760180).
+
+-------------------------------------------------------------------

Old:
----
  librsvg-2.40.12.tar.xz

New:
----
  librsvg-2.40.13.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ librsvg.spec ++++++
--- /var/tmp/diff_new_pack.eXeshj/_old  2016-01-12 16:11:32.000000000 +0100
+++ /var/tmp/diff_new_pack.eXeshj/_new  2016-01-12 16:11:32.000000000 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package librsvg
 #
-# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
 
 
 Name:           librsvg
-Version:        2.40.12
+Version:        2.40.13
 Release:        0
 Summary:        A Library for Rendering SVG Data
 License:        LGPL-2.0+ and GPL-2.0+

++++++ librsvg-2.40.12.tar.xz -> librsvg-2.40.13.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/ChangeLog 
new/librsvg-2.40.13/ChangeLog
--- old/librsvg-2.40.12/ChangeLog       2015-12-02 02:13:44.000000000 +0100
+++ new/librsvg-2.40.13/ChangeLog       2016-01-08 02:44:51.000000000 +0100
@@ -1,3 +1,245 @@
+commit a12e7b90e7b9fa6a6a325f39fb409722b06a6735
+Author: Federico Mena Quintero <feder...@gnome.org>
+Date:   Thu Jan 7 19:37:34 2016 -0600
+
+    Update NEWS
+
+ NEWS | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+commit 954e40e52363fe5bcfbb7e9c28dfcc05aa1affa3
+Author: Federico Mena Quintero <feder...@gnome.org>
+Date:   Thu Jan 7 19:27:22 2016 -0600
+
+    Regenerate reference images which were failing; they are OK now
+
+ tests/fixtures/reftests/bugs/340047-ref.png | Bin 4855 -> 4706 bytes
+ tests/fixtures/reftests/bugs/749415-ref.png | Bin 22441 -> 19572 bytes
+ 2 files changed, 0 insertions(+), 0 deletions(-)
+
+commit 63371906c63d74bfb1f1ca6b10237d3b563bb55a
+Author: Federico Mena Quintero <feder...@gnome.org>
+Date:   Thu Jan 7 19:15:38 2016 -0600
+
+    bgo#760180: handle the viewBox of markers correctly
+    
+    One of the SVG test suite's images has a marker with a viewBox that 
doesn't actually start at (0, 0).
+    This was rendered incorrectly.
+    
+    I'm not sure why this specific use of rsvg_preserve_aspect_ratio() is not 
the same as the others
+    in librsvg, but it certainly produced incorrect results.
+    
+    https://bugzilla.gnome.org/show_bug.cgi?id=760180
+
+ rsvg-marker.c                               |  13 +--
+ tests/fixtures/reftests/bugs/760180-ref.png | Bin 0 -> 8120 bytes
+ tests/fixtures/reftests/bugs/760180.svg     | 159 ++++++++++++++++++++++++++++
+ 3 files changed, 161 insertions(+), 11 deletions(-)
+
+commit 0e2c78cb95a72e7378638a6bb6b647e5c7a7c8c1
+Author: Federico Mena Quintero <feder...@gnome.org>
+Date:   Thu Jan 7 17:24:42 2016 -0600
+
+    rsvg-marker: Use the correct default marker size as specified in the spec
+    
+    The spec uses 3 as the default markerWidth and markerHeight:
+    http://www.w3.org/TR/SVG/painting.html#MarkerWidthAttribute
+
+ rsvg-marker.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 92b16618981031f4599d429192ad0b99337a680d
+Author: Paolo Borelli <pbore...@gnome.org>
+Date:   Thu Jan 7 23:56:56 2016 +0100
+
+    MSVC builds: Fix install with CopyDir != GlibEtcInstallRoot
+    
+    We should create CopyDir since that is where we copy the files
+
+ build/win32/vs10/rsvg-install.propsin  | 4 ++--
+ build/win32/vs9/rsvg-install.vspropsin | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+commit bb0a86f9daa7a8504d6c52a08e9b604b9af80f25
+Author: Federico Mena Quintero <feder...@gnome.org>
+Date:   Wed Jan 6 14:34:32 2016 -0600
+
+    Update NEWS
+
+ NEWS | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+commit cb7fd6b635a519e968ea67ec529651fe774abe26
+Author: Menner <m...@gmx.org>
+Date:   Sat Jan 2 09:35:52 2016 +0100
+
+    bgo#749415: Don't duplicate logic for deciding when to push discrete layers
+    
+    rsvg_cairo_render_path() tried to avoid calling
+    rsvg_cairo_push/pop_discrete_layer(), but the logic to decide whether
+    to actually create an intermediate surface is best left in those
+    functions.  With the duplicate/incorrect logic, text had incorrect
+    spacing as a result.
+    
+    Also, remove an extra-old comment from when those functions were first
+    implemented.
+    
+    https://bugzilla.gnome.org/show_bug.cgi?id=749415
+
+ rsvg-cairo-draw.c                           |  23 +++--------------
+ tests/fixtures/reftests/bugs/749415-ref.png | Bin 0 -> 22441 bytes
+ tests/fixtures/reftests/bugs/749415.svg     |  38 ++++++++++++++++++++++++++++
+ 3 files changed, 42 insertions(+), 19 deletions(-)
+
+commit 41345523c756297b0b88dbcfeedc38e5f5c86c18
+Author: Federico Mena Quintero <feder...@gnome.org>
+Date:   Tue Jan 5 19:40:39 2016 -0600
+
+    Update NEWS
+
+ NEWS | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+commit 5dc9e603227296766ee05b9fab6812b5e6b4d535
+Author: Federico Mena Quintero <feder...@gnome.org>
+Date:   Tue Jan 5 19:40:32 2016 -0600
+
+    Remove leftover from the unsupported a:adobe-blending-mode
+
+ rsvg-styles.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+commit e804fb1adcf564ce4bae661cc595a8d4df55efd3
+Author: Menner <m...@gmx.org>
+Date:   Sat Jan 2 09:42:53 2016 +0100
+
+    bgo#340047 - Add support for the "baseline-shift" text attribute
+    
+    This commit adds support for the baseline-shift attribute for tags
+    "sub/super/baseline".  We don't support percentages of the font size
+    or explicit lengths yet.
+    
+    https://bugzilla.gnome.org/show_bug.cgi?id=340047
+
+ rsvg-css.c                                  |  24 +++++++++++++++-
+ rsvg-private.h                              |   2 ++
+ rsvg-styles.c                               |  21 ++++++++++++++
+ rsvg-styles.h                               |   2 ++
+ rsvg-text.c                                 |  16 +++++++----
+ tests/fixtures/reftests/bugs/340047-ref.png | Bin 0 -> 4855 bytes
+ tests/fixtures/reftests/bugs/340047.svg     |  43 ++++++++++++++++++++++++++++
+ 7 files changed, 101 insertions(+), 7 deletions(-)
+
+commit 1fc06fe6def169920f4032e348040c38be320fb1
+Author: Menner <m...@gmx.org>
+Date:   Tue Jan 5 13:50:17 2016 -0600
+
+    rsvg-marker: Don't try to render NULL markers
+    
+    https://bugzilla.gnome.org/show_bug.cgi?id=685906#c7
+
+ rsvg-marker.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+commit b945b6f5dbee693ac82d1b94f8f5a0ec37d00ee5
+Author: Chun-wei Fan <fanchun...@src.gnome.org>
+Date:   Tue Dec 15 14:00:44 2015 +0800
+
+    MSVC 2008 builds: include gio-win32-2.0 in the include paths
+    
+    This is a follow-up commit for commit 7ebe28c for Visual Studio 2008
+    builds, for the same reason as that commit.
+
+ build/win32/vs9/rsvg-build-defines.vsprops | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 00744676387ce7914bff33f43ce5f04960219925
+Author: Chun-wei Fan <fanchun...@src.gnome.org>
+Date:   Tue Dec 15 13:55:49 2015 +0800
+
+    MSVC builds: Fix pixbuf loaders cache generation
+    
+    Use $(GlibEtcInstallRoot)\bin\gdk-pixbuf-query-loaders instead of
+    $(CopyDir)\bin\gdk-pixbuf-query-loaders to fix the "installation" when
+    CopyDir != GlibEtcInstallRoot.
+    
+    https://bugzilla.gnome.org/show_bug.cgi?id=759438
+
+ build/win32/vs10/rsvg-install.propsin  | 2 +-
+ build/win32/vs9/rsvg-install.vspropsin | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+commit 7ebe28c3be9ba8227cebd407511dcec92d34c39e
+Author: Paolo Borelli <pbore...@gnome.org>
+Date:   Sat Dec 12 17:33:46 2015 +0100
+
+    win32: add gio-win32-2.0 to the include paths
+    
+    rsvg-convert uses the win32 gio streams
+
+ build/win32/vs10/rsvg-build-defines.props | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 3ef996ce17903642187326e20fc5dea48a3c6206
+Author: Federico Mena Quintero <feder...@gnome.org>
+Date:   Mon Dec 7 20:15:30 2015 -0600
+
+    test/bugs: add reference image for #685906
+
+ tests/bugs/685906-ref.png | Bin 0 -> 2955 bytes
+ 1 file changed, 0 insertions(+), 0 deletions(-)
+
+commit 0cfdd27ecb5023b65865d6458d9a810f48f08eb2
+Author: Federico Mena Quintero <feder...@gnome.org>
+Date:   Mon Dec 7 20:11:43 2015 -0600
+
+    bgo#685906 - Marker angles are wrong when control points of a curve are 
coincident
+    
+    This is a rewrite of the code to draw markers at path vertices.  The 
previous code did a single pass
+    over the cairo_path_t data, and it tried to figure out the appropriate 
marker type for each vertex
+    (start marker, middle, or end).  However, it had trouble with coincident 
points in curveto
+    commands, and with zero-length path segments.  The SVG spec is verbose but 
clear on the behavior
+    for those cases.
+    
+    The code now does two passes:
+    
+    1. Take the cairo_path_t data, which is an array of 
moveto/lineto/curveto/closepath commands, and
+    turn it into a sequence of segments.  Each segment either has four control 
points, *or* it has
+    a single point and the segment is degenerate.
+    
+    2. Walk that list of segments, and draw the appropriate markers for them.
+    
+    Having the list of segments makes it easy to implement the algorithm from 
the SVG spec,
+    in which the directionality of special vertices (like those at the ends of 
zero-length segments)
+    needs to be determined.
+    
+    This code is careful to not do division by zero or to get NaNs in the 
middle of the computation,
+    which would get Cairo into an error state, preventing further drawing of 
markers within
+    the path.
+    
+    Fixes https://bugzilla.gnome.org/show_bug.cgi?id=685906
+
+ rsvg-marker.c | 524 ++++++++++++++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 414 insertions(+), 110 deletions(-)
+
+commit 7621ae4f61901c349af7cfe5ae3790b417227bf6
+Author: Federico Mena Quintero <feder...@gnome.org>
+Date:   Tue Dec 1 18:58:15 2015 -0600
+
+    Tests: add bug test for #685906
+
+ tests/bugs/685906.svg | 313 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 313 insertions(+)
+
+commit 3c58d0816d1ebacdd840ba5c60c3cbdfe2eb87c0
+Author: Federico Mena Quintero <feder...@gnome.org>
+Date:   Tue Dec 1 19:18:19 2015 -0600
+
+    Post release version bump
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
 commit 513c51f88ed66e7d76718039998658e8b68ba92c
 Author: Federico Mena Quintero <feder...@gnome.org>
 Date:   Tue Dec 1 19:13:09 2015 -0600
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/NEWS new/librsvg-2.40.13/NEWS
--- old/librsvg-2.40.12/NEWS    2015-12-02 02:12:51.000000000 +0100
+++ new/librsvg-2.40.13/NEWS    2016-01-08 02:43:51.000000000 +0100
@@ -1,3 +1,23 @@
+Version 2.40.13
+- Chun-wei Fan and Paolo Borelli fixed the Windows build.
+- Menner added basic support for the "baseline-shift" attribute in
+  text objects.  We support "sub", "super", and plain "baseline", so
+  you can at least have subscripts and superscripts for formulas and
+  such.  There is no support for percentages or explicit lengths yet.
+  bgo#340047.
+- Menner fixed some duplicate logic when rendering paths, which would
+  try to decide whether to create intermediate surfaces.  Now we have
+  a single place where this is done.  This fixes inconsistent text
+  spacing in some situations.  bgo#749415.
+- Rewrote the markers engine, for bgo#685906 and bgo#760180 - Our
+  machinery for rendering SVG markers (like arrowheads and such)
+  didn't handle several cases correctly.  Curves with coincident
+  control points produced incorrect orientations for the markers, as
+  did multiple contiguous zero-length segments.  We follow the spec
+  for this now and handle things correctly.  Also, markers didn't
+  render in the correct position if they had the viewBox attribute
+  set.
+
 Version 2.40.12
 - Benjamin Otte did *great* work in refactoring the test harness to
   use Glib's gtest infrastructure, instead of using home-grown
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/librsvg-2.40.12/build/win32/vs10/rsvg-build-defines.props 
new/librsvg-2.40.13/build/win32/vs10/rsvg-build-defines.props
--- old/librsvg-2.40.12/build/win32/vs10/rsvg-build-defines.props       
2015-10-08 00:25:45.000000000 +0200
+++ new/librsvg-2.40.13/build/win32/vs10/rsvg-build-defines.props       
2016-01-05 20:44:05.000000000 +0100
@@ -19,7 +19,7 @@
   </PropertyGroup>
   <ItemDefinitionGroup>
     <ClCompile>
-      
<AdditionalIncludeDirectories>..\..\..;$(GlibEtcInstallRoot)\include\gdk-pixbuf-2.0;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+      
<AdditionalIncludeDirectories>..\..\..;$(GlibEtcInstallRoot)\include\gdk-pixbuf-2.0;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include\gio-win32-2.0;$(GlibEtcInstallRoot)\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
       
<PreprocessorDefinitions>HAVE_CONFIG_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       
<ForcedIncludeFiles>msvc_recommended_pragmas.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
       <MultiProcessorCompilation>true</MultiProcessorCompilation>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/build/win32/vs10/rsvg-install.props 
new/librsvg-2.40.13/build/win32/vs10/rsvg-install.props
--- old/librsvg-2.40.12/build/win32/vs10/rsvg-install.props     2015-12-02 
02:13:48.000000000 +0100
+++ new/librsvg-2.40.13/build/win32/vs10/rsvg-install.props     2016-01-08 
02:44:53.000000000 +0100
@@ -5,8 +5,8 @@
   </ImportGroup>
   <PropertyGroup Label="UserMacros">
     <RsvgDoInstall>
-mkdir $(GlibEtcInstallRoot)
-mkdir $(GlibEtcInstallRoot)\bin
+mkdir $(CopyDir)
+mkdir $(CopyDir)\bin
 copy 
$(SolutionDir)$(Configuration)\$(Platform)\bin\$(RsvgDllPrefix)rsvg$(RsvgDllSuffix).dll
 $(CopyDir)\bin
 copy 
$(SolutionDir)$(Configuration)\$(Platform)\bin\$(RsvgDllPrefix)rsvg$(RsvgDllSuffix).pdb
 $(CopyDir)\bin
 copy $(SolutionDir)$(Configuration)\$(Platform)\bin\rsvg-convert.exe 
$(CopyDir)\bin
@@ -22,7 +22,7 @@
 copy $(SolutionDir)$(Configuration)\$(Platform)\bin\rsvg-$(ApiVersion).lib 
$(CopyDir)\lib
 copy $(SolutionDir)$(Configuration)\$(Platform)\bin\libpixbufloader-svg.dll 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders
 copy $(SolutionDir)$(Configuration)\$(Platform)\bin\libpixbufloader-svg.pdb 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders
-$(CopyDir)\bin\gdk-pixbuf-query-loaders.exe &gt; 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache
+$(GlibEtcInstallRoot)\bin\gdk-pixbuf-query-loaders.exe &gt; 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache
 </RsvgDoInstall>
   </PropertyGroup>
   <PropertyGroup>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/librsvg-2.40.12/build/win32/vs10/rsvg-install.propsin 
new/librsvg-2.40.13/build/win32/vs10/rsvg-install.propsin
--- old/librsvg-2.40.12/build/win32/vs10/rsvg-install.propsin   2015-10-08 
00:25:45.000000000 +0200
+++ new/librsvg-2.40.13/build/win32/vs10/rsvg-install.propsin   2016-01-08 
02:43:40.000000000 +0100
@@ -5,8 +5,8 @@
   </ImportGroup>
   <PropertyGroup Label="UserMacros">
     <RsvgDoInstall>
-mkdir $(GlibEtcInstallRoot)
-mkdir $(GlibEtcInstallRoot)\bin
+mkdir $(CopyDir)
+mkdir $(CopyDir)\bin
 
 copy 
$(SolutionDir)$(Configuration)\$(Platform)\bin\$(RsvgDllPrefix)rsvg$(RsvgDllSuffix).dll
 $(CopyDir)\bin
 copy 
$(SolutionDir)$(Configuration)\$(Platform)\bin\$(RsvgDllPrefix)rsvg$(RsvgDllSuffix).pdb
 $(CopyDir)\bin
@@ -23,7 +23,7 @@
 copy $(SolutionDir)$(Configuration)\$(Platform)\bin\libpixbufloader-svg.dll 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders
 copy $(SolutionDir)$(Configuration)\$(Platform)\bin\libpixbufloader-svg.pdb 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders
 
-$(CopyDir)\bin\gdk-pixbuf-query-loaders.exe &gt; 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache
+$(GlibEtcInstallRoot)\bin\gdk-pixbuf-query-loaders.exe &gt; 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache
 </RsvgDoInstall>
   </PropertyGroup>
   <PropertyGroup>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/librsvg-2.40.12/build/win32/vs9/rsvg-build-defines.vsprops 
new/librsvg-2.40.13/build/win32/vs9/rsvg-build-defines.vsprops
--- old/librsvg-2.40.12/build/win32/vs9/rsvg-build-defines.vsprops      
2015-10-08 00:25:45.000000000 +0200
+++ new/librsvg-2.40.13/build/win32/vs9/rsvg-build-defines.vsprops      
2016-01-05 20:44:05.000000000 +0100
@@ -9,7 +9,7 @@
        >
        <Tool
                Name="VCCLCompilerTool"
-               
AdditionalIncludeDirectories="..\..\..;$(GlibEtcInstallRoot)\include\gdk-pixbuf-2.0;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include"
+               
AdditionalIncludeDirectories="..\..\..;$(GlibEtcInstallRoot)\include\gdk-pixbuf-2.0;$(GlibEtcInstallRoot)\include\gio-win32-2.0;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include"
                PreprocessorDefinitions="HAVE_CONFIG_H"
                ForcedIncludeFiles="msvc_recommended_pragmas.h"
                AdditionalOptions="/MP"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/build/win32/vs9/rsvg-install.vsprops 
new/librsvg-2.40.13/build/win32/vs9/rsvg-install.vsprops
--- old/librsvg-2.40.12/build/win32/vs9/rsvg-install.vsprops    2015-12-02 
02:13:48.000000000 +0100
+++ new/librsvg-2.40.13/build/win32/vs9/rsvg-install.vsprops    2016-01-08 
02:44:53.000000000 +0100
@@ -8,8 +8,8 @@
  <UserMacro
   Name="RsvgDoInstall"
   Value="
-mkdir $(GlibEtcInstallRoot)&#x0D;&#x0A;
-mkdir $(GlibEtcInstallRoot)\bin&#x0D;&#x0A;
+mkdir $(CopyDir)&#x0D;&#x0A;
+mkdir $(CopyDir)\bin&#x0D;&#x0A;
 copy 
$(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\$(RsvgDllPrefix)rsvg$(RsvgDllSuffix).dll
 $(CopyDir)\bin&#x0D;&#x0A;
 copy 
$(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\$(RsvgDllPrefix)rsvg$(RsvgDllSuffix).pdb
 $(CopyDir)\bin&#x0D;&#x0A;
 copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\rsvg-convert.exe 
$(CopyDir)\bin&#x0D;&#x0A;
@@ -25,7 +25,7 @@
 copy 
$(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\rsvg-$(ApiVersion).lib 
$(CopyDir)\lib&#x0D;&#x0A;
 copy 
$(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\libpixbufloader-svg.dll 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders&#x0D;&#x0A;
 copy 
$(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\libpixbufloader-svg.pdb 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders&#x0D;&#x0A;
-$(CopyDir)\bin\gdk-pixbuf-query-loaders.exe &gt; 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache&#x0D;&#x0A;
+$(GlibEtcInstallRoot)\bin\gdk-pixbuf-query-loaders.exe &gt; 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache&#x0D;&#x0A;
 "
  />
 </VisualStudioPropertySheet>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/librsvg-2.40.12/build/win32/vs9/rsvg-install.vspropsin 
new/librsvg-2.40.13/build/win32/vs9/rsvg-install.vspropsin
--- old/librsvg-2.40.12/build/win32/vs9/rsvg-install.vspropsin  2015-10-08 
00:25:45.000000000 +0200
+++ new/librsvg-2.40.13/build/win32/vs9/rsvg-install.vspropsin  2016-01-08 
02:43:40.000000000 +0100
@@ -8,8 +8,8 @@
  <UserMacro
   Name="RsvgDoInstall"
   Value="
-mkdir $(GlibEtcInstallRoot)&#x0D;&#x0A;
-mkdir $(GlibEtcInstallRoot)\bin&#x0D;&#x0A;
+mkdir $(CopyDir)&#x0D;&#x0A;
+mkdir $(CopyDir)\bin&#x0D;&#x0A;
 
 copy 
$(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\$(RsvgDllPrefix)rsvg$(RsvgDllSuffix).dll
 $(CopyDir)\bin&#x0D;&#x0A;
 copy 
$(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\$(RsvgDllPrefix)rsvg$(RsvgDllSuffix).pdb
 $(CopyDir)\bin&#x0D;&#x0A;
@@ -26,7 +26,7 @@
 copy 
$(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\libpixbufloader-svg.dll 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders&#x0D;&#x0A;
 copy 
$(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\libpixbufloader-svg.pdb 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders&#x0D;&#x0A;
 
-$(CopyDir)\bin\gdk-pixbuf-query-loaders.exe &gt; 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache&#x0D;&#x0A;
+$(GlibEtcInstallRoot)\bin\gdk-pixbuf-query-loaders.exe &gt; 
$(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache&#x0D;&#x0A;
 "
  />
 </VisualStudioPropertySheet>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/config.h.win32 
new/librsvg-2.40.13/config.h.win32
--- old/librsvg-2.40.12/config.h.win32  2015-12-02 02:00:13.000000000 +0100
+++ new/librsvg-2.40.13/config.h.win32  2015-12-02 21:27:37.000000000 +0100
@@ -64,7 +64,7 @@
 #define PACKAGE_NAME "RSVG"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "RSVG 2.40.12"
+#define PACKAGE_STRING "RSVG 2.40.13"
 
 /* Define to the one symbol short name of this package. */
 #define PACKAGE_TARNAME "librsvg"
@@ -73,13 +73,13 @@
 #define PACKAGE_URL ""
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "2.40.12"
+#define PACKAGE_VERSION "2.40.13"
 
 /* Define to 1 if you have the ANSI C header files. */
 #define STDC_HEADERS 1
 
 /* Version number of package */
-#define VERSION "2.40.12"
+#define VERSION "2.40.13"
 
 /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
    significant byte first (like Motorola and SPARC, unlike Intel). */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/configure 
new/librsvg-2.40.13/configure
--- old/librsvg-2.40.12/configure       2015-12-02 02:00:08.000000000 +0100
+++ new/librsvg-2.40.13/configure       2015-12-02 21:27:33.000000000 +0100
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for RSVG 2.40.12.
+# Generated by GNU Autoconf 2.69 for RSVG 2.40.13.
 #
 # Report bugs to <https://bugzilla.gnome.org/enter_bug.cgi?product=librsvg>.
 #
@@ -591,8 +591,8 @@
 # Identity of this package.
 PACKAGE_NAME='RSVG'
 PACKAGE_TARNAME='librsvg'
-PACKAGE_VERSION='2.40.12'
-PACKAGE_STRING='RSVG 2.40.12'
+PACKAGE_VERSION='2.40.13'
+PACKAGE_STRING='RSVG 2.40.13'
 PACKAGE_BUGREPORT='https://bugzilla.gnome.org/enter_bug.cgi?product=librsvg'
 PACKAGE_URL=''
 
@@ -1433,7 +1433,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures RSVG 2.40.12 to adapt to many kinds of systems.
+\`configure' configures RSVG 2.40.13 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1503,7 +1503,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of RSVG 2.40.12:";;
+     short | recursive ) echo "Configuration of RSVG 2.40.13:";;
    esac
   cat <<\_ACEOF
 
@@ -1657,7 +1657,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-RSVG configure 2.40.12
+RSVG configure 2.40.13
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2026,7 +2026,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by RSVG $as_me 2.40.12, which was
+It was created by RSVG $as_me 2.40.13, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -2895,7 +2895,7 @@
 
 # Define the identity of the package.
  PACKAGE='librsvg'
- VERSION='2.40.12'
+ VERSION='2.40.13'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -3033,13 +3033,13 @@
 
 # ===========================================================================
 
-RSVG_LT_VERSION_INFO=42:12:40
+RSVG_LT_VERSION_INFO=42:13:40
 
 LIBRSVG_MAJOR_VERSION=2
 
 LIBRSVG_MINOR_VERSION=40
 
-LIBRSVG_MICRO_VERSION=12
+LIBRSVG_MICRO_VERSION=13
 
 
 
@@ -15688,7 +15688,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by RSVG $as_me 2.40.12, which was
+This file was extended by RSVG $as_me 2.40.13, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -15754,7 +15754,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; 
s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-RSVG config.status 2.40.12
+RSVG config.status 2.40.13
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/configure.ac 
new/librsvg-2.40.13/configure.ac
--- old/librsvg-2.40.12/configure.ac    2015-10-22 16:45:11.000000000 +0200
+++ new/librsvg-2.40.13/configure.ac    2015-12-02 02:18:33.000000000 +0100
@@ -1,6 +1,6 @@
 m4_define([rsvg_major_version],[2])
 m4_define([rsvg_minor_version],[40])
-m4_define([rsvg_micro_version],[12])
+m4_define([rsvg_micro_version],[13])
 m4_define([rsvg_extra_version],[])
 
m4_define([rsvg_version],[rsvg_major_version.rsvg_minor_version.rsvg_micro_version()rsvg_extra_version])
 m4_define([rsvg_lt_version_info],m4_eval(rsvg_major_version + 
rsvg_minor_version):rsvg_micro_version:rsvg_minor_version)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/doc/html/index.html 
new/librsvg-2.40.13/doc/html/index.html
--- old/librsvg-2.40.12/doc/html/index.html     2015-12-02 02:13:48.000000000 
+0100
+++ new/librsvg-2.40.13/doc/html/index.html     2016-01-08 02:44:53.000000000 
+0100
@@ -15,7 +15,7 @@
 <div>
 <div><table class="navigation" id="top" width="100%" cellpadding="2" 
cellspacing="0"><tr><th valign="middle"><p class="title">RSVG Libary Reference 
Manual</p></th></tr></table></div>
 <div><p class="releaseinfo">
-      For RSVG version 2.40.12
+      For RSVG version 2.40.13
 .
       The latest version of this documentation can be found on-line at the
       <a class="ulink" href="http://library.gnome.org/devel/rsvg/index.html"; 
target="_top">GNOME Library</a>.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/doc/version.xml 
new/librsvg-2.40.13/doc/version.xml
--- old/librsvg-2.40.12/doc/version.xml 2015-12-02 02:00:13.000000000 +0100
+++ new/librsvg-2.40.13/doc/version.xml 2015-12-02 21:27:37.000000000 +0100
@@ -1 +1 @@
-2.40.12
+2.40.13
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/librsvg-features.h 
new/librsvg-2.40.13/librsvg-features.h
--- old/librsvg-2.40.12/librsvg-features.h      2015-12-02 02:00:13.000000000 
+0100
+++ new/librsvg-2.40.13/librsvg-features.h      2015-12-02 21:27:36.000000000 
+0100
@@ -7,8 +7,8 @@
 
 #define LIBRSVG_MAJOR_VERSION (2)
 #define LIBRSVG_MINOR_VERSION (40)
-#define LIBRSVG_MICRO_VERSION (12)
-#define LIBRSVG_VERSION "2.40.12"
+#define LIBRSVG_MICRO_VERSION (13)
+#define LIBRSVG_VERSION "2.40.13"
 
 #define LIBRSVG_CHECK_VERSION(major,minor,micro) \
   (LIBRSVG_MAJOR_VERSION > (major) || \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/rsvg-cairo-draw.c 
new/librsvg-2.40.13/rsvg-cairo-draw.c
--- old/librsvg-2.40.12/rsvg-cairo-draw.c       2015-11-03 21:56:53.000000000 
+0100
+++ new/librsvg-2.40.13/rsvg-cairo-draw.c       2016-01-07 23:12:03.000000000 
+0100
@@ -458,16 +458,10 @@
     RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
     RsvgState *state = rsvg_current_state (ctx);
     cairo_t *cr;
-    int need_tmpbuf = 0;
     RsvgBbox bbox;
     double backup_tolerance;
 
-    need_tmpbuf = ((state->fill != NULL) && (state->stroke != NULL) && 
state->opacity != 0xff)
-        || state->clip_path || state->mask || state->filter
-        || (state->comp_op != CAIRO_OPERATOR_OVER);
-
-    if (need_tmpbuf)
-        rsvg_cairo_push_discrete_layer (ctx);
+    rsvg_cairo_push_discrete_layer (ctx);
 
     cr = render->cr;
 
@@ -530,10 +524,7 @@
 
         cairo_set_fill_rule (cr, state->fill_rule);
 
-        if (!need_tmpbuf)
-            opacity = (state->fill_opacity * state->opacity) / 255;
-        else
-            opacity = state->fill_opacity;
+        opacity = state->fill_opacity;
 
         _set_source_rsvg_paint_server (ctx,
                                        state->current_color,
@@ -548,10 +539,7 @@
 
     if (state->stroke != NULL) {
         int opacity;
-        if (!need_tmpbuf)
-            opacity = (state->stroke_opacity * state->opacity) / 255;
-        else
-            opacity = state->stroke_opacity;
+        opacity = state->stroke_opacity;
 
         _set_source_rsvg_paint_server (ctx,
                                        state->current_color,
@@ -563,8 +551,7 @@
 
     cairo_new_path (cr); /* clear the path in case stroke == fill == NULL; 
otherwise we leave it around from computing the bounding box */
 
-    if (need_tmpbuf)
-        rsvg_cairo_pop_discrete_layer (ctx);
+    rsvg_cairo_pop_discrete_layer (ctx);
 }
 
 void
@@ -724,8 +711,6 @@
 static void
 rsvg_cairo_push_render_stack (RsvgDrawingCtx * ctx)
 {
-    /* XXX: Untested, probably needs help wrt filters */
-
     RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
     cairo_surface_t *surface;
     cairo_t *child_cr;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/rsvg-css.c 
new/librsvg-2.40.13/rsvg-css.c
--- old/librsvg-2.40.12/rsvg-css.c      2015-08-18 22:07:56.000000000 +0200
+++ new/librsvg-2.40.13/rsvg-css.c      2016-01-06 01:55:44.000000000 +0100
@@ -204,6 +204,7 @@
     return out;
 }
 
+/* Recursive evaluation of all parent elements regarding absolute font size */
 double
 _rsvg_css_normalize_font_size (RsvgState * state, RsvgDrawingCtx * ctx)
 {
@@ -213,7 +214,7 @@
     case 'p':
     case 'm':
     case 'x':
-        parent= rsvg_state_parent (state);
+        parent = rsvg_state_parent (state);
         if (parent) {
             double parent_size;
             parent_size = _rsvg_css_normalize_font_size (parent, ctx);
@@ -263,6 +264,27 @@
     return 0;
 }
 
+/* Recursive evaluation of all parent elements regarding basline-shift */
+double
+_rsvg_css_accumulate_baseline_shift (RsvgState * state, RsvgDrawingCtx * ctx)
+{
+    RsvgState *parent;
+    double shift = 0.;
+
+    parent = rsvg_state_parent (state);
+    if (parent) {
+        if (state->has_baseline_shift) {
+            double parent_font_size;
+            parent_font_size = _rsvg_css_normalize_font_size (parent, ctx); /* 
font size from here */
+            shift = parent_font_size * state->baseline_shift;
+        }
+        shift += _rsvg_css_accumulate_baseline_shift (parent, ctx); /* 
baseline-shift for parent element */
+    }
+
+    return shift;
+}
+
+
 double
 _rsvg_css_hand_normalize_length (const RsvgLength * in, gdouble 
pixels_per_inch,
                                  gdouble width_or_height, gdouble font_size)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/rsvg-marker.c 
new/librsvg-2.40.13/rsvg-marker.c
--- old/librsvg-2.40.12/rsvg-marker.c   2015-10-22 16:45:11.000000000 +0200
+++ new/librsvg-2.40.13/rsvg-marker.c   2016-01-08 02:43:41.000000000 +0100
@@ -92,7 +92,7 @@
     marker->orientAuto = FALSE;
     marker->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
     marker->refX = marker->refY = _rsvg_css_parse_length ("0");
-    marker->width = marker->height = _rsvg_css_parse_length ("1");
+    marker->width = marker->height = _rsvg_css_parse_length ("3");
     marker->bbox = TRUE;
     marker->vbox.active = FALSE;
     marker->super.set_atts = rsvg_node_marker_set_atts;
@@ -109,6 +109,9 @@
     gdouble rotation;
     RsvgState *state = rsvg_current_state (ctx);
 
+    if (marker_name == NULL)
+        return; /* to avoid the caller having to check for nonexistent markers 
on every call */
+
     self = (RsvgMarker *) rsvg_acquire_node (ctx, marker_name);
     if (self == NULL || RSVG_NODE_TYPE (&self->super) != RSVG_NODE_TYPE_MARKER)
       {
@@ -133,7 +136,6 @@
     }
 
     if (self->vbox.active) {
-
         double w, h, x, y;
         w = _rsvg_css_normalize_length (&self->width, ctx, 'h');
         h = _rsvg_css_normalize_length (&self->height, ctx, 'v');
@@ -145,17 +147,9 @@
                                     self->vbox.rect.height,
                                     &w, &h, &x, &y);
 
-        x = -self->vbox.rect.x * w / self->vbox.rect.width;
-        y = -self->vbox.rect.y * h / self->vbox.rect.height;
-
-        cairo_matrix_init (&taffine,
-                           w / self->vbox.rect.width,
-                           0,
-                           0,
-                           h / self->vbox.rect.height,
-                           x,
-                           y);
+        cairo_matrix_init_scale (&taffine, w / self->vbox.rect.width, h / 
self->vbox.rect.height);
         cairo_matrix_multiply (&affine, &taffine, &affine);
+
         _rsvg_push_view_box (ctx, self->vbox.rect.width, 
self->vbox.rect.height);
     }
 
@@ -203,21 +197,361 @@
     rsvg_release_node (ctx, (RsvgNode *) self);
 }
 
+typedef struct {
+    gboolean is_degenerate; /* If true, only (p1x, p1y) are valid.  If false, 
all are valid */
+    double p1x, p1y;
+    double p2x, p2y;
+    double p3x, p3y;
+    double p4x, p4y;
+} Segment;
+
+typedef enum {
+    SEGMENT_START,
+    SEGMENT_END,
+} SegmentState;
+
+/* This converts a cairo_path_t into a list of curveto-like segments.  Each 
segment can be:
+ *
+ * 1. segment->is_degenerate = TRUE => the segment is actually a single point 
(segment->p1x, segment->p1y)
+ *
+ * 2. segment->is_degenerate = FALSE => either a lineto or a curveto (or the 
effective lineto that results from a closepath).
+ *    We have the following points:
+ *       P1 = (p1x, p1y)
+ *       P2 = (p2x, p2y)
+ *       P3 = (p3x, p3y)
+ *       P4 = (p4x, p4y)
+ *
+ *    The start and end points are P1 and P4, respectively.
+ *    The tangent at the start point is given by the vector (P2 - P1).
+ *    The tangent at the end point is given by the vector (P4 - P3).
+ *    The tangents also work if the segment refers to a lineto (they will both 
just point in the same direction).
+ */
+
+#define EPSILON 1e-10
+#define DOUBLE_EQUALS(a, b) (fabs ((a) - (b)) < EPSILON)
+
+static void
+path_to_segments (const cairo_path_t *path,
+                  Segment **out_segments,
+                  int *num_segments)
+{
+    int i;
+    double last_x, last_y;
+    double cur_x, cur_y;
+    double subpath_start_x, subpath_start_y;
+    int max_segments;
+    int segment_num;
+    Segment *segments;
+    SegmentState state;
+
+    max_segments = path->num_data; /* We'll generate maximum this many 
segments */
+    segments = g_new (Segment, max_segments);
+    *out_segments = segments;
+
+    last_x = last_y = cur_x = cur_y = subpath_start_x = subpath_start_y = 0.0;
+
+    segment_num = -1;
+    state = SEGMENT_END;
+
+    for (i = 0; i < path->num_data; i += path->data[i].header.length) {
+        last_x = cur_x;
+        last_y = cur_y;
+
+        switch (path->data[i].header.type) {
+        case CAIRO_PATH_MOVE_TO:
+            segment_num++;
+            g_assert (segment_num < max_segments);
+
+            g_assert (i + 1 < path->num_data);
+            cur_x = path->data[i + 1].point.x;
+            cur_y = path->data[i + 1].point.y;
+
+            subpath_start_x = cur_x;
+            subpath_start_y = cur_y;
+
+            segments[segment_num].is_degenerate = TRUE;
+
+            segments[segment_num].p1x = cur_x;
+            segments[segment_num].p1y = cur_y;
+
+            state = SEGMENT_START;
+
+            break;
+
+        case CAIRO_PATH_LINE_TO:
+            g_assert (i + 1 < path->num_data);
+            cur_x = path->data[i + 1].point.x;
+            cur_y = path->data[i + 1].point.y;
+
+            if (state == SEGMENT_START) {
+                segments[segment_num].is_degenerate = FALSE;
+                state = SEGMENT_END;
+            } else {
+                segment_num++;
+                g_assert (segment_num < max_segments);
+
+                segments[segment_num].is_degenerate = FALSE;
+
+                segments[segment_num].p1x = last_x;
+                segments[segment_num].p1y = last_y;
+            }
+
+            segments[segment_num].p2x = cur_x;
+            segments[segment_num].p2y = cur_y;
+
+            segments[segment_num].p3x = last_x;
+            segments[segment_num].p3y = last_y;
+
+            segments[segment_num].p4x = cur_x;
+            segments[segment_num].p4y = cur_y;
+
+            break;
+
+        case CAIRO_PATH_CURVE_TO:
+            g_assert (i + 3 < path->num_data);
+            cur_x = path->data[i + 3].point.x;
+            cur_y = path->data[i + 3].point.y;
+
+            if (state == SEGMENT_START) {
+                segments[segment_num].is_degenerate = FALSE;
+                state = SEGMENT_END;
+            } else {
+                segment_num++;
+                g_assert (segment_num < max_segments);
+
+                segments[segment_num].is_degenerate = FALSE;
+
+                segments[segment_num].p1x = last_x;
+                segments[segment_num].p1y = last_y;
+            }
+
+            segments[segment_num].p2x = path->data[i + 1].point.x;
+            segments[segment_num].p2y = path->data[i + 1].point.y;
+
+            segments[segment_num].p3x = path->data[i + 2].point.x;
+            segments[segment_num].p3y = path->data[i + 2].point.y;
+
+            segments[segment_num].p4x = cur_x;
+            segments[segment_num].p4y = cur_y;
+
+            /* Fix the tangents for when the middle control points coincide 
with their respective endpoints */
+
+            if (DOUBLE_EQUALS (segments[segment_num].p2x, 
segments[segment_num].p1x)
+                && DOUBLE_EQUALS (segments[segment_num].p2y, 
segments[segment_num].p1y)) {
+                segments[segment_num].p2x = segments[segment_num].p3x;
+                segments[segment_num].p2y = segments[segment_num].p3y;
+            }
+
+            if (DOUBLE_EQUALS (segments[segment_num].p3x, 
segments[segment_num].p4x)
+                && DOUBLE_EQUALS (segments[segment_num].p3y, 
segments[segment_num].p4y)) {
+                segments[segment_num].p3x = segments[segment_num].p2x;
+                segments[segment_num].p3y = segments[segment_num].p2y;
+            }
+
+            break;
+
+        case CAIRO_PATH_CLOSE_PATH:
+            cur_x = subpath_start_x;
+            cur_y = subpath_start_y;
+
+            if (state == SEGMENT_START) {
+                segments[segment_num].is_degenerate = FALSE;
+
+                segments[segment_num].p2x = cur_x;
+                segments[segment_num].p2y = cur_y;
+
+                segments[segment_num].p3x = last_x;
+                segments[segment_num].p3y = last_y;
+
+                segments[segment_num].p4x = cur_x;
+                segments[segment_num].p4y = cur_y;
+
+                state = SEGMENT_END;
+            } else {
+                /* nothing; closepath after moveto (or a single lone 
closepath) does nothing */
+            }
+
+            break;
+
+        default:
+            g_assert_not_reached ();
+        }
+    }
+
+    *num_segments = segment_num + 1;
+    g_assert (*num_segments <= max_segments);
+}
+
+static gboolean
+points_equal (double x1, double y1, double x2, double y2)
+{
+    return DOUBLE_EQUALS (x1, x2) && DOUBLE_EQUALS (y1, y2);
+}
+
+/* A segment is zero length if it is degenerate, or if all four control points
+ * coincide (the first and last control points may coincide, but the others may
+ * define a loop - thus nonzero length)
+ */
+static gboolean
+is_zero_length_segment (Segment *segment)
+{
+    double p1x, p1y;
+    double p2x, p2y;
+    double p3x, p3y;
+    double p4x, p4y;
+
+    if (segment->is_degenerate)
+        return TRUE;
+
+    p1x = segment->p1x;
+    p1y = segment->p1y;
+
+    p2x = segment->p2x;
+    p2y = segment->p2y;
+
+    p3x = segment->p3x;
+    p3y = segment->p3y;
+
+    p4x = segment->p4x;
+    p4y = segment->p4y;
+
+    return (points_equal (p1x, p1y, p2x, p2y)
+            && points_equal (p1x, p1y, p3x, p3y)
+            && points_equal (p1x, p1y, p4x, p4y));
+}
+
+/* The SVG spec 1.1 says 
http://www.w3.org/TR/SVG/implnote.html#PathElementImplementationNotes
+ *
+ * Certain line-capping and line-joining situations and markers
+ * require that a path segment have directionality at its start and
+ * end points. Zero-length path segments have no directionality. In
+ * these cases, the following algorithm is used to establish
+ * directionality:  to determine the directionality of the start
+ * point of a zero-length path segment, go backwards in the path
+ * data specification within the current subpath until you find a
+ * segment which has directionality at its end point (e.g., a path
+ * segment with non-zero length) and use its ending direction;
+ * otherwise, temporarily consider the start point to lack
+ * directionality. Similarly, to determine the directionality of the
+ * end point of a zero-length path segment, go forwards in the path
+ * data specification within the current subpath until you find a
+ * segment which has directionality at its start point (e.g., a path
+ * segment with non-zero length) and use its starting direction;
+ * otherwise, temporarily consider the end point to lack
+ * directionality. If the start point has directionality but the end
+ * point doesn't, then the end point uses the start point's
+ * directionality. If the end point has directionality but the start
+ * point doesn't, then the start point uses the end point's
+ * directionality. Otherwise, set the directionality for the path
+ * segment's start and end points to align with the positive x-axis
+ * in user space.
+ */
+static gboolean
+find_incoming_directionality_backwards (Segment *segments, int num_segments, 
int start_index, double *vx, double *vy)
+{
+    int j;
+    gboolean found;
+
+    /* "go backwards ... within the current subpath until ... segment which 
has directionality at its end point" */
+
+    found = FALSE;
+
+    for (j = start_index; j >= 0; j--) {
+        if (segments[j].is_degenerate)
+            break; /* reached the beginning of the subpath as we ran into a 
standalone point */
+        else {
+            if (is_zero_length_segment (&segments[j]))
+                continue;
+            else {
+                found = TRUE;
+                break;
+            }
+        }
+    }
+
+    if (found) {
+        g_assert (j >= 0);
+        *vx = segments[j].p4x - segments[j].p3x;
+        *vy = segments[j].p4y - segments[j].p3y;
+        return TRUE;
+    } else {
+        *vx = 0.0;
+        *vy = 0.0;
+        return FALSE;
+    }
+}
+
+static gboolean
+find_outgoing_directionality_forwards (Segment *segments, int num_segments, 
int start_index, double *vx, double *vy)
+{
+    int j;
+    gboolean found;
+
+    /* "go forwards ... within the current subpath until ... segment which has 
directionality at its start point" */
+
+    found = FALSE;
+
+    for (j = start_index; j < num_segments; j++) {
+        if (segments[j].is_degenerate)
+            break; /* reached the end of a subpath as we ran into a standalone 
point */
+        else {
+            if (is_zero_length_segment (&segments[j]))
+                continue;
+            else {
+                found = TRUE;
+                break;
+            }
+        }
+    }
+
+    if (found) {
+        g_assert (j < num_segments);
+        *vx = segments[j].p2x - segments[j].p1x;
+        *vy = segments[j].p2y - segments[j].p1y;
+        return TRUE;
+    } else {
+        *vx = 0.0;
+        *vy = 0.0;
+        return FALSE;
+    }
+}
+
+static double
+angle_from_vector (double vx, double vy)
+{
+    double angle;
+
+    angle = atan2 (vy, vx);
+
+    if (isnan (angle))
+        return 0.0;
+    else
+        return angle;
+}
+
+typedef enum {
+    NO_SUBPATH,
+    IN_SUBPATH,
+} SubpathState;
+
 void
 rsvg_render_markers (RsvgDrawingCtx * ctx,
                      const cairo_path_t *path)
 {
-    double x, y;
-    double lastx, lasty;
-    double linewidth;
-    cairo_path_data_type_t code, nextcode;
-
     RsvgState *state;
+    double linewidth;
     const char *startmarker;
     const char *middlemarker;
     const char *endmarker;
-    cairo_path_data_t *data, *nextdata, *end;
-    cairo_path_data_t nextp;
+
+    int i;
+    double incoming_vx, incoming_vy;
+    double outgoing_vx, outgoing_vy;
+
+    Segment *segments;
+    int num_segments;
+
+    SubpathState subpath_state;
 
     state = rsvg_current_state (ctx);
 
@@ -232,116 +566,80 @@
     if (!startmarker && !middlemarker && !endmarker)
         return;
 
-    x = 0;
-    y = 0;
-
     if (path->num_data <= 0)
         return;
 
-    end = &path->data[path->num_data];
-    data = &path->data[0];
-    nextcode = data[0].header.type;
-    if (data[0].header.length > 1)
-        nextp = data[data[0].header.length - 1];
-    else
-        nextp.point.x = nextp.point.y = 0.;
+    /* Convert the path to a list of segments and bare points (i.e. degenerate 
segments) */
+    path_to_segments (path, &segments, &num_segments);
 
-    for ( ; data < end; data = nextdata) {
-        lastx = x;
-        lasty = y;
-        x = nextp.point.x;
-        y = nextp.point.y;
-        code = nextcode;
-
-        nextdata = data + data->header.length;
-        if (nextdata < end) {
-            nextcode = nextdata->header.type;
-            if (nextdata->header.length > 1) {
-                nextp = nextdata[nextdata->header.length - 1];
-            } else {
-                /* keep nextp unchanged */
-            }
-        } else {
-            nextcode = CAIRO_PATH_MOVE_TO;
-        }
+    subpath_state = NO_SUBPATH;
 
-        if (nextcode == CAIRO_PATH_MOVE_TO ||
-            code == CAIRO_PATH_CLOSE_PATH) {
-            if (endmarker) {
-                if (code == CAIRO_PATH_CURVE_TO) {
-                    if (data[2].point.x == x && data[2].point.y == y) {
-                        /* Can't calculate angle as points are coincident; use 
the previous point */
-                        rsvg_marker_render (endmarker, x, y,
-                                            atan2 (y - data[1].point.y,
-                                                   x - data[1].point.x),
-                                            linewidth, ctx);
-                    } else {
-                        rsvg_marker_render (endmarker, x, y,
-                                            atan2 (y - data[2].point.y,
-                                                   x - data[2].point.x),
-                                            linewidth, ctx);
-                    }
-                } else {
-                    rsvg_marker_render (endmarker, x, y,
-                                        atan2 (y - lasty, x - lastx),
-                                        linewidth, ctx);
-                }
-            }
-        } else if (code == CAIRO_PATH_MOVE_TO ||
-                   code == CAIRO_PATH_CLOSE_PATH) {
-            if (startmarker) {
-                if (nextcode == CAIRO_PATH_CURVE_TO) {
-                    if (nextdata[1].point.x == x && nextdata[1].point.y == y) {
-                        /* Can't calculate angle as points are coincident; use 
the next point */
-                        rsvg_marker_render (startmarker, x, y,
-                                            atan2 (nextdata[2].point.y - y,
-                                                   nextdata[2].point.x - x),
-                                            linewidth,
-                                            ctx);
-                    } else {
-                        rsvg_marker_render (startmarker, x, y,
-                                            atan2 (nextdata[1].point.y - y,
-                                                   nextdata[1].point.x - x),
-                                            linewidth,
-                                            ctx);
-                    }
-                } else {
-                    rsvg_marker_render (startmarker, x, y,
-                                        atan2 (nextp.point.y - y, 
nextp.point.x - x),
-                                        linewidth,
-                                        ctx);
-                }
+    for (i = 0; i < num_segments; i++) {
+        incoming_vx = incoming_vy = outgoing_vx = outgoing_vy = 0.0;
+
+        if (segments[i].is_degenerate) {
+            if (subpath_state == IN_SUBPATH) {
+                g_assert (i > 0);
+
+                /* Got a lone point after a subpath; render the subpath's end 
marker first */
+
+                find_incoming_directionality_backwards (segments, 
num_segments, i - 1, &incoming_vx, &incoming_vy);
+                rsvg_marker_render (endmarker, segments[i - 1].p4x, segments[i 
- 1].p4y, angle_from_vector (incoming_vx, incoming_vy), linewidth, ctx);
             }
+
+            /* Render marker for the lone point; no directionality */
+            rsvg_marker_render (middlemarker, segments[i].p1x, 
segments[i].p1y, 0.0, linewidth, ctx);
+
+            subpath_state = NO_SUBPATH;
         } else {
-            if (middlemarker) {
-                double xdifin, ydifin, xdifout, ydifout, intot, outtot, angle;
+            /* Not a degenerate segment */
+
+            if (subpath_state == NO_SUBPATH) {
+                find_outgoing_directionality_forwards (segments, num_segments, 
i, &outgoing_vx, &outgoing_vy);
+                rsvg_marker_render (startmarker, segments[i].p1x, 
segments[i].p1y, angle_from_vector (outgoing_vx, outgoing_vy), linewidth, ctx);
+
+                subpath_state = IN_SUBPATH;
+            } else {
+                /* subpath_state == IN_SUBPATH */
+
+                gboolean has_incoming, has_outgoing;
+                double incoming, outgoing;
+                double angle;
+
+                g_assert (i > 0);
+
+                has_incoming = find_incoming_directionality_backwards 
(segments, num_segments, i - 1, &incoming_vx, &incoming_vy);
+                has_outgoing = find_outgoing_directionality_forwards 
(segments, num_segments, i, &outgoing_vx, &outgoing_vy);
 
-                if (code == CAIRO_PATH_CURVE_TO) {
-                    xdifin = x - data[2].point.x;
-                    ydifin = y - data[2].point.y;
-                } else {
-                    xdifin = x - lastx;
-                    ydifin = y - lasty;
-                }
-                if (nextcode == CAIRO_PATH_CURVE_TO) {
-                    xdifout = nextdata[1].point.x - x;
-                    ydifout = nextdata[1].point.y - y;
-                } else {
-                    xdifout = nextp.point.x - x;
-                    ydifout = nextp.point.y - y;
-                }
-
-                intot = sqrt (xdifin * xdifin + ydifin * ydifin);
-                outtot = sqrt (xdifout * xdifout + ydifout * ydifout);
-
-                xdifin /= intot;
-                ydifin /= intot;
-                xdifout /= outtot;
-                ydifout /= outtot;
+                if (has_incoming)
+                    incoming = angle_from_vector (incoming_vx, incoming_vy);
 
-                angle = atan2 ((ydifin + ydifout) / 2, (xdifin + xdifout) / 2);
-                rsvg_marker_render (middlemarker, x, y, angle, linewidth, ctx);
+                if (has_outgoing)
+                    outgoing = angle_from_vector (outgoing_vx, outgoing_vy);
+
+                if (has_incoming && has_outgoing)
+                    angle = (incoming + outgoing) / 2;
+                else if (has_incoming)
+                    angle = incoming;
+                else if (has_outgoing)
+                    angle = outgoing;
+                else
+                    angle = 0.0;
+
+                rsvg_marker_render (middlemarker, segments[i].p1x, 
segments[i].p1y, angle, linewidth, ctx);
             }
         }
     }
+
+    /* Finally, render the last point */
+
+    if (num_segments > 0) {
+        if (!segments[num_segments - 1].is_degenerate) {
+            find_incoming_directionality_backwards (segments, num_segments, 
num_segments - 1, &incoming_vx, &incoming_vy);
+
+            rsvg_marker_render (endmarker, segments[num_segments - 1].p4x, 
segments[num_segments - 1].p4y, angle_from_vector (incoming_vx, incoming_vy), 
linewidth, ctx);
+        }
+    }
+
+    g_free (segments);
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/rsvg-private.h 
new/librsvg-2.40.13/rsvg-private.h
--- old/librsvg-2.40.12/rsvg-private.h  2015-10-22 16:45:11.000000000 +0200
+++ new/librsvg-2.40.13/rsvg-private.h  2016-01-06 01:56:07.000000000 +0100
@@ -394,6 +394,8 @@
                                          gdouble width_or_height, gdouble 
font_size);
 double _rsvg_css_normalize_font_size    (RsvgState * state, RsvgDrawingCtx * 
ctx);
 G_GNUC_INTERNAL
+double _rsvg_css_accumulate_baseline_shift (RsvgState * state, RsvgDrawingCtx 
* ctx);
+G_GNUC_INTERNAL
 RsvgLength _rsvg_css_parse_length (const char *str);
 G_GNUC_INTERNAL
 void _rsvg_push_view_box    (RsvgDrawingCtx * ctx, double w, double h);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/rsvg-styles.c 
new/librsvg-2.40.13/rsvg-styles.c
--- old/librsvg-2.40.12/rsvg-styles.c   2015-10-22 16:45:11.000000000 +0200
+++ new/librsvg-2.40.13/rsvg-styles.c   2016-01-06 02:36:33.000000000 +0100
@@ -118,6 +118,7 @@
     cairo_matrix_init_identity (&state->personal_affine);
     state->mask = NULL;
     state->opacity = 0xff;
+    state->baseline_shift = 0.;
     state->fill = rsvg_paint_server_parse (NULL, "#000");
     state->fill_opacity = 0xff;
     state->stroke_opacity = 0xff;
@@ -153,6 +154,7 @@
     state->middleMarker = NULL;
     state->endMarker = NULL;
 
+    state->has_baseline_shift = FALSE;
     state->has_current_color = FALSE;
     state->has_flood_color = FALSE;
     state->has_flood_opacity = FALSE;
@@ -253,6 +255,8 @@
 {
     gint i;
 
+    if (function (dst->has_baseline_shift, src->has_baseline_shift))
+        dst->baseline_shift = src->baseline_shift;
     if (function (dst->has_current_color, src->has_current_color))
         dst->current_color = src->current_color;
     if (function (dst->has_flood_color, src->has_flood_color))
@@ -513,6 +517,22 @@
     } else if (g_str_equal (name, "mask")) {
         g_free (state->mask);
         state->mask = rsvg_get_url_string (value);
+    } else if (g_str_equal (name, "baseline-shift")) {
+        /* These values come from Inkscape's 
SP_CSS_BASELINE_SHIFT_(SUB/SUPER/BASELINE);
+         * see sp_style_merge_baseline_shift_from_parent()
+         */
+        if (g_str_equal (value, "sub")) {
+           state->has_baseline_shift = TRUE;
+           state->baseline_shift = -0.2;
+        } else if (g_str_equal (value, "super")) {
+           state->has_baseline_shift = TRUE;
+           state->baseline_shift = 0.4;
+        } else if (g_str_equal (value, "baseline")) {
+           state->has_baseline_shift = TRUE;
+           state->baseline_shift = 0.;
+        } else {
+          g_warning ("value \'%s\' for attribute \'baseline-shift\' is not 
supported; only 'sub', 'super', and 'baseline' are supported\n", value);
+        }
     } else if (g_str_equal (name, "clip-path")) {
         g_free (state->clip_path);
         state->clip_path = rsvg_get_url_string (value);
@@ -861,7 +881,7 @@
 void
 rsvg_parse_style_pairs (RsvgHandle * ctx, RsvgState * state, RsvgPropertyBag * 
atts)
 {
-    rsvg_lookup_parse_style_pair (ctx, state, "a:adobe-blending-mode", atts);
+    rsvg_lookup_parse_style_pair (ctx, state, "baseline-shift", atts);
     rsvg_lookup_parse_style_pair (ctx, state, "clip-path", atts);
     rsvg_lookup_parse_style_pair (ctx, state, "clip-rule", atts);
     rsvg_lookup_parse_style_pair (ctx, state, "color", atts);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/rsvg-styles.h 
new/librsvg-2.40.13/rsvg-styles.h
--- old/librsvg-2.40.12/rsvg-styles.h   2015-10-22 16:45:11.000000000 +0200
+++ new/librsvg-2.40.13/rsvg-styles.h   2016-01-06 01:49:51.000000000 +0100
@@ -83,6 +83,8 @@
     char *mask;
     char *clip_path;
     guint8 opacity;             /* 0..255 */
+    double baseline_shift;
+    gboolean has_baseline_shift;
 
     RsvgPaintServer *fill;
     gboolean has_fill_server;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/librsvg-2.40.12/rsvg-text.c 
new/librsvg-2.40.13/rsvg-text.c
--- old/librsvg-2.40.12/rsvg-text.c     2015-10-22 16:45:11.000000000 +0200
+++ new/librsvg-2.40.13/rsvg-text.c     2016-01-06 02:35:13.000000000 +0100
@@ -163,6 +163,7 @@
                             gdouble * x, gdouble * y, gboolean * lastwasspace,
                             gboolean usetextonly);
 
+/* This function is responsible of selecting render for a text element 
including its children and giving it the drawing context */
 static void
 _rsvg_node_text_type_children (RsvgNode * self, RsvgDrawingCtx * ctx,
                                gdouble * x, gdouble * y, gboolean * 
lastwasspace,
@@ -598,7 +599,8 @@
     PangoLayout *layout;
     PangoLayoutIter *iter;
     RsvgState *state;
-    gint w, h, offsetX, offsetY;
+    gint w, h;
+    double offset_x, offset_y, offset;
 
     state = rsvg_current_state (ctx);
 
@@ -610,15 +612,17 @@
     layout = rsvg_text_create_layout (ctx, state, text, context);
     pango_layout_get_size (layout, &w, &h);
     iter = pango_layout_get_iter (layout);
+    offset = pango_layout_iter_get_baseline (iter) / (double) PANGO_SCALE;
+    offset += _rsvg_css_accumulate_baseline_shift (state, ctx);
     if (PANGO_GRAVITY_IS_VERTICAL (state->text_gravity)) {
-        offsetX = -pango_layout_iter_get_baseline (iter) / (double)PANGO_SCALE;
-        offsetY = 0;
+        offset_x = -offset;
+        offset_y = 0;
     } else {
-        offsetX = 0;
-        offsetY = pango_layout_iter_get_baseline (iter) / (double)PANGO_SCALE;
+        offset_x = 0;
+        offset_y = offset;
     }
     pango_layout_iter_free (iter);
-    ctx->render->render_pango_layout (ctx, layout, *x - offsetX, *y - offsetY);
+    ctx->render->render_pango_layout (ctx, layout, *x - offset_x, *y - 
offset_y);
     if (PANGO_GRAVITY_IS_VERTICAL (state->text_gravity))
         *y += w / (double)PANGO_SCALE;
     else


Reply via email to