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 > $(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache +$(GlibEtcInstallRoot)\bin\gdk-pixbuf-query-loaders.exe > $(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 > $(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache +$(GlibEtcInstallRoot)\bin\gdk-pixbuf-query-loaders.exe > $(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)
 -mkdir $(GlibEtcInstallRoot)\bin
 +mkdir $(CopyDir)
 +mkdir $(CopyDir)\bin
 copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\$(RsvgDllPrefix)rsvg$(RsvgDllSuffix).dll $(CopyDir)\bin
 copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\$(RsvgDllPrefix)rsvg$(RsvgDllSuffix).pdb $(CopyDir)\bin
 copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\rsvg-convert.exe $(CopyDir)\bin
 @@ -25,7 +25,7 @@ copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\rsvg-$(ApiVersion).lib $(CopyDir)\lib
 copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\libpixbufloader-svg.dll $(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders
 copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\libpixbufloader-svg.pdb $(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders
 -$(CopyDir)\bin\gdk-pixbuf-query-loaders.exe > $(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache
 +$(GlibEtcInstallRoot)\bin\gdk-pixbuf-query-loaders.exe > $(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache
 " /> </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)
 -mkdir $(GlibEtcInstallRoot)\bin
 +mkdir $(CopyDir)
 +mkdir $(CopyDir)\bin
 copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\$(RsvgDllPrefix)rsvg$(RsvgDllSuffix).dll $(CopyDir)\bin
 copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\$(RsvgDllPrefix)rsvg$(RsvgDllSuffix).pdb $(CopyDir)\bin
 @@ -26,7 +26,7 @@ copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\libpixbufloader-svg.dll $(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders
 copy $(SolutionDir)$(ConfigurationName)\$(PlatformName)\bin\libpixbufloader-svg.pdb $(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders
 -$(CopyDir)\bin\gdk-pixbuf-query-loaders.exe > $(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache
 +$(GlibEtcInstallRoot)\bin\gdk-pixbuf-query-loaders.exe > $(CopyDir)\lib\gdk-pixbuf-2.0\2.10.0\loaders.cache
 " /> </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