...
 
Commits (232)
......@@ -27,7 +27,7 @@ stages:
- cross_distro
.test_template: &test
before_script:
script:
# CCache Config
- mkdir -p ccache
- mkdir -p .cargo_cache
......@@ -38,16 +38,19 @@ stages:
# Only stuff inside the repo directory can be cached
# Override the CARGO_HOME variable to force it location
- export CARGO_HOME="${PWD}/.cargo_cache"
script:
- rustc --version && cargo --version
- ./autogen.sh --enable-gtk-doc --enable-vala
- mkdir -p _build
- cd _build
- ../autogen.sh --enable-gtk-doc --enable-vala
- make
- make check
artifacts:
when: on_failure
paths:
- tests/*.log
- tests/output/
- _build/tests/*.log
- _build/tests/output/
cache:
# JOB_NAME - Each job will have it's own cache
......@@ -55,7 +58,7 @@ stages:
# ^ Keep diffrerent caches for each branch
key: "$CI_JOB_NAME-$CI_COMMIT_REF_SLUG"
paths:
- target/
- _build/target/
- .cargo_cache/
- ccache/
......@@ -81,8 +84,10 @@ stages:
only:
# When branching a stable branch,
# update the following line from master to branch's name.
- librsvg-2.44@GNOME/librsvg
- librsvg-2.42@GNOME/librsvg
- master@GNOME/librsvg
- librsvg-2.44
- librsvg-2.42
- schedules
- tags
......@@ -119,7 +124,7 @@ rustfmt:
- rustc --version && cargo --version
- cargo fmt --version
- cargo fmt --all -- --check
when: manual
# Configure and run clippy on nightly
# Only fails on errors atm.
......@@ -139,7 +144,9 @@ tarball:
LIBRSVG_DEBUG: "yes"
script:
- rustc --version && cargo --version
- ./autogen.sh --enable-gtk-doc --enable-vala
- mkdir -p _build
- cd _build
- ../autogen.sh --enable-gtk-doc --enable-vala
- make distcheck DESTDIR=/tmp/distcheck
<<: *stage_2
......@@ -164,6 +171,8 @@ debian:testing:
image: $AMD64_DEBIAN_TESTING
variables:
LIBRSVG_DEBUG: "yes"
before_script:
- export PATH=$PATH:/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0
<<: *distro_test
<<: *stage_2
......@@ -171,6 +180,8 @@ debian_i386:testing:
image: $I386_DEBIAN_TESTING
variables:
LIBRSVG_DEBUG: "yes"
before_script:
- export PATH=$PATH:/usr/lib/i386-linux-gnu/gdk-pixbuf-2.0
<<: *distro_test
<<: *stage_2
......@@ -189,27 +200,29 @@ debian:testing_release_i386:
image: $I386_DEBIAN_TESTING
variables:
LIBRSVG_DEBUG: "no"
before_script:
- export PATH=$PATH:/usr/lib/i386-linux-gnu/gdk-pixbuf-2.0
<<: *distro_test
<<: *stage_3
# STAGE 3 RUSTC TESTS
#######################################################################
rustc 1.26 1:
.rustc 1.26 1:
image: $RUSTC_1_26
variables:
LIBRSVG_DEBUG: "yes"
<<: *rustc
<<: *stage_3
rustc 1.27 2:
.rustc 1.27 2:
image: $RUSTC_1_27
variables:
LIBRSVG_DEBUG: "yes"
<<: *rustc
<<: *stage_3
rustc 1.28 3:
.rustc 1.28 3:
image: $RUSTC_1_28
variables:
LIBRSVG_DEBUG: "yes"
......
......@@ -19,6 +19,7 @@ explains librsvg's peculiarities.
* [Basic compilation instructions](#basic-compilation-instructions)
* [Verbosity](#verbosity)
* [Debug or release builds](#debug-or-release-builds)
* [Selecting a Rust toolchain](#selecting-a-rust-toolchain)
* [Cross-compilation](#cross-compilation)
* [Building with no network access](#building-with-no-network-access)
* [Running `make distcheck`](#running-make-distcheck)
......@@ -31,12 +32,12 @@ minimum version is listed here; you may use a newer version instead.
**Compilers:**
* a C compiler and `make` tool; we recommend GNU `make`.
* rust 1.26 or later
* rust 1.27 or later
* cargo
**Mandatory dependencies:**
* Cairo 1.15.4 with PNG support
* Cairo 1.15.12 with PNG support
* Freetype2 2.8.0
* Libcroco 0.6.1
* Gdk-pixbuf 2.20.0
......@@ -55,9 +56,9 @@ several systems.
### Debian based systems
As of 2018/Feb/22, librsvg cannot be built in `debian stable` and
`ubuntu 16.04`, as they have packages that are too old.
`ubuntu 18.04`, as they have packages that are too old.
**Build dependencies on Debian Testing or Ubuntu 18.04+:**
**Build dependencies on Debian Testing or Ubuntu 18.10:**
```sh
apt-get install -y gcc make rustc cargo \
......@@ -67,6 +68,12 @@ gtk-doc-tools git libgtk-3-dev \
libxml2-dev libcroco3-dev libcairo2-dev libpango1.0-dev
```
Additionally, as of September 2018 you need to add `gdk-pixbuf` utilities to your path, see #331 for more.
```sh
PATH="$PATH:/usr/lib/x86_64-linux-gnu/gdk-pixbuf-2.0"
```
### Fedora based systems
```sh
......@@ -185,6 +192,24 @@ build the Rust sub-library in debug mode.
In case both the environment variable and the command-line option are
specified, the command-line option overrides the env var.
# Selecting a Rust toolchain
By default, the configure/make steps will use the `cargo` binary that
is found in your `$PATH`. If you have a system installation of Rust
and one in your home directory, or for special build systems, you may
need to override the locations of `cargo` and/or `rustc`. In this
case, you can set any of these environment variables before running
`configure` or `autogen.sh`:
* `RUSTC` - path to the `rustc` compiler
* `CARGO` - path to `cargo`
Note that `$RUSTC` only gets used in the `configure` script to ensure
that there is a Rust compiler installed with an appropriate version.
The actual compilation process just uses `$CARGO`, and assumes that
that `cargo` binary will use the same Rust compiler as the other
variable.
# Cross-compilation
If you need to cross-compile librsvg, specify the `--host=TRIPLE` to
......
......@@ -161,19 +161,14 @@ of CI pipelines will fail:
indentation, but don't want it to make changes on its own:
`cargo fmt --all -- --check`
***Installing rustfmt*** As of 2018/Jun, our continuous integration
pipeline assumes the Rust nightly version of rustfmt. You can install
it with
***Installing rustfmt*** As of 2018/Sep, our continuous integration
pipeline assumes the version of rustfmt that is distributed through the
nightly channel of [rustup](rustup.rs). You can install it with
```
cargo +nightly install --force rustfmt-nightly
rustup component add rustfmt-preview --toolchain=nightly
```
Note that rustfmt changes frequently. If the CI pipeline fails on the
`Lint` stage because your code is formatted differently, try updating
your rustfmt. Hopefully this will stabilize once rustfmt reaches
version 1.0.
### Test suite
Please make sure that the test suite passes with the changes in your
......
This diff is collapsed.
......@@ -14,14 +14,7 @@ headers = \
librsvg/rsvg.h \
librsvg/rsvg-cairo.h
enum_sources = \
librsvg/librsvg-enum-types.h \
librsvg/librsvg-enum-types.c
BUILT_SOURCES += $(enum_sources)
librsvg_@RSVG_API_MAJOR_VERSION@_la_SOURCES = \
librsvg/librsvg-enum-types.c \
librsvg/librsvg-enum-types.h \
librsvg/librsvg-features.c \
librsvg/librsvg-features.h \
librsvg/rsvg-attributes.h \
......@@ -37,8 +30,6 @@ librsvg_@RSVG_API_MAJOR_VERSION@_la_SOURCES = \
librsvg/rsvg-private.h \
librsvg/rsvg-size-callback.c \
librsvg/rsvg-size-callback.h \
librsvg/rsvg-styles.c \
librsvg/rsvg-styles.h \
librsvg/rsvg.h \
$(NULL)
......@@ -49,10 +40,13 @@ RUST_SRC = \
rsvg_internals/src/aspect_ratio.rs \
rsvg_internals/src/attributes.rs \
rsvg_internals/src/bbox.rs \
rsvg_internals/src/c_api.rs \
rsvg_internals/src/clip_path.rs \
rsvg_internals/src/color.rs \
rsvg_internals/src/cond.rs \
rsvg_internals/src/coord_units.rs \
rsvg_internals/src/croco.rs \
rsvg_internals/src/css.rs \
rsvg_internals/src/defs.rs \
rsvg_internals/src/drawing_ctx.rs \
rsvg_internals/src/filters/bounds.rs \
......@@ -147,16 +141,23 @@ CARGO_TARGET_DIR=@abs_top_builddir@/target
check-local:
cd $(srcdir) && \
CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) cargo test $(CARGO_VERBOSE) $(CARGO_TARGET_ARGS) $(CARGO_RELEASE_ARGS)
CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) $(CARGO) --locked test $(CARGO_VERBOSE) $(CARGO_TARGET_ARGS) $(CARGO_RELEASE_ARGS)
clean-local:
cd $(top_srcdir) && \
CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) cargo clean
CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) $(CARGO) clean
distcheck-hook:
if test -z "${DESTDIR}"; \
then \
echo "Please specify DESTDIR=/tmp/foo so distcheck will work"; \
exit 1; \
fi
dist-hook:
(cd $(distdir) && \
cargo vendor -q && \
mkdir .cargo && \
(cd $(distdir) && \
$(CARGO) vendor -q && \
mkdir .cargo && \
cp cargo-vendor-config .cargo/config)
$(RUST_LIB): $(RUST_SRC)
......@@ -164,7 +165,7 @@ $(RUST_LIB): $(RUST_SRC)
PKG_CONFIG_ALLOW_CROSS=1 \
PKG_CONFIG='$(PKG_CONFIG)' \
CARGO_TARGET_DIR=$(CARGO_TARGET_DIR) \
cargo build $(CARGO_VERBOSE) $(CARGO_TARGET_ARGS) $(CARGO_RELEASE_ARGS)
$(CARGO) --locked build $(CARGO_VERBOSE) $(CARGO_TARGET_ARGS) $(CARGO_RELEASE_ARGS)
librsvg_@RSVG_API_MAJOR_VERSION@_la_CPPFLAGS = \
-I$(top_srcdir) \
......@@ -190,16 +191,15 @@ librsvg_@RSVG_API_MAJOR_VERSION@_la_LDFLAGS = \
$(AM_LDFLAGS)
librsvg_@RSVG_API_MAJOR_VERSION@_la_LIBADD = \
$(RUST_LIB) \
$(LIBRSVG_LIBS) \
$(LIBM) \
$(RUST_LIB) \
$(DLOPEN_LIBS)
librsvgincdir = $(includedir)/librsvg-$(RSVG_API_VERSION)/librsvg
librsvginc_HEADERS = \
$(headers) \
librsvg/librsvg-features.h \
librsvg/librsvg-enum-types.h
librsvg/librsvg-features.h
dist_man_MANS = rsvg-convert.1
......@@ -279,45 +279,12 @@ EXTRA_DIST = \
tap-driver.sh \
tap-test
CLEANFILES = \
$(enum_sources) \
s-enum-types-h s-enum-types-c
## Put `exec' in the name because this should be installed by
## `install-exec', not `install-data'.
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = librsvg-$(RSVG_API_VERSION).pc
librsvg/librsvg-enum-types.h: librsvg/s-enum-types-h
@true
librsvg/s-enum-types-h: $(headers) Makefile
$(AM_V_GEN) ( cd $(srcdir) && $(GLIB_MKENUMS) \
--fhead "#if !defined (__RSVG_RSVG_H_INSIDE__) && !defined (RSVG_COMPILATION)\n#warning \"Including <librsvg/librsvg-enum-types.h> directly is deprecated.\"\n#endif\n\n#ifndef __LIBRSVG_ENUM_TYPES_H__\n#define __LIBRSVG_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \
--fprod "/* enumerations from \"@filename@\" */\n" \
--vhead "GType @enum_name@_get_type (void);\n#define RSVG_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \
--ftail "G_END_DECLS\n\n#endif /* __LIBRSVG_ENUM_TYPES_H__ */" \
$(headers) ) > librsvg/tmp-librsvg-enum-types.h \
&& (cmp -s librsvg/tmp-librsvg-enum-types.h librsvg/librsvg-enum-types.h || cp librsvg/tmp-librsvg-enum-types.h librsvg/librsvg-enum-types.h ) \
&& rm -f librsvg/tmp-librsvg-enum-types.h \
&& echo timestamp > $(@F)
librsvg/librsvg-enum-types.c: librsvg/s-enum-types-c librsvg/librsvg-enum-types.h
@true
librsvg/s-enum-types-c: $(headers) Makefile
$(AM_V_GEN) ( cd $(srcdir) && $(GLIB_MKENUMS) \
--fhead "#include \"librsvg/rsvg.h\"" \
--fprod "\n/* enumerations from \"@filename@\" */" \
--vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \
--vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \
--vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \
$(headers) ) > librsvg/tmp-librsvg-enum-types.c \
&& (cmp -s librsvg/tmp-librsvg-enum-types.c librsvg/librsvg-enum-types.c || cp librsvg/tmp-librsvg-enum-types.c librsvg/librsvg-enum-types.c ) \
&& rm -f librsvg/tmp-librsvg-enum-types.c \
&& echo timestamp > $(@F)
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
if HAVE_INTROSPECTION
......@@ -356,7 +323,7 @@ nodist_gir_DATA = $(INTROSPECTION_GIRS)
typelibsdir = $(libdir)/girepository-1.0
nodist_typelibs_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
CLEANFILES += $(nodist_gir_DATA) $(nodist_typelibs_DATA)
CLEANFILES = $(nodist_gir_DATA) $(nodist_typelibs_DATA)
if ENABLE_VAPIGEN
include $(VAPIGEN_MAKEFILE)
......@@ -367,7 +334,7 @@ VAPIGEN_VAPIS = librsvg-$(RSVG_API_VERSION).vapi
librsvg_@RSVG_API_VERSION_U@_vapi_DEPS = gio-2.0 cairo
librsvg_@RSVG_API_VERSION_U@_vapi_METADATADIRS = $(srcdir)
librsvg_@RSVG_API_VERSION_U@_vapi_FILES = Rsvg-$(RSVG_API_VERSION).gir Rsvg-$(RSVG_API_VERSION)-custom.vala
librsvg_@RSVG_API_VERSION_U@_vapi_FILES = Rsvg-$(RSVG_API_VERSION).gir $(srcdir)/Rsvg-$(RSVG_API_VERSION)-custom.vala
vapidir = $(datadir)/vala/vapi
vapi_DATA = $(VAPIGEN_VAPIS)
......@@ -423,14 +390,3 @@ endif # HAVE_INTROSPECTION
$(MSVCPROJ_GENERATED): $(top_builddir)/win32/vs12/rsvg.vs12.headers
EXTRA_DIST += $(MSVCPROJ_GENERATED)
# ChangeLog generation
ChangeLog:
$(AM_V_GEN) if test -d $(top_srcdir)/.git; then \
GIT_DIR="$(top_srcdir)/.git" git log --stat > $@; \
fi
dist: ChangeLog
.PHONY: ChangeLog
Version 2.44.14
- Fix #425 - Don't fail parsing if the system's locale is broken (Paolo Borelli).
- Fix #438, #443 - Don't create intermediate raster surfaces unless
absolutely needed. This was causing blurred output for SVGs from
Inkscape and Illustrator, since they include an "enable-background"
property even when there are no filters in use. Thanks to Julian
Sparber, Jordan Petridis, Zeeshan Ali for doing a huge "git bisect"
to find the cause of this bug.
- Fix #443 - Fix blurry output when enable-background is used without filters.
- Fix #455 - Fix rounding error on i386 (Olivier Tilloy).
- Check for Cairo errors when constructing paths.
Version 2.44.13
- Updated compilation docs for Debian (Jordan Petridis)
- Fix #415 - register RsvgHandleFlags and the RsvgError enum values in
a thread-safe fashion (Sebastian Dröge).
Version 2.44.12
- At build time, you can now pass $CARGO and $RUSTC environment
variables if you need to override the default Rust toolchain.
Please see COMPILING.md for details. (Tobias Kortkamp)
- Fix #405 - In the gdk-pixbuf loader, don't crash the write()
function doesn't receive a GError.
- Fix #398 - Detect circular references in gradients.
Version 2.44.11
- Fix crash when a linear RGB filter is followed by an SRGB filter
(Ivan Molodetskikh).
- Fix #393 - Stack overflow when freeing thousands of sibling elements.
- Fix #395 - feMorphology was crashing with a negative scaling
transformation.
- Fix positioning of adjacent <tspan> elements.
Version 2.44.10
- Fix #385 - Don't crash if there is no rsvg_handle_write() before
rsvg_handle_close().
- Fix #391 - Avoid undefined behavior when casting opaque pointers
(Jordan Petridis).
- Added g_warning()s to ensure the API is called in the correct
sequence.
Version 2.44.9
- Fix #371 - rsvg-convert was positioning extracted elements
incorrectly when using the -w/-h options together with --export-id.
- Fix #372 - Mis-rendering in small arc segments.
- Fix #373 - Rendering of gradients for horizontal/vertical stroked
lines with gradientUnits="userSpaceOnUse".
- Fix a couple of memory leaks in the error paths of the GdkPixbuf
loader (Benedikt Heine).
Version 2.44.8
- Librsvg now requires Rust 1.27; this should have happened since
2.44.0. Apologies if the 2.44.x series didn't catch this build
failure early for you.
- Librsvg now requires Cairo 1.15.12.
- Fix #363 - Don't drop spaces around <tspan> elements.
- Fix #365 - rsvg-convert now uses pixel units for SVG output, instead
of points. This requires cairo 1.15.12 (Antonio Ospite).
- Fix #358, #366 - tweaks to have the test suite pass on i386 and
non-x86_64 platforms (Simon McVittie, Federico Mena).
- Fix #368 - With RSVG_LOG=1, librsvg will now report when SVGs have
references to nonexistent elements, to aid debugging (for example,
in an xlink:href attribute).
- Allow reference tests with a small difference to pass without
breaking the build (Simon McVittie).
Version 2.44.7
- Fix #256 - Correctly match the systemLanguage attribute with the
user's locale.
- Fix #320 - Parse xml:lang correctly.
- Fix #334 - Don't modify the caller's cairo_t state during rendering.
- Fix #349 - Don't panic if we get a "data:" URI with empty data.
- Fix #352 - Don't panic on getting a very large "order" for
feConvolveMatrix (Ivan Molodetskikh).
Version 2.44.6
- Fix 32-bit builds (Jordan Petridis).
Version 2.44.5
- Fix #343 - Handle child being in error in feComponentTransfer.
- Fix #346 - Handle filter primitives producing errors.
- Fix #347 - Regression in computation of text element extents.
- Fix #348 - Fix incorrect font sizing.
- Fix #349 - Don't panic when loading an external image that is bigger
than Cairo's limits.
- Fix - rsvg_handle_get_dimensions_sub() no longer panics if passed a
nonexistent fragment identifier.
- CSS processing code is now in Rust, although it still calls libcroco
to do the parsing.
Version 2.44.4
- Fix #341 - Don't infinite-loop with cyclic pattern references.
- Fix #342 - Don't crash if a <use> node references one of its ancestors.
- Fix #344 - Don't panic when a viewBox has overflowing numbers.
- Fix #345 - Fix panics due to bad path parsing and overflows in
surface size.
- Cleanups and refactoring (Paolo Borelli, Linus Unnebäck, Federico Mena).
Version 2.44.3
- Fix building when srcdir != builddir (Mathieu Bridon).
- Fix #339 - Panic in filters with primitiveUnits="objectBoundingBox"
on zero-sized elements (Ivan Molodetskikh).
- Fix #335 - Don't panic if the toplevel node is not <svg>.
- Fixes from fuzz testing (Ivan Molodetskikh): don't panic when the
feConvolveMatrix kernel is not set; fix upper bounds in filter pixel
getters.
- Fix #337 - Don't panic with "em" or "ex" units in the font-size property.
- Fix #338 - Don't panic when an image element doesn't have
width/height attributes.
- Fix #340 - Don't panic when a marker has a zero-sized viewBox attribute.
- Special thanks to Ivan Molodetskikh for doing a fuzz-testing run for
this round.
- Updates to the CI infrastructure and the build documentation (Jordan
Petridis).
Version 2.44.2
- A *double brown paper bag* release! Super strong, this one!
- Fix #325 - Don't leak all the elements at the toplevel.
- Fix #328 - Make masking work on big-endian. Thanks to
Simon McVittie for quick testing of this on s390x.
- Fix library ordering so -Wl,--as-needed works (Simon McVittie).
Version 2.44.1
- This is a brown paper bag release! Apologies for the bugs:
- Fix #324 - Don't panic if trying to render a non-empty SVG with no
elements (Paolo Borelli).
- Fix #325 - All the elements were being leaked at the toplevel.
- Fix #326 - Fix COMPILING.md - librsvg 2.44 does not build on Ubuntu
18.04 because it has a rust version that is too old.
Version 2.44.0
- Librsvg now has minimal logging for debugging by setting the
RSVG_LOG environment variable. See CONTRIBUTING.md for details.
......
m4_define([rsvg_major_version],[2])
m4_define([rsvg_minor_version],[44])
m4_define([rsvg_micro_version],[0])
m4_define([rsvg_micro_version],[14])
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)
......@@ -38,8 +38,7 @@ AC_SUBST([LIBRSVG_MICRO_VERSION],[rsvg_micro_version])
dnl ===========================================================================
dnl Please update COMPILING.md with version numbers if these change
CAIRO_REQUIRED=1.15.4
CAIRO_REQUIRED=1.15.12
CROCO_REQUIRED=0.6.1
dnl This corresponds to Freetype2 2.8
FREETYPE2_REQUIRED=20.0.14
......@@ -74,11 +73,11 @@ AC_SUBST(DLOPEN_LIBS)
dnl ===========================================================================
AC_CHECK_PROG(CARGO, [cargo], [yes], [no])
AC_CHECK_PROGS(CARGO, [cargo], [no])
AS_IF(test x$CARGO = xno,
AC_MSG_ERROR([cargo is required. Please install the Rust toolchain from https://www.rust-lang.org/])
)
AC_CHECK_PROG(RUSTC, [rustc], [yes], [no])
AC_CHECK_PROGS(RUSTC, [rustc], [no])
AS_IF(test x$RUSTC = xno,
AC_MSG_ERROR([rustc is required. Please install the Rust toolchain from https://www.rust-lang.org/])
)
......@@ -86,9 +85,9 @@ AS_IF(test x$RUSTC = xno,
dnl Minimum version of rustc that we support
dnl If you change this, please update COMPILING.md
MINIMUM_RUST_MAJOR=1
MINIMUM_RUST_MINOR=26
MINIMUM_RUST_MINOR=27
rust_version=`rustc --version`
rust_version=`$RUSTC --version`
version=`echo "$rust_version" | sed -e 's/^rustc //g'`
major=`echo "$version" | cut -d. -f1`
minor=`echo "$version" | cut -d. -f2`
......
......@@ -58,8 +58,7 @@ HFILE_GLOB = \
$(top_builddir)/librsvg/*.h
CFILE_GLOB = \
$(top_srcdir)/librsvg/*.c \
$(top_builddir)/librsvg/*.c
$(top_srcdir)/librsvg/*.c
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
......
......@@ -131,6 +131,7 @@ gdk_pixbuf__svg_image_load_increment (gpointer data,
}
if (!rsvg_handle_write (context->handle, buf, size, error)) {
g_clear_error(error);
rsvg_propagate_error (error, _("Error writing"), ERROR_WRITING);
return FALSE;
}
......@@ -153,8 +154,11 @@ gdk_pixbuf__svg_image_stop_load (gpointer data, GError **error)
return FALSE;
}
if (!rsvg_handle_close (context->handle, error))
if (!rsvg_handle_close (context->handle, error)) {
g_object_unref (context->handle);
g_free (context);
return FALSE;
}
pixbuf = rsvg_handle_get_pixbuf (context->handle);
......
......@@ -157,8 +157,4 @@ typedef enum {
RSVG_ATTRIBUTE_Z,
} RsvgAttribute;
/* Implemented in rust/src/attributes.rs */
G_GNUC_INTERNAL
gboolean rsvg_attribute_from_name (const char *name, RsvgAttribute *out_attr);
#endif /* RSVG_ATTRIBUTES_H */
......@@ -27,6 +27,7 @@
#include "config.h"
#include "rsvg-private.h"
#include "rsvg-css.h"
/*
* This is configurable at runtime
......@@ -149,3 +150,11 @@ rsvg_return_if_fail_warning (const char *pretty_function, const char *expression
g_set_error (error, RSVG_ERROR, 0, _("%s: assertion `%s' failed"), pretty_function, expression);
}
/* This is defined like this so that we can export the Rust function... just for
* the benefit of rsvg-convert.c
*/
RsvgCssColorSpec
rsvg_css_parse_color_ (const char *str)
{
return rsvg_css_parse_color (str);
}
......@@ -58,12 +58,8 @@ RsvgCssColorSpec rsvg_css_parse_color_ (const char *str);
G_GNUC_INTERNAL
RsvgCssColorSpec rsvg_css_parse_color (const char *str);
/* Implemented in rust/src/parsers.rs */
G_GNUC_INTERNAL
gboolean rsvg_css_parse_number_optional_number (const char *str, double *out_x, double *out_y);
#endif /* RSVG_COMPILATION */
G_END_DECLS
#endif
#endif
......@@ -128,6 +128,10 @@
#include "rsvg-load.h"
#include "rsvg-private.h"
/* Implemented in rsvg_internals/src/c_api.rs */
extern GType rsvg_rust_error_get_type (void);
extern GType rsvg_rust_handle_flags_get_type (void);
enum {
PROP_0,
PROP_FLAGS,
......@@ -160,10 +164,7 @@ rsvg_handle_init (RsvgHandle * self)
self->priv->dpi_x = rsvg_internal_dpi_x;
self->priv->dpi_y = rsvg_internal_dpi_y;
self->priv->css_props = g_hash_table_new_full (g_str_hash,
g_str_equal,
g_free,
(GDestroyNotify) g_hash_table_destroy);
self->priv->css_styles = rsvg_css_styles_new ();
self->priv->tree = NULL;
......@@ -191,7 +192,7 @@ rsvg_handle_dispose (GObject *instance)
g_clear_pointer (&self->priv->load, rsvg_load_free);
g_clear_pointer (&self->priv->defs, rsvg_defs_free);
g_clear_pointer (&self->priv->css_props, g_hash_table_destroy);
g_clear_pointer (&self->priv->css_styles, rsvg_css_styles_free);
g_clear_pointer (&self->priv->tree, rsvg_tree_free);
g_clear_pointer (&self->priv->base_uri, g_free);
g_clear_object (&self->priv->base_gfile);
......@@ -654,7 +655,9 @@ rsvg_handle_write (RsvgHandle *handle, const guchar *buf, gsize count, GError **
{
RsvgHandlePrivate *priv;
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
rsvg_return_val_if_fail (handle, FALSE, error);
priv = handle->priv;
rsvg_return_val_if_fail (priv->hstate == RSVG_HANDLE_STATE_START
......@@ -673,19 +676,49 @@ rsvg_handle_write (RsvgHandle *handle, const guchar *buf, gsize count, GError **
}
static gboolean
finish_load (RsvgHandle *handle, gboolean was_successful)
tree_is_valid (RsvgTree *tree, GError **error)
{
if (!tree) {
g_set_error (error, RSVG_ERROR, RSVG_ERROR_FAILED, _("SVG has no elements"));
return FALSE;
}
if (!rsvg_tree_root_is_svg (tree)) {
g_set_error (error, RSVG_ERROR, RSVG_ERROR_FAILED, _("root element is not <svg>"));
return FALSE;
}
return TRUE;
}
static gboolean
finish_load (RsvgHandle *handle, gboolean was_successful, GError **error)
{
RsvgTree *tree = NULL;
g_assert (handle->priv->load != NULL);
g_assert (handle->priv->tree == NULL);
if (was_successful) {
g_assert (error == NULL || *error == NULL);
tree = rsvg_load_steal_tree (handle->priv->load);
was_successful = tree_is_valid (tree, error);
if (!was_successful) {
rsvg_tree_free (tree);
tree = NULL;
}
}
if (was_successful) {
g_assert (tree != NULL);
handle->priv->hstate = RSVG_HANDLE_STATE_CLOSED_OK;
handle->priv->tree = rsvg_load_steal_tree (handle->priv->load);
} else {
handle->priv->hstate = RSVG_HANDLE_STATE_CLOSED_ERROR;
}
g_clear_pointer (&handle->priv->load, rsvg_load_free);
handle->priv->tree = tree;
return was_successful;
}
......@@ -705,18 +738,39 @@ gboolean
rsvg_handle_close (RsvgHandle *handle, GError **error)
{
RsvgHandlePrivate *priv;
gboolean result;
gboolean read_successfully;
gboolean result = FALSE;
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
rsvg_return_val_if_fail (handle, FALSE, error);
priv = handle->priv;
if (priv->hstate == RSVG_HANDLE_STATE_CLOSED_OK
|| priv->hstate == RSVG_HANDLE_STATE_CLOSED_ERROR) {
switch (priv->hstate) {
case RSVG_HANDLE_STATE_START:
g_set_error (error, RSVG_ERROR, RSVG_ERROR_FAILED, _("no data passed to parser"));
priv->hstate = RSVG_HANDLE_STATE_CLOSED_ERROR;
result = FALSE;
break;
case RSVG_HANDLE_STATE_LOADING:
g_assert (priv->load != NULL);
read_successfully = rsvg_load_close (priv->load, error);
result = finish_load (handle, read_successfully, error);
break;
case RSVG_HANDLE_STATE_CLOSED_OK:
case RSVG_HANDLE_STATE_CLOSED_ERROR:
/* closing is idempotent */
return TRUE;
result = TRUE;
break;
default:
g_assert_not_reached ();
}
result = finish_load (handle, rsvg_load_close (priv->load, error));
g_assert (priv->hstate == RSVG_HANDLE_STATE_CLOSED_OK
|| priv->hstate == RSVG_HANDLE_STATE_CLOSED_ERROR);
return result;
}
......@@ -747,6 +801,7 @@ rsvg_handle_read_stream_sync (RsvgHandle *handle,
GError **error)
{
RsvgHandlePrivate *priv;
gboolean read_successfully;
gboolean result;
RsvgLoad *saved_load;
......@@ -764,7 +819,9 @@ rsvg_handle_read_stream_sync (RsvgHandle *handle,
saved_load = priv->load;
priv->load = rsvg_load_new (handle, (priv->flags & RSVG_HANDLE_FLAG_UNLIMITED) != 0);
result = finish_load (handle, rsvg_load_read_stream_sync (priv->load, stream, cancellable, error));
read_successfully = rsvg_load_read_stream_sync (priv->load, stream, cancellable, error);
result = finish_load (handle, read_successfully, error);
priv->load = saved_load;
......@@ -823,6 +880,17 @@ get_base_uri_from_filename (const gchar * filename)
return base_uri;
}
static gboolean
is_at_start_for_setting_base_file (RsvgHandle *handle)
{
if (handle->priv->hstate == RSVG_HANDLE_STATE_START) {
return TRUE;
} else {
g_warning ("Please set the base file or URI before loading any data into RsvgHandle");
return FALSE;
}
}
/**
* rsvg_handle_set_base_uri:
* @handle: A #RsvgHandle
......@@ -839,10 +907,15 @@ rsvg_handle_set_base_uri (RsvgHandle * handle, const char *base_uri)
gchar *uri;
GFile *file;
g_return_if_fail (handle != NULL);
g_return_if_fail (RSVG_IS_HANDLE (handle));
if (base_uri == NULL)
if (!is_at_start_for_setting_base_file (handle)) {
return;
}
if (base_uri == NULL) {
return;
}
if (path_is_uri (base_uri))
uri = g_strdup (base_uri);
......@@ -875,6 +948,10 @@ rsvg_handle_set_base_gfile (RsvgHandle *handle,
g_return_if_fail (RSVG_IS_HANDLE (handle));
g_return_if_fail (G_IS_FILE (base_file));
if (!is_at_start_for_setting_base_file (handle)) {
return;
}
priv = handle->priv;
g_object_ref (base_file);
......@@ -962,6 +1039,12 @@ rsvg_handle_get_defs (RsvgHandle *handle)
return handle->priv->defs;
}
RsvgCssStyles *
rsvg_handle_get_css_styles (RsvgHandle *handle)
{
return handle->priv->css_styles;
}
RsvgHandle *
rsvg_handle_load_extern (RsvgHandle *handle, const char *uri)
{
......@@ -989,6 +1072,12 @@ rsvg_handle_load_extern (RsvgHandle *handle, const char *uri)
return res;
}
gboolean
rsvg_handle_keep_image_data (RsvgHandle *handle)
{
return (handle->priv->flags & RSVG_HANDLE_FLAG_KEEP_IMAGE_DATA) != 0;
}
static RsvgDrawingCtx *
rsvg_handle_create_drawing_ctx(RsvgHandle *handle,
cairo_t *cr,
......@@ -1002,6 +1091,32 @@ rsvg_handle_create_drawing_ctx(RsvgHandle *handle,
handle->priv->is_testing);
}
static gboolean
is_loaded (RsvgHandle *handle)
{
switch (handle->priv->hstate) {
case RSVG_HANDLE_STATE_START:
g_warning ("RsvgHandle has not been loaded");
return FALSE;
case RSVG_HANDLE_STATE_LOADING:
g_warning ("RsvgHandle is still loading; call rsvg_handle_close() first");
return FALSE;
case RSVG_HANDLE_STATE_CLOSED_OK:
return TRUE;
case RSVG_HANDLE_STATE_CLOSED_ERROR:
g_warning ("RsvgHandle could not read or parse the SVG; did you check for errors\n"
"during the loading stage?");
return FALSE;
default:
g_assert_not_reached();
return FALSE;
}
}
/**
* rsvg_handle_render_cairo_sub:
* @handle: A #RsvgHandle
......@@ -1029,8 +1144,9 @@ rsvg_handle_render_cairo_sub (RsvgHandle * handle, cairo_t * cr, const char *id)
g_return_val_if_fail (handle != NULL, FALSE);
if (handle->priv->hstate != RSVG_HANDLE_STATE_CLOSED_OK)
if (!is_loaded (handle)) {
return FALSE;
}
status = cairo_status (cr);
......@@ -1054,21 +1170,21 @@ rsvg_handle_render_cairo_sub (RsvgHandle * handle, cairo_t * cr, const char *id)
if (dimensions.width == 0 || dimensions.height == 0)
return FALSE;
cairo_save (cr);
draw = rsvg_handle_create_drawing_ctx (handle, cr, &dimensions);
if (drawsub != NULL) {
rsvg_drawing_ctx_add_node_and_ancestors_to_stack (draw, drawsub);
}
cairo_save (cr);
rsvg_tree_cascade (handle->priv->tree);
res = rsvg_drawing_ctx_draw_node_from_stack (draw, handle->priv->tree);
cairo_restore (cr);
rsvg_drawing_ctx_free (draw);
cairo_restore (cr);
return res;
}
......@@ -1103,6 +1219,13 @@ rsvg_handle_render_cairo (RsvgHandle * handle, cairo_t * cr)
void
rsvg_handle_get_dimensions (RsvgHandle * handle, RsvgDimensionData * dimension_data)
{
g_return_if_fail (RSVG_IS_HANDLE (handle));
g_return_if_fail (dimension_data != NULL);
if (!is_loaded (handle)) {
return;
}
/* This function is probably called from the cairo_render functions.
* To prevent an infinite loop we are saving the state.
*/
......@@ -1166,39 +1289,49 @@ get_node_ink_rect(RsvgHandle *handle, RsvgNode *node, cairo_rectangle_t *ink_rec
gboolean
rsvg_handle_get_dimensions_sub (RsvgHandle * handle, RsvgDimensionData * dimension_data, const char *id)
{
RsvgNode *root = NULL;
RsvgNode *node;
gboolean has_size;
int root_width, root_height;
gboolean res = FALSE;
g_return_val_if_fail (handle, FALSE);
g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
g_return_val_if_fail (dimension_data, FALSE);
if (!is_loaded (handle)) {
return FALSE;
}
memset (dimension_data, 0, sizeof (RsvgDimensionData));
if (handle->priv->tree == NULL)
return FALSE;
root = rsvg_tree_get_root (handle->priv->tree);
if (id && *id) {
node = rsvg_defs_lookup (handle->priv->defs, id);
if (rsvg_tree_is_root (handle->priv->tree, node))
if (node && rsvg_tree_is_root (handle->priv->tree, node))
id = NULL;
} else {
node = rsvg_tree_get_root (handle->priv->tree);
node = root;
}
if (!node && id)
return FALSE;
if (!node && id) {
goto out;
}
has_size = rsvg_node_svg_get_size (rsvg_tree_get_root (handle->priv->tree),
has_size = rsvg_node_svg_get_size (root,
handle->priv->dpi_x, handle->priv->dpi_y,
&root_width, &root_height);
if (id || !has_size) {
cairo_rectangle_t ink_rect;
if (!get_node_ink_rect (handle, node, &ink_rect))
return FALSE;
if (!get_node_ink_rect (handle, node, &ink_rect)) {
goto out;
}
dimension_data->width = ink_rect.width;
dimension_data->height = ink_rect.height;
......@@ -1214,7 +1347,13 @@ rsvg_handle_get_dimensions_sub (RsvgHandle * handle, RsvgDimensionData * dimensi
(*handle->priv->size_func) (&dimension_data->width, &dimension_data->height,
handle->priv->user_data);
return TRUE;
res = TRUE;
out:
g_clear_pointer (&root, rsvg_node_unref);
return res;
}
/**
......@@ -1236,8 +1375,12 @@ rsvg_handle_get_position_sub (RsvgHandle * handle, RsvgPositionData * position_d
cairo_rectangle_t ink_rect;
int width, height;
g_return_val_if_fail (handle, FALSE);
g_return_val_if_fail (position_data, FALSE);
g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
g_return_val_if_fail (position_data != NULL, FALSE);
if (!is_loaded (handle)) {
return FALSE;
}
memset (position_data, 0, sizeof (*position_data));
......@@ -1285,7 +1428,11 @@ gboolean
rsvg_handle_has_sub (RsvgHandle * handle,
const char *id)
{
g_return_val_if_fail (handle, FALSE);
g_return_val_if_fail (RSVG_IS_HANDLE (handle), FALSE);
if (!is_loaded (handle)) {
return FALSE;
}
if (G_UNLIKELY (!id || !id[0]))
return FALSE;
......@@ -1323,10 +1470,11 @@ rsvg_handle_get_pixbuf_sub (RsvgHandle * handle, const char *id)
cairo_surface_t *surface;
cairo_t *cr;
g_return_val_if_fail (handle != NULL, NULL);
if (handle->priv->hstate != RSVG_HANDLE_STATE_CLOSED_OK)
g_return_val_if_fail (RSVG_IS_HANDLE (handle), NULL);
if (!is_loaded (handle)) {
return NULL;
}
rsvg_handle_get_dimensions (handle, &dimensions);
if (!(dimensions.width && dimensions.height))
......@@ -1665,82 +1813,6 @@ _rsvg_handle_acquire_stream (RsvgHandle *handle,
return stream;
}
cairo_surface_t *
rsvg_cairo_surface_new_from_href (RsvgHandle *handle,
const char *href,
GError **error)
{
char *data;
gsize data_len;
char *mime_type = NULL;
GdkPixbufLoader *loader = NULL;
GdkPixbuf *pixbuf = NULL;
cairo_surface_t *surface = NULL;
data = _rsvg_handle_acquire_data (handle, href, &mime_type, &data_len, error);
if (data == NULL)
return NULL;
if (mime_type) {
loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, error);
} else {
loader = gdk_pixbuf_loader_new ();
}
if (loader == NULL)
goto out;
if (!gdk_pixbuf_loader_write (loader, (guchar *) data, data_len, error)) {
gdk_pixbuf_loader_close (loader, NULL);
goto out;
}
if (!gdk_pixbuf_loader_close (loader, error))
goto out;
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
if (!pixbuf) {
g_set_error (error,
GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_FAILED,
_("Failed to load image '%s': reason not known, probably a corrupt image file"),
href);
goto out;
}
surface = rsvg_cairo_surface_from_pixbuf (pixbuf);
if (mime_type == NULL) {
/* Try to get the information from the loader */
GdkPixbufFormat *format;
char **mime_types;
if ((format = gdk_pixbuf_loader_get_format (loader)) != NULL) {
mime_types = gdk_pixbuf_format_get_mime_types (format);
if (mime_types != NULL)
mime_type = g_strdup (mime_types[0]);
g_strfreev (mime_types);
}
}
if ((handle->priv->flags & RSVG_HANDLE_FLAG_KEEP_IMAGE_DATA) != 0 &&
mime_type != NULL &&
cairo_surface_set_mime_data (surface, mime_type, (guchar *) data,
data_len, g_free, data) == CAIRO_STATUS_SUCCESS) {
data = NULL; /* transferred to the surface */
}
out:
if (loader)
g_object_unref (loader);
g_free (mime_type);
g_free (data);
return surface;
}
#ifdef HAVE_PANGOFT2
static void
......@@ -1808,3 +1880,15 @@ rsvg_handle_internal_set_testing (RsvgHandle *handle, gboolean testing)
rsvg_handle_update_font_map_for_testing (handle);
}
GType
rsvg_error_get_type(void)
{
return rsvg_rust_error_get_type();
}
GType
rsvg_handle_flags_get_type(void)
{
return rsvg_rust_handle_flags_get_type();
}
......@@ -28,7 +28,6 @@
#include "rsvg-attributes.h"
#include "rsvg-load.h"
#include "rsvg-styles.h"
typedef enum {
LOAD_STATE_START,
......@@ -40,11 +39,11 @@ typedef enum {
/* Implemented in rsvg_internals/src/load.rs */
G_GNUC_INTERNAL
RsvgNode *rsvg_load_new_node (const char *element_name, RsvgNode *parent, RsvgPropertyBag *atts, RsvgDefs *defs, gboolean *is_svg);
RsvgNode *rsvg_load_new_node (const char *element_name, RsvgNode *parent, RsvgPropertyBag *atts, RsvgDefs *defs);
/* Implemented in rsvg_internals/src/load.rs */
G_GNUC_INTERNAL
void rsvg_load_set_node_atts (RsvgHandle *handle, RsvgNode *node, const char *element_name, RsvgPropertyBag atts);
void rsvg_load_set_node_atts (RsvgHandle *handle, RsvgNode *node, RsvgPropertyBag atts);
/* Implemented in rsvg_internals/src/load.rs */
G_GNUC_INTERNAL
......@@ -184,7 +183,7 @@ style_handler_free (RsvgSaxHandler * self)
RsvgSaxHandlerStyle *z = (RsvgSaxHandlerStyle *) self;
if (z->is_text_css)
rsvg_parse_cssbuffer (z->load->handle, z->style->str, z->style->len);
rsvg_css_parse_into_handle (z->load->handle, z->style->str, z->style->len);
g_string_free (z->style, TRUE);
g_free (z);
......@@ -298,24 +297,23 @@ standard_element_start (RsvgLoad *load, const char *name, RsvgPropertyBag * atts
{
RsvgDefs *defs;
RsvgNode *newnode;
gboolean is_svg;
defs = rsvg_handle_get_defs(load->handle);
newnode = rsvg_load_new_node(name, load->currentnode, atts, defs, &is_svg);
newnode = rsvg_load_new_node(name, load->currentnode, atts, defs);
push_element_name (load, name);
if (load->currentnode) {
rsvg_node_add_child (load->currentnode, newnode);
load->currentnode = rsvg_node_unref (load->currentnode);
} else if (is_svg) {
} else {
load->tree = rsvg_tree_new (newnode);
}
load->currentnode = rsvg_node_ref (newnode);
rsvg_load_set_node_atts (load->handle, newnode, name, atts);
rsvg_load_set_node_atts (load->handle, newnode, atts);
newnode = rsvg_node_unref (newnode);
}
......@@ -934,7 +932,7 @@ sax_processing_instruction_cb (void *user_data, const xmlChar * target, const xm
if (style_data &&
mime_type &&
strcmp (mime_type, "text/css") == 0) {
rsvg_parse_cssbuffer (load->handle, style_data, style_data_len);
rsvg_css_parse_into_handle (load->handle, style_data, style_data_len);
}
g_free (mime_type);
......
......@@ -260,97 +260,6 @@ rsvg_pixbuf_from_file_at_max_size (const gchar * file_name,
return rsvg_pixbuf_from_file_with_size_data (file_name, &data, error);
}
cairo_surface_t *
rsvg_cairo_surface_from_pixbuf (const GdkPixbuf *pixbuf)
{
gint width, height, gdk_rowstride, n_channels, cairo_rowstride;
guchar *gdk_pixels, *cairo_pixels;
cairo_format_t format;
cairo_surface_t *surface;
int j;
if (pixbuf == NULL)
return NULL;
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
n_channels = gdk_pixbuf_get_n_channels (pixbuf);
if (n_channels == 3)
format = CAIRO_FORMAT_RGB24;
else
format = CAIRO_FORMAT_ARGB32;
surface = cairo_image_surface_create (format, width, height);
if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) {
cairo_surface_destroy (surface);
return NULL;
}
cairo_pixels = cairo_image_surface_get_data (surface);
cairo_rowstride = cairo_image_surface_get_stride (surface);
if (n_channels == 3) {
for (j = height; j; j--) {
guchar *p = gdk_pixels;
guchar *q = cairo_pixels;
guchar *end = p + 3 * width;
while (p < end) {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
q[0] = p[2];
q[1] = p[1];
q[2] = p[0];
#else
q[1] = p[0];
q[2] = p[1];
q[3] = p[2];
#endif
p += 3;
q += 4;
}
gdk_pixels += gdk_rowstride;
cairo_pixels += cairo_rowstride;
}
} else {
for (j = height; j; j--) {
guchar *p = gdk_pixels;
guchar *q = cairo_pixels;
guchar *end = p + 4 * width;
guint t1, t2, t3;
#define MULT(d,c,a,t) G_STMT_START { t = c * a + 0x7f; d = ((t >> 8) + t) >> 8; } G_STMT_END
while (p < end) {
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
MULT (q[0], p[2], p[3], t1);
MULT (q[1], p[1], p[3], t2);
MULT (q[2], p[0], p[3], t3);
q[3] = p[3];
#else
q[0] = p[3];
MULT (q[1], p[0], p[3], t1);
MULT (q[2], p[1], p[3], t2);
MULT (q[3], p[2], p[3], t3);
#endif
p += 4;
q += 4;