Hello community,
here is the log from the commit of package librsvg for openSUSE:Factory checked in at 2015-04-03 14:33:50
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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-03-03 11:13:15.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.librsvg.new/librsvg.changes 2015-04-03 14:33:51.000000000 +0200
@@ -1,0 +2,9 @@
+Fri Mar 27 09:22:06 UTC 2015 - zaitor@opensuse.org
+
+- Update to version 2.40.9:
+ + bgo#738367: V/v/H/h commands in path elements were not working.
+ + bgo#605875: Gaussian-blurred objects were sometimes missing.
+ + bgo#710163: Use _wfullpath() on Windows when canonicalizing
+ filenames.
+
+-------------------------------------------------------------------
Old:
----
librsvg-2.40.8.tar.xz
New:
----
librsvg-2.40.9.tar.xz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ librsvg.spec ++++++
--- /var/tmp/diff_new_pack.ZO2Tc0/_old 2015-04-03 14:33:52.000000000 +0200
+++ /var/tmp/diff_new_pack.ZO2Tc0/_new 2015-04-03 14:33:52.000000000 +0200
@@ -17,7 +17,7 @@
Name: librsvg
-Version: 2.40.8
+Version: 2.40.9
Release: 0
Summary: A Library for Rendering SVG Data
License: LGPL-2.0+ and GPL-2.0+
++++++ librsvg-2.40.8.tar.xz -> librsvg-2.40.9.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librsvg-2.40.8/ChangeLog new/librsvg-2.40.9/ChangeLog
--- old/librsvg-2.40.8/ChangeLog 2015-02-27 17:37:39.000000000 +0100
+++ new/librsvg-2.40.9/ChangeLog 2015-03-27 00:50:34.000000000 +0100
@@ -1,3 +1,94 @@
+commit 19bb11837877538382cd11f7243f9875e082268f
+Author: Federico Mena Quintero
+Date: Wed Mar 25 19:47:09 2015 -0600
+
+ Update NEWS
+
+ NEWS | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+commit 22a90daef0813f1cf2ac70a15266a8b820145b3c
+Author: Federico Mena Quintero
+Date: Wed Mar 25 19:44:31 2015 -0600
+
+ Bump version
+
+ configure.ac | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+commit 28694c791067f0321ae21d44734b1ef88b45d742
+Author: LRN
+Date: Tue Mar 24 18:14:23 2015 -0600
+
+ bgo#710163 - Use _wfullpath() on Windows instead of _fullpath()
+
+ rsvg-base.c | 32 ++++++++++++++++++++++++++------
+ 1 file changed, 26 insertions(+), 6 deletions(-)
+
+commit 7fc95d9571c7d25e548a590aae482f9707f290d2
+Author: Federico Mena Quintero
+Date: Tue Mar 24 15:25:19 2015 -0600
+
+ Gaussian blur: clip the blurred image to the filter effects region
+
+ rsvg-filter.c | 29 ++++++++++++++++++++++++-----
+ 1 file changed, 24 insertions(+), 5 deletions(-)
+
+commit 054807726db76558728e7a7513aabc4698b3dc95
+Author: Federico Mena Quintero
+Date: Fri Mar 13 12:23:11 2015 -0600
+
+ bgo#605875 - Gaussian blurred objects are sometimes missing
+
+ This replaces the blurring machinery with a real gaussian blur for small radiuses,
+ and fixes box blurs for large radiuses.
+
+ Based on a patch by Eduard Braun.
+
+ rsvg-filter.c | 598 ++++++++++++++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 494 insertions(+), 104 deletions(-)
+
+commit 86589fb2046d0d8996ed024c3036f3c0ed48d695
+Author: Federico Mena Quintero
+Date: Tue Mar 10 17:48:12 2015 -0600
+
+ Add test for bgo#605875 - Incorrect rendering of feGaussianBlur
+
+ This test image comes from
+ https://commons.wikimedia.org/wiki/File:Kaliningrad_Oblast_Coat_of_Arms_2006...
+ The topmost jewel in the center of the crown was not getting
+ rendered at all.
+
+ tests/bugs/605875-ref.png | Bin 0 -> 156652 bytes
+ tests/bugs/605875.svg | 681 ++++++++++++++++++++++++++++++++++++++++++++++
+ tests/rsvg-test.txt | 1 +
+ 3 files changed, 682 insertions(+)
+
+commit 9628f3da0023bfd3e919e2bfb4c2dc10ad45d9ab
+Author: Andrea Griffini
+Date: Fri Mar 13 12:36:24 2015 -0600
+
+ bgo#738367 - Fix handling of V/v/H/h commands in path
+
+ These were not setting one of the x/y components for the reflection point
+ to be used in smooth curves.
+
+ https://bugzilla.gnome.org/show_bug.cgi?id=738367
+
+ rsvg-path.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+commit f8d37dfb240f0ecb90a91ce534829ec7ac279071
+Author: Federico Mena Quintero
+Date: Fri Mar 13 12:44:53 2015 -0600
+
+ Add test for bgo#738367 - incorrect handling of V/v/H/h commands in path
+
+ tests/bugs/738367-ref.png | Bin 0 -> 4184 bytes
+ tests/bugs/738367.svg | 7 +++++++
+ tests/rsvg-test.txt | 1 +
+ 3 files changed, 8 insertions(+)
+
commit 8eb0392f2041080f32830949ae22cd463bf219b7
Author: Federico Mena Quintero
Date: Thu Feb 26 16:03:52 2015 -0600
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librsvg-2.40.8/NEWS new/librsvg-2.40.9/NEWS
--- old/librsvg-2.40.8/NEWS 2015-02-26 23:03:06.000000000 +0100
+++ new/librsvg-2.40.9/NEWS 2015-03-26 02:47:02.000000000 +0100
@@ -1,3 +1,11 @@
+Version 2.40.9
+- Fixed bgo#738367 - V/v/H/h commands in path elements were not
+ working. Patch by Andrea Griffini.
+- Fixed bgo#605875 - Gaussian-blurred objects were sometimes missing.
+ Based on a patch by Eduard Braun.
+- Fixed bgo#710163 - use _wfullpath() on Windows when canonicalizing
+ filenames. Patch by LRN.
+
Version 2.40.8
- Bugs fixed from fuzz testing: #744688 - possible double g_free()
when processing stroke-dasharray
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librsvg-2.40.8/configure new/librsvg-2.40.9/configure
--- old/librsvg-2.40.8/configure 2015-02-27 17:36:55.000000000 +0100
+++ new/librsvg-2.40.9/configure 2015-03-27 00:48:49.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.8.
+# Generated by GNU Autoconf 2.69 for RSVG 2.40.9.
#
# 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.8'
-PACKAGE_STRING='RSVG 2.40.8'
+PACKAGE_VERSION='2.40.9'
+PACKAGE_STRING='RSVG 2.40.9'
PACKAGE_BUGREPORT='https://bugzilla.gnome.org/enter_bug.cgi?product=librsvg'
PACKAGE_URL=''
@@ -1422,7 +1422,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.8 to adapt to many kinds of systems.
+\`configure' configures RSVG 2.40.9 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1492,7 +1492,7 @@
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of RSVG 2.40.8:";;
+ short | recursive ) echo "Configuration of RSVG 2.40.9:";;
esac
cat <<\_ACEOF
@@ -1642,7 +1642,7 @@
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-RSVG configure 2.40.8
+RSVG configure 2.40.9
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2011,7 +2011,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.8, which was
+It was created by RSVG $as_me 2.40.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2880,7 +2880,7 @@
# Define the identity of the package.
PACKAGE='librsvg'
- VERSION='2.40.8'
+ VERSION='2.40.9'
cat >>confdefs.h <<_ACEOF
@@ -3018,13 +3018,13 @@
# ===========================================================================
-RSVG_LT_VERSION_INFO=42:8:40
+RSVG_LT_VERSION_INFO=42:9:40
LIBRSVG_MAJOR_VERSION=2
LIBRSVG_MINOR_VERSION=40
-LIBRSVG_MICRO_VERSION=8
+LIBRSVG_MICRO_VERSION=9
@@ -15547,7 +15547,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.8, which was
+This file was extended by RSVG $as_me 2.40.9, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -15613,7 +15613,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.8
+RSVG config.status 2.40.9
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.8/configure.ac new/librsvg-2.40.9/configure.ac
--- old/librsvg-2.40.8/configure.ac 2015-02-13 23:47:01.000000000 +0100
+++ new/librsvg-2.40.9/configure.ac 2015-03-26 02:44:03.000000000 +0100
@@ -1,6 +1,6 @@
m4_define([rsvg_major_version],[2])
m4_define([rsvg_minor_version],[40])
-m4_define([rsvg_micro_version],[8])
+m4_define([rsvg_micro_version],[9])
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.8/doc/html/annotation-glossary.html new/librsvg-2.40.9/doc/html/annotation-glossary.html
--- old/librsvg-2.40.8/doc/html/annotation-glossary.html 2015-02-27 17:37:39.000000000 +0100
+++ new/librsvg-2.40.9/doc/html/annotation-glossary.html 2015-03-27 00:50:34.000000000 +0100
@@ -21,35 +21,35 @@
<td><a accesskey="n" href="licence.html"><img src="right.png" width="24" height="24" border="0" alt="Next"></a></td>
</tr>
<tr><td colspan="5" class="shortcuts">
-<a class="shortcut" href="#glsO">O</a>
+<a class="shortcut" href="#glsT">T</a>
|
<a class="shortcut" href="#glsA">A</a>
|
- <a class="shortcut" href="#glsT">T</a>
- |
- <a class="shortcut" href="#glsE">E</a>
+ <a class="shortcut" href="#glsO">O</a>
|
<a class="shortcut" href="#glsA">A</a>
+ |
+ <a class="shortcut" href="#glsE">E</a>
</td></tr>
</table>
<div class="glossary">
<div class="titlepage"><div><div><h1 class="title">
<a name="annotation-glossary"></a>Annotation Glossary</h1></div></div></div>
+<a name="glsT"></a><h3 class="title">T</h3>
+<dt><span class="glossterm"><a name="annotation-glossterm-transfer%20full"></a>transfer full</span></dt>
+<dd class="glossdef"><p>Free data after the code is done.</p></dd>
+<a name="glsA"></a><h3 class="title">A</h3>
+<dt><span class="glossterm"><a name="annotation-glossterm-array"></a>array</span></dt>
+<dd class="glossdef"><p>Parameter points to an array of items.</p></dd>
<a name="glsO"></a><h3 class="title">O</h3>
<dt><span class="glossterm"><a name="annotation-glossterm-out"></a>out</span></dt>
<dd class="glossdef"><p>Parameter for returning results. Default is <acronym title="Free data after the code is done."><span class="acronym">transfer full</span></acronym>.</p></dd>
<a name="glsA"></a><h3 class="title">A</h3>
-<dt><span class="glossterm"><a name="annotation-glossterm-array"></a>array</span></dt>
-<dd class="glossdef"><p>Parameter points to an array of items.</p></dd>
-<a name="glsT"></a><h3 class="title">T</h3>
-<dt><span class="glossterm"><a name="annotation-glossterm-transfer%20full"></a>transfer full</span></dt>
-<dd class="glossdef"><p>Free data after the code is done.</p></dd>
+<dt><span class="glossterm"><a name="annotation-glossterm-allow-none"></a>allow-none</span></dt>
+<dd class="glossdef"><p>NULL is ok, both for passing and for returning.</p></dd>
<a name="glsE"></a><h3 class="title">E</h3>
<dt><span class="glossterm"><a name="annotation-glossterm-element-type"></a>element-type</span></dt>
<dd class="glossdef"><p>Generics and defining elements of containers and arrays.</p></dd>
-<a name="glsA"></a><h3 class="title">A</h3>
-<dt><span class="glossterm"><a name="annotation-glossterm-allow-none"></a>allow-none</span></dt>
-<dd class="glossdef"><p>NULL is ok, both for passing and for returning.</p></dd>
</div>
<div class="footer">
<hr>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librsvg-2.40.8/doc/html/index.html new/librsvg-2.40.9/doc/html/index.html
--- old/librsvg-2.40.8/doc/html/index.html 2015-02-27 17:37:39.000000000 +0100
+++ new/librsvg-2.40.9/doc/html/index.html 2015-03-27 00:50:34.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.8
+ For RSVG version 2.40.9
.
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.8/doc/html/index.sgml new/librsvg-2.40.9/doc/html/index.sgml
--- old/librsvg-2.40.8/doc/html/index.sgml 2015-02-27 17:37:39.000000000 +0100
+++ new/librsvg-2.40.9/doc/html/index.sgml 2015-03-27 00:50:34.000000000 +0100
@@ -96,8 +96,8 @@
<ANCHOR id="LIBRSVG-HAVE-SVGZ:CAPS" href="rsvg/rsvg-Version-check-and-feature-tests.html#LIBRSVG-HAVE-SVGZ:CAPS">
<ANCHOR id="LIBRSVG-HAVE-CSS:CAPS" href="rsvg/rsvg-Version-check-and-feature-tests.html#LIBRSVG-HAVE-CSS:CAPS">
<ANCHOR id="LIBRSVG-CHECK-FEATURE:CAPS" href="rsvg/rsvg-Version-check-and-feature-tests.html#LIBRSVG-CHECK-FEATURE:CAPS">
-<ANCHOR id="annotation-glossterm-out" href="rsvg/annotation-glossary.html#annotation-glossterm-out">
-<ANCHOR id="annotation-glossterm-array" href="rsvg/annotation-glossary.html#annotation-glossterm-array">
<ANCHOR id="annotation-glossterm-transfer full" href="rsvg/annotation-glossary.html#annotation-glossterm-transfer full">
-<ANCHOR id="annotation-glossterm-element-type" href="rsvg/annotation-glossary.html#annotation-glossterm-element-type">
+<ANCHOR id="annotation-glossterm-array" href="rsvg/annotation-glossary.html#annotation-glossterm-array">
+<ANCHOR id="annotation-glossterm-out" href="rsvg/annotation-glossary.html#annotation-glossterm-out">
<ANCHOR id="annotation-glossterm-allow-none" href="rsvg/annotation-glossary.html#annotation-glossterm-allow-none">
+<ANCHOR id="annotation-glossterm-element-type" href="rsvg/annotation-glossary.html#annotation-glossterm-element-type">
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librsvg-2.40.8/doc/version.xml new/librsvg-2.40.9/doc/version.xml
--- old/librsvg-2.40.8/doc/version.xml 2015-02-27 17:36:59.000000000 +0100
+++ new/librsvg-2.40.9/doc/version.xml 2015-03-27 00:48:51.000000000 +0100
@@ -1 +1 @@
-2.40.8
+2.40.9
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librsvg-2.40.8/librsvg-features.h new/librsvg-2.40.9/librsvg-features.h
--- old/librsvg-2.40.8/librsvg-features.h 2015-02-27 17:36:59.000000000 +0100
+++ new/librsvg-2.40.9/librsvg-features.h 2015-03-27 00:48:51.000000000 +0100
@@ -7,8 +7,8 @@
#define LIBRSVG_MAJOR_VERSION (2)
#define LIBRSVG_MINOR_VERSION (40)
-#define LIBRSVG_MICRO_VERSION (8)
-#define LIBRSVG_VERSION "2.40.8"
+#define LIBRSVG_MICRO_VERSION (9)
+#define LIBRSVG_VERSION "2.40.9"
#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.8/rsvg-base.c new/librsvg-2.40.9/rsvg-base.c
--- old/librsvg-2.40.8/rsvg-base.c 2015-02-12 21:08:09.000000000 +0100
+++ new/librsvg-2.40.9/rsvg-base.c 2015-03-25 01:12:48.000000000 +0100
@@ -57,13 +57,33 @@
#include "rsvg-paint-server.h"
#include "rsvg-xml.h"
-/*
- * XXX: Perhaps do a GIO-based implementation for
- * realpath() or use gnulib implementation for this
- * https://bugzilla.gnome.org/show_bug.cgi?id=710163
- */
#ifdef G_OS_WIN32
-#define realpath(a,b) _fullpath(b,a,_MAX_PATH)
+static char *
+rsvg_realpath_utf8 (const char *filename, const char *unused)
+{
+ wchar_t *wfilename;
+ wchar_t *wfull;
+ char *full;
+
+ wfilename = g_utf8_to_utf16 (filename, -1, NULL, NULL, NULL);
+ if (!wfilename)
+ return NULL;
+
+ wfull = _wfullpath (NULL, wfilename, 0);
+ g_free (wfilename);
+ if (!wfull)
+ return NULL;
+
+ full = g_utf16_to_utf8 (wfull, -1, NULL, NULL, NULL);
+ free (wfull);
+
+ if (!full)
+ return NULL;
+
+ return full;
+}
+
+#define realpath(a,b) rsvg_realpath_utf8 (a, b)
#endif
/*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librsvg-2.40.8/rsvg-filter.c new/librsvg-2.40.9/rsvg-filter.c
--- old/librsvg-2.40.8/rsvg-filter.c 2015-02-20 01:18:08.000000000 +0100
+++ new/librsvg-2.40.9/rsvg-filter.c 2015-03-24 22:22:07.000000000 +0100
@@ -1327,154 +1327,545 @@
};
static void
-box_blur (cairo_surface_t *in,
- cairo_surface_t *output,
- guchar *intermediate,
- gint kw,
- gint kh,
- RsvgIRect boundarys,
- RsvgFilterPrimitiveOutput op)
+box_blur_line (gint box_width, gint even_offset,
+ guchar *src, guchar *dest,
+ gint len, gint bpp)
{
- gint ch;
- gint x, y;
- gint rowstride;
- guchar *in_pixels;
- guchar *output_pixels;
- gint sum;
+ gint i;
+ gint lead; /* This marks the leading edge of the kernel */
+ gint output; /* This marks the center of the kernel */
+ gint trail; /* This marks the pixel BEHIND the last 1 in the
+ kernel; it's the pixel to remove from the accumulator. */
+ gint ac[bpp]; /* Accumulator for each channel */
+
+
+ /* The algorithm differs for even and odd-sized kernels.
+ * With the output at the center,
+ * If odd, the kernel might look like this: 0011100
+ * If even, the kernel will either be centered on the boundary between
+ * the output and its left neighbor, or on the boundary between the
+ * output and its right neighbor, depending on even_lr.
+ * So it might be 0111100 or 0011110, where output is on the center
+ * of these arrays.
+ */
+ lead = 0;
+
+ if (box_width % 2 != 0) {
+ /* Odd-width kernel */
+ output = lead - (box_width - 1) / 2;
+ trail = lead - box_width;
+ } else {
+ /* Even-width kernel. */
+ if (even_offset == 1) {
+ /* Right offset */
+ output = lead + 1 - box_width / 2;
+ trail = lead - box_width;
+ } else if (even_offset == -1) {
+ /* Left offset */
+ output = lead - box_width / 2;
+ trail = lead - box_width;
+ } else {
+ /* If even_offset isn't 1 or -1, there's some error. */
+ g_assert_not_reached ();
+ }
+ }
- in_pixels = cairo_image_surface_get_data (in);
- output_pixels = cairo_image_surface_get_data (output);
+ /* Initialize accumulator */
+ for (i = 0; i < bpp; i++)
+ ac[i] = 0;
+
+ /* As the kernel moves across the image, it has a leading edge and a
+ * trailing edge, and the output is in the middle. */
+ while (output < len) {
+ /* The number of pixels that are both in the image and
+ * currently covered by the kernel. This is necessary to
+ * handle edge cases. */
+ guint coverage = (lead < len ? lead : len - 1) - (trail >= 0 ? trail : -1);
+
+#ifdef READABLE_BOXBLUR_CODE
+/* The code here does the same as the code below, but the code below
+ * has been optimized by moving the if statements out of the tight for
+ * loop, and is harder to understand.
+ * Don't use both this code and the code below. */
+ for (i = 0; i < bpp; i++) {
+ /* If the leading edge of the kernel is still on the image,
+ * add the value there to the accumulator. */
+ if (lead < len)
+ ac[i] += src[bpp * lead + i];
+
+ /* If the trailing edge of the kernel is on the image,
+ * subtract the value there from the accumulator. */
+ if (trail >= 0)
+ ac[i] -= src[bpp * trail + i];
+
+ /* Take the averaged value in the accumulator and store
+ * that value in the output. The number of pixels currently
+ * stored in the accumulator can be less than the nominal
+ * width of the kernel because the kernel can go "over the edge"
+ * of the image. */
+ if (output >= 0)
+ dest[bpp * output + i] = (ac[i] + (coverage >> 1)) / coverage;
+ }
+#endif
- rowstride = cairo_image_surface_get_stride (in);
+ /* If the leading edge of the kernel is still on the image... */
+ if (lead < len) {
+ if (trail >= 0) {
+ /* If the trailing edge of the kernel is on the image. (Since
+ * the output is in between the lead and trail, it must be on
+ * the image. */
+ for (i = 0; i < bpp; i++) {
+ ac[i] += src[bpp * lead + i];
+ ac[i] -= src[bpp * trail + i];
+ dest[bpp * output + i] = (ac[i] + (coverage >> 1)) / coverage;
+ }
+ } else if (output >= 0) {
+ /* If the output is on the image, but the trailing edge isn't yet
+ * on the image. */
+
+ for (i = 0; i < bpp; i++) {
+ ac[i] += src[bpp * lead + i];
+ dest[bpp * output + i] = (ac[i] + (coverage >> 1)) / coverage;
+ }
+ } else {
+ /* If leading edge is on the image, but the output and trailing
+ * edge aren't yet on the image. */
+ for (i = 0; i < bpp; i++)
+ ac[i] += src[bpp * lead + i];
+ }
+ } else if (trail >= 0) {
+ /* If the leading edge has gone off the image, but the output and
+ * trailing edge are on the image. (The big loop exits when the
+ * output goes off the image. */
+ for (i = 0; i < bpp; i++) {
+ ac[i] -= src[bpp * trail + i];
+ dest[bpp * output + i] = (ac[i] + (coverage >> 1)) / coverage;
+ }
+ } else if (output >= 0) {
+ /* Leading has gone off the image and trailing isn't yet in it
+ * (small image) */
+ for (i = 0; i < bpp; i++)
+ dest[bpp * output + i] = (ac[i] + (coverage >> 1)) / coverage;
+ }
- if (kw > boundarys.x1 - boundarys.x0)
- kw = boundarys.x1 - boundarys.x0;
+ lead++;
+ output++;
+ trail++;
+ }
+}
- if (kh > boundarys.y1 - boundarys.y0)
- kh = boundarys.y1 - boundarys.y0;
+static gint
+compute_box_blur_width (double radius)
+{
+ double width;
+
+ width = radius * 3 * sqrt (2 * G_PI) / 4;
+ return (gint) (width + 0.5);
+}
+
+#define SQR(x) ((x) * (x))
+
+static void
+make_gaussian_convolution_matrix (gdouble radius, gdouble **out_matrix, gint *out_matrix_len)
+{
+ gdouble *matrix;
+ gdouble std_dev;
+ gdouble sum;
+ gint matrix_len;
+ gint i, j;
+
+ std_dev = radius + 1.0;
+ radius = std_dev * 2;
+
+ matrix_len = 2 * ceil (radius - 0.5) + 1;
+ if (matrix_len <= 0)
+ matrix_len = 1;
+
+ matrix = g_new (gdouble, matrix_len);
+
+ /* Fill the matrix by doing numerical integration approximation
+ * from -2*std_dev to 2*std_dev, sampling 50 points per pixel.
+ * We do the bottom half, mirror it to the top half, then compute the
+ * center point. Otherwise asymmetric quantization errors will occur.
+ * The formula to integrate is e^-(x^2/2s^2).
+ */
+
+ for (i = matrix_len / 2 + 1; i < matrix_len; i++)
+ {
+ gdouble base_x = i - (matrix_len / 2) - 0.5;
+
+ sum = 0;
+ for (j = 1; j <= 50; j++)
+ {
+ gdouble r = base_x + 0.02 * j;
+
+ if (r <= radius)
+ sum += exp (- SQR (r) / (2 * SQR (std_dev)));
+ }
+
+ matrix[i] = sum / 50;
+ }
+ /* mirror to the bottom half */
+ for (i = 0; i <= matrix_len / 2; i++)
+ matrix[i] = matrix[matrix_len - 1 - i];
+
+ /* find center val -- calculate an odd number of quanta to make it
+ * symmetric, even if the center point is weighted slightly higher
+ * than others.
+ */
+ sum = 0;
+ for (j = 0; j <= 50; j++)
+ sum += exp (- SQR (- 0.5 + 0.02 * j) / (2 * SQR (std_dev)));
+
+ matrix[matrix_len / 2] = sum / 51;
+
+ /* normalize the distribution by scaling the total sum to one */
+ sum = 0;
+ for (i = 0; i < matrix_len; i++)
+ sum += matrix[i];
- if (kw >= 1) {
- for (ch = 0; ch < 4; ch++) {
- switch (ch) {
- case 0:
- if (!op.Rused)
- continue;
- case 1:
- if (!op.Gused)
- continue;
- case 2:
- if (!op.Bused)
- continue;
- case 3:
- if (!op.Aused)
- continue;
+ for (i = 0; i < matrix_len; i++)
+ matrix[i] = matrix[i] / sum;
+
+ *out_matrix = matrix;
+ *out_matrix_len = matrix_len;
+}
+
+static void
+gaussian_blur_line (gdouble *matrix,
+ gint matrix_len,
+ guchar *src,
+ guchar *dest,
+ gint len,
+ gint bpp)
+{
+ guchar *src_p;
+ guchar *src_p1;
+ gint matrix_middle;
+ gint row;
+ gint i, j;
+
+ matrix_middle = matrix_len / 2;
+
+ /* picture smaller than the matrix? */
+ if (matrix_len > len) {
+ for (row = 0; row < len; row++) {
+ /* find the scale factor */
+ gdouble scale = 0;
+
+ for (j = 0; j < len; j++) {
+ /* if the index is in bounds, add it to the scale counter */
+ if (j + matrix_middle - row >= 0 &&
+ j + matrix_middle - row < matrix_len)
+ scale += matrix[j];
}
- for (y = boundarys.y0; y < boundarys.y1; y++) {
- sum = 0;
- for (x = boundarys.x0; x < boundarys.x0 + kw; x++) {
- sum += (intermediate[x % kw] = in_pixels[4 * x + y * rowstride + ch]);
- if (x - kw / 2 >= 0 && x - kw / 2 < boundarys.x1)
- output_pixels[4 * (x - kw / 2) + y * rowstride + ch] = sum / kw;
- }
- for (x = boundarys.x0 + kw; x < boundarys.x1; x++) {
- sum -= intermediate[x % kw];
- sum += (intermediate[x % kw] = in_pixels[4 * x + y * rowstride + ch]);
- output_pixels[4 * (x - kw / 2) + y * rowstride + ch] = sum / kw;
- }
- for (x = boundarys.x1; x < boundarys.x1 + kw; x++) {
- sum -= intermediate[x % kw];
+ src_p = src;
+
+ for (i = 0; i < bpp; i++) {
+ gdouble sum = 0;
+
+ src_p1 = src_p++;
+
+ for (j = 0; j < len; j++) {
+ if (j + matrix_middle - row >= 0 &&
+ j + matrix_middle - row < matrix_len)
+ sum += *src_p1 * matrix[j];
- if (x - kw / 2 >= 0 && x - kw / 2 < boundarys.x1)
- output_pixels[4 * (x - kw / 2) + y * rowstride + ch] = sum / kw;
+ src_p1 += bpp;
}
+
+ *dest++ = (guchar) (sum / scale + 0.5);
}
}
- in_pixels = output_pixels;
- }
+ } else {
+ /* left edge */
- if (kh >= 1) {
- for (ch = 0; ch < 4; ch++) {
- switch (ch) {
- case 0:
- if (!op.Rused)
- continue;
- case 1:
- if (!op.Gused)
- continue;
- case 2:
- if (!op.Bused)
- continue;
- case 3:
- if (!op.Aused)
- continue;
- }
+ for (row = 0; row < matrix_middle; row++) {
+ /* find scale factor */
+ gdouble scale = 0;
+ for (j = matrix_middle - row; j < matrix_len; j++)
+ scale += matrix[j];
- for (x = boundarys.x0; x < boundarys.x1; x++) {
- sum = 0;
+ src_p = src;
- for (y = boundarys.y0; y < boundarys.y0 + kh; y++) {
- sum += (intermediate[y % kh] = in_pixels[4 * x + y * rowstride + ch]);
+ for (i = 0; i < bpp; i++) {
+ gdouble sum = 0;
- if (y - kh / 2 >= 0 && y - kh / 2 < boundarys.y1)
- output_pixels[4 * x + (y - kh / 2) * rowstride + ch] = sum / kh;
+ src_p1 = src_p++;
+
+ for (j = matrix_middle - row; j < matrix_len; j++) {
+ sum += *src_p1 * matrix[j];
+ src_p1 += bpp;
}
- for (y = boundarys.y0 + kh; y < boundarys.y1; y++) {
- sum -= intermediate[y % kh];
- sum += (intermediate[y % kh] = in_pixels[4 * x + y * rowstride + ch]);
- output_pixels[4 * x + (y - kh / 2) * rowstride + ch] = sum / kh;
+
+ *dest++ = (guchar) (sum / scale + 0.5);
+ }
+ }
+
+ /* go through each pixel in each col */
+ for (; row < len - matrix_middle; row++) {
+ src_p = src + (row - matrix_middle) * bpp;
+
+ for (i = 0; i < bpp; i++) {
+ gdouble sum = 0;
+
+ src_p1 = src_p++;
+
+ for (j = 0; j < matrix_len; j++) {
+ sum += matrix[j] * *src_p1;
+ src_p1 += bpp;
}
- for (y = boundarys.y1; y < boundarys.y1 + kh; y++) {
- sum -= intermediate[y % kh];
- if (y - kh / 2 >= 0 && y - kh / 2 < boundarys.y1)
- output_pixels[4 * x + (y - kh / 2) * rowstride + ch] = sum / kh;
+ *dest++ = (guchar) (sum + 0.5);
+ }
+ }
+
+ /* for the edge condition, we only use available info and scale to one */
+ for (; row < len; row++) {
+ /* find scale factor */
+ gdouble scale = 0;
+
+ for (j = 0; j < len - row + matrix_middle; j++)
+ scale += matrix[j];
+
+ src_p = src + (row - matrix_middle) * bpp;
+
+ for (i = 0; i < bpp; i++) {
+ gdouble sum = 0;
+
+ src_p1 = src_p++;
+
+ for (j = 0; j < len - row + matrix_middle; j++) {
+ sum += *src_p1 * matrix[j];
+ src_p1 += bpp;
}
+
+ *dest++ = (guchar) (sum / scale + 0.5);
}
}
}
}
static void
-fast_blur (cairo_surface_t *in,
- cairo_surface_t *output,
- gfloat sx,
- gfloat sy,
- RsvgIRect boundarys,
- RsvgFilterPrimitiveOutput op)
+get_column (guchar *column_data,
+ guchar *src_data,
+ gint src_stride,
+ gint bpp,
+ gint height,
+ gint x)
{
- gint kx, ky;
- guchar *intermediate;
+ gint y;
+ gint c;
+
+ for (y = 0; y < height; y++) {
+ guchar *src = src_data + y * src_stride + x * bpp;
+
+ for (c = 0; c < bpp; c++)
+ column_data[c] = src[c];
+ column_data += bpp;
+ }
+}
+
+static void
+put_column (guchar *column_data, guchar *dest_data, gint dest_stride, gint bpp, gint height, gint x)
+{
+ gint y;
+ gint c;
+
+ for (y = 0; y < height; y++) {
+ guchar *dst = dest_data + y * dest_stride + x * bpp;
+
+ for (c = 0; c < bpp; c++)
+ dst[c] = column_data[c];
+
+ column_data += bpp;
+ }
+}
+
+static void
+gaussian_blur_surface (cairo_surface_t *in,
+ cairo_surface_t *out,
+ gdouble sx,
+ gdouble sy)
+{
+ gboolean use_box_blur;
+ gint width, height;
+ cairo_format_t in_format, out_format;
+ gint in_stride;
+ gint out_stride;
+ guchar *in_data, *out_data;
+ gint bpp;
+ gboolean out_has_data;
+
cairo_surface_flush (in);
- kx = floor (sx * 3 * sqrt (2 * M_PI) / 4 + 0.5);
- ky = floor (sy * 3 * sqrt (2 * M_PI) / 4 + 0.5);
+ width = cairo_image_surface_get_width (in);
+ height = cairo_image_surface_get_height (in);
+
+ g_assert (width == cairo_image_surface_get_width (out)
+ && height == cairo_image_surface_get_height (out));
+
+ in_format = cairo_image_surface_get_format (in);
+ out_format = cairo_image_surface_get_format (out);
+ g_assert (in_format == out_format);
+ g_assert (in_format == CAIRO_FORMAT_ARGB32
+ || in_format == CAIRO_FORMAT_A8);
+
+ if (in_format == CAIRO_FORMAT_ARGB32)
+ bpp = 4;
+ else if (in_format == CAIRO_FORMAT_A8)
+ bpp = 1;
+ else {
+ g_assert_not_reached ();
+ return;
+ }
+
+ in_stride = cairo_image_surface_get_stride (in);
+ out_stride = cairo_image_surface_get_stride (out);
+
+ in_data = cairo_image_surface_get_data (in);
+ out_data = cairo_image_surface_get_data (out);
+
+ if (sx < 0.0)
+ sx = 0.0;
- if (kx < 1 && ky < 1)
+ if (sy < 0.0)
+ sy = 0.0;
+
+ /* For small radiuses, use a true gaussian kernel; otherwise use three box blurs with
+ * clever offsets.
+ */
+ if (sx < 10.0 && sy < 10.0)
+ use_box_blur = FALSE;
+ else
+ use_box_blur = TRUE;
+
+ /* Bail out by just copying? */
+ if ((sx == 0.0 && sy == 0.0)
+ || sx > 1000 || sy > 1000) {
+ cairo_t *cr;
+
+ cr = cairo_create (out);
+ cairo_set_source_surface (cr, in, 0, 0);
+ cairo_paint (cr);
return;
+ }
+
+ if (sx != 0.0) {
+ gint box_width;
+ gdouble *gaussian_matrix;
+ gint gaussian_matrix_len;
+ int y;
+ guchar *row_buffer;
+ guchar *row1, *row2;
+
+ if (use_box_blur) {
+ box_width = compute_box_blur_width (sx);
+
+ /* twice the size so we can have "two" scratch rows */
+ row_buffer = g_new (guchar, width * bpp * 2);
+ row1 = row_buffer;
+ row2 = row_buffer + width * bpp;
+ } else
+ make_gaussian_convolution_matrix (sx, &gaussian_matrix, &gaussian_matrix_len);
+
+ for (y = 0; y < height; y++) {
+ guchar *in_row, *out_row;
+
+ in_row = in_data + in_stride * y;
+ out_row = out_data + out_stride * y;
+
+ if (use_box_blur) {
+ if (box_width % 2 != 0) {
+ /* Odd-width box blur: repeat 3 times, centered on output pixel */
+
+ box_blur_line (box_width, 0, in_row, row1, width, bpp);
+ box_blur_line (box_width, 0, row1, row2, width, bpp);
+ box_blur_line (box_width, 0, row2, out_row, width, bpp);
+ } else {
+ /* Even-width box blur:
+ * This method is suggested by the specification for SVG.
+ * One pass with width n, centered between output and right pixel
+ * One pass with width n, centered between output and left pixel
+ * One pass with width n+1, centered on output pixel
+ */
+ box_blur_line (box_width, -1, in_row, row1, width, bpp);
+ box_blur_line (box_width, 1, row1, row2, width, bpp);
+ box_blur_line (box_width + 1, 0, row2, out_row, width, bpp);
+ }
+ } else
+ gaussian_blur_line (gaussian_matrix, gaussian_matrix_len, in_row, out_row, width, bpp);
+ }
- intermediate = g_new (guchar, MAX (kx, ky));
+ if (!use_box_blur)
+ g_free (gaussian_matrix);
- box_blur (in, output, intermediate, kx, ky, boundarys, op);
- box_blur (output, output, intermediate, kx, ky, boundarys, op);
- box_blur (output, output, intermediate, kx, ky, boundarys, op);
+ out_has_data = TRUE;
+ } else
+ out_has_data = FALSE;
+
+ if (sy != 0.0) {
+ gint box_height;
+ gdouble *gaussian_matrix;
+ gint gaussian_matrix_len;
+ guchar *col_buffer;
+ guchar *col1, *col2;
+ int x;
+
+ /* twice the size so we can have the source pixels and the blurred pixels */
+ col_buffer = g_new (guchar, height * bpp * 2);
+ col1 = col_buffer;
+ col2 = col_buffer + height * bpp;
+
+ if (use_box_blur) {
+ box_height = compute_box_blur_width (sy);
+ } else
+ make_gaussian_convolution_matrix (sy, &gaussian_matrix, &gaussian_matrix_len);
+
+ for (x = 0; x < width; x++) {
+ if (out_has_data)
+ get_column (col1, out_data, out_stride, bpp, height, x);
+ else
+ get_column (col1, in_data, in_stride, bpp, height, x);
+
+ if (use_box_blur) {
+ if (box_height % 2 != 0) {
+ /* Odd-width box blur */
+ box_blur_line (box_height, 0, col1, col2, height, bpp);
+ box_blur_line (box_height, 0, col2, col1, height, bpp);
+ box_blur_line (box_height, 0, col1, col2, height, bpp);
+ } else {
+ /* Even-width box blur */
+ box_blur_line (box_height, -1, col1, col2, height, bpp);
+ box_blur_line (box_height, 1, col2, col1, height, bpp);
+ box_blur_line (box_height + 1, 0, col1, col2, height, bpp);
+ }
+ } else
+ gaussian_blur_line (gaussian_matrix, gaussian_matrix_len, col1, col2, height, bpp);
+
+ put_column (col2, out_data, out_stride, bpp, height, x);
+ }
- g_free (intermediate);
+ g_free (col_buffer);
+ }
- cairo_surface_mark_dirty (output);
+ cairo_surface_mark_dirty (out);
}
static void
rsvg_filter_primitive_gaussian_blur_render (RsvgFilterPrimitive * self, RsvgFilterContext * ctx)
{
RsvgFilterPrimitiveGaussianBlur *upself;
+ int width, height;
cairo_surface_t *output, *in;
RsvgIRect boundarys;
gfloat sdx, sdy;
RsvgFilterPrimitiveOutput op;
+ cairo_t *cr;
upself = (RsvgFilterPrimitiveGaussianBlur *) self;
boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
@@ -1482,8 +1873,11 @@
op = rsvg_filter_get_result (self->in, ctx);
in = op.surface;
- output = _rsvg_image_surface_new (cairo_image_surface_get_width (in),
- cairo_image_surface_get_height (in));
+ width = cairo_image_surface_get_width (in);
+ height = cairo_image_surface_get_height (in);
+
+ output = _rsvg_image_surface_new (width, height);
+
if (output == NULL) {
cairo_surface_destroy (in);
return;
@@ -1493,7 +1887,22 @@
sdx = upself->sdx * ctx->paffine.xx;
sdy = upself->sdy * ctx->paffine.yy;
- fast_blur (in, output, sdx, sdy, boundarys, op);
+ gaussian_blur_surface (in, output, sdx, sdy);
+
+ /* Hard-clip to the filter area */
+ if (!(boundarys.x0 == 0
+ && boundarys.y0 == 0
+ && boundarys.x1 == width
+ && boundarys.y1 == height)) {
+ cr = cairo_create (output);
+ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
+ cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
+ cairo_rectangle (cr, 0, 0, width, height);
+ cairo_rectangle (cr,
+ boundarys.x0, boundarys.y0,
+ boundarys.x1 - boundarys.x0, boundarys.y1 - boundarys.y0);
+ cairo_fill (cr);
+ }
op.surface = output;
op.bounds = boundarys;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/librsvg-2.40.8/rsvg-path.c new/librsvg-2.40.9/rsvg-path.c
--- old/librsvg-2.40.8/rsvg-path.c 2015-02-26 22:38:38.000000000 +0100
+++ new/librsvg-2.40.9/rsvg-path.c 2015-03-13 20:36:05.000000000 +0100
@@ -429,6 +429,7 @@
if (ctx->param == 1) {
rsvg_path_builder_line_to (&ctx->builder, ctx->params[0], ctx->cp.point.y);
ctx->cp.point.x = ctx->rp.point.x = ctx->params[0];
+ ctx->rp.point.y = ctx->cp.point.y;
ctx->param = 0;
}
break;
@@ -436,6 +437,7 @@
/* vertical lineto */
if (ctx->param == 1) {
rsvg_path_builder_line_to (&ctx->builder, ctx->cp.point.x, ctx->params[0]);
+ ctx->rp.point.x = ctx->cp.point.x;
ctx->cp.point.y = ctx->rp.point.y = ctx->params[0];
ctx->param = 0;
}