summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico.mena@gmail.com>2018-03-20 01:44:58 +0000
committerFederico Mena Quintero <federico.mena@gmail.com>2018-03-20 01:44:58 +0000
commite236e8f804dad86f3cc243097f6ca2170343a976 (patch)
tree0aa4f0ecc8cc180b2fc91a19ec82f591f76ff892
parent0381c490029fcfaaf060da3a490bb272d726df8e (diff)
parent2eb933da6d271dcbb7a07c02150af8577cc07242 (diff)
downloadlibrsvg-e236e8f804dad86f3cc243097f6ca2170343a976.tar.gz
Merge branch 'cond-rs' into 'master'
Implement svg switch conditions in rust See merge request GNOME/librsvg!39
-rw-r--r--Makefile.am1
-rw-r--r--config.h.win32.in3
-rw-r--r--configure.ac4
-rw-r--r--librsvg/rsvg-cond.c192
-rw-r--r--librsvg/rsvg-css.c83
-rw-r--r--librsvg/rsvg-css.h3
-rw-r--r--librsvg/rsvg-private.h12
-rw-r--r--librsvg/rsvg-styles.c47
-rw-r--r--rsvg_internals/src/cond.rs224
-rw-r--r--rsvg_internals/src/lib.rs7
10 files changed, 289 insertions, 287 deletions
diff --git a/Makefile.am b/Makefile.am
index cd7324a1..fafacd96 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -34,7 +34,6 @@ librsvg_@RSVG_API_MAJOR_VERSION@_la_SOURCES = \
librsvg/rsvg-cairo-render.c \
librsvg/rsvg-cairo-render.h \
librsvg/rsvg-cairo.h \
- librsvg/rsvg-cond.c \
librsvg/rsvg-css.c \
librsvg/rsvg-css.h \
librsvg/rsvg-defs.c \
diff --git a/config.h.win32.in b/config.h.win32.in
index 7d4ee6b6..7cfdd175 100644
--- a/config.h.win32.in
+++ b/config.h.win32.in
@@ -39,9 +39,6 @@
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
-/* Define to 1 if you have the `strtok_r' function. */
-/* #undef HAVE_STRTOK_R */
-
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
diff --git a/configure.ac b/configure.ac
index 4a653d0d..63b10627 100644
--- a/configure.ac
+++ b/configure.ac
@@ -151,10 +151,6 @@ esac
GLIB_TESTS
-dnl ===========================================================================
-
-AC_CHECK_FUNCS(strtok_r)
-
# ===========================================================================
# GTK
# ===========================================================================
diff --git a/librsvg/rsvg-cond.c b/librsvg/rsvg-cond.c
deleted file mode 100644
index 0fd2c67b..00000000
--- a/librsvg/rsvg-cond.c
+++ /dev/null
@@ -1,192 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/* vim: set sw=4 sts=4 expandtab: */
-/*
- rsvg-cond.c: Handle SVG conditionals
-
- Copyright (C) 2004-2005 Dom Lachowicz <cinamod@hotmail.com>
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public
- License along with this program; if not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
-
- Author: Dom Lachowicz
-*/
-
-#include "config.h"
-
-#include "rsvg-private.h"
-#include "rsvg-css.h"
-#include "rsvg-styles.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <locale.h>
-
-/* Keep these sorted alphabetically! These are used with bsearch() */
-static const char *implemented_features[] = {
- "http://www.w3.org/TR/SVG11/feature#BasicFilter",
- "http://www.w3.org/TR/SVG11/feature#BasicGraphicsAttribute",
- "http://www.w3.org/TR/SVG11/feature#BasicPaintAttribute",
- "http://www.w3.org/TR/SVG11/feature#BasicStructure",
- "http://www.w3.org/TR/SVG11/feature#BasicText",
- "http://www.w3.org/TR/SVG11/feature#ConditionalProcessing",
- "http://www.w3.org/TR/SVG11/feature#ContainerAttribute",
- "http://www.w3.org/TR/SVG11/feature#Filter",
- "http://www.w3.org/TR/SVG11/feature#Gradient",
- "http://www.w3.org/TR/SVG11/feature#Image",
- "http://www.w3.org/TR/SVG11/feature#Marker",
- "http://www.w3.org/TR/SVG11/feature#Mask",
- "http://www.w3.org/TR/SVG11/feature#OpacityAttribute",
- "http://www.w3.org/TR/SVG11/feature#Pattern",
- "http://www.w3.org/TR/SVG11/feature#SVG",
- "http://www.w3.org/TR/SVG11/feature#SVG-static",
- "http://www.w3.org/TR/SVG11/feature#Shape",
- "http://www.w3.org/TR/SVG11/feature#Structure",
- "http://www.w3.org/TR/SVG11/feature#Style",
- "http://www.w3.org/TR/SVG11/feature#View",
- "org.w3c.svg.static" /* deprecated SVG 1.0 feature string */
-};
-static const guint nb_implemented_features = G_N_ELEMENTS (implemented_features);
-
-static const char **implemented_extensions = NULL;
-static const guint nb_implemented_extensions = 0;
-
-static int
-rsvg_feature_compare (const void *a, const void *b)
-{
- return strcmp ((const char *) a, *(const char **) b);
-}
-
-/* http://www.w3.org/TR/SVG/struct.html#RequiredFeaturesAttribute */
-static gboolean
-rsvg_cond_fulfills_requirement (const char *value, const char **features, guint nb_features)
-{
- guint nb_elems = 0;
- char **elems;
- gboolean permitted = TRUE;
-
- elems = rsvg_css_parse_list (value, &nb_elems);
-
- if (elems && nb_elems) {
- guint i;
-
- for (i = 0; (i < nb_elems) && permitted; i++)
- if (!bsearch (elems[i], features, nb_features, sizeof (char *), rsvg_feature_compare))
- permitted = FALSE;
-
- g_strfreev (elems);
- } else
- permitted = FALSE;
-
- return permitted;
-}
-
-/* http://www.w3.org/TR/SVG/struct.html#SystemLanguageAttribute */
-static gboolean
-rsvg_locale_compare (const char *a, const char *b)
-{
- const char *hyphen;
-
- /* check for an exact-ish match first */
- if (!g_ascii_strncasecmp (a, b, strlen (b)))
- return TRUE;
-
- /* check to see if there's a hyphen */
- hyphen = strstr (b, "-");
- if (!hyphen)
- return FALSE;
-
- /* compare up to the hyphen */
- return !g_ascii_strncasecmp (a, b, (hyphen - b));
-}
-
-/* http://www.w3.org/TR/SVG/struct.html#SystemLanguageAttribute */
-static gboolean
-rsvg_cond_parse_system_language (const char *value)
-{
- guint nb_elems = 0;
- char **elems;
- gboolean permitted = FALSE;
-
- elems = rsvg_css_parse_list (value, &nb_elems);
-
- if (elems && nb_elems) {
- const gchar * const *languages;
-
- languages = g_get_language_names ();
-
- if (languages) {
- guint i, j;
-
- for (i = 0; (i < nb_elems) && !permitted; i++) {
- for (j = 0; languages[j] && !permitted; j++) {
- permitted = rsvg_locale_compare (languages[j], elems[i]);
- }
- }
- }
-
- g_strfreev (elems);
- }
-
- return permitted;
-}
-
-/* returns TRUE if this element should be processed according to <switch> semantics
- http://www.w3.org/TR/SVG/struct.html#SwitchElement */
-gboolean
-rsvg_eval_switch_attributes (RsvgPropertyBag * atts, gboolean * p_has_cond)
-{
- gboolean required_features_ok = TRUE;
- gboolean required_extensions_ok = TRUE;
- gboolean system_language_ok = TRUE;
- gboolean has_cond = FALSE;
-
- RsvgPropertyBagIter *iter;
- const char *key;
- RsvgAttribute attr;
- const char *value;
-
- iter = rsvg_property_bag_iter_begin (atts);
-
- while (rsvg_property_bag_iter_next (iter, &key, &attr, &value)) {
- switch (attr) {
- case RSVG_ATTRIBUTE_REQUIRED_FEATURES:
- required_features_ok = rsvg_cond_fulfills_requirement (value, implemented_features,
- nb_implemented_features);
- has_cond = TRUE;
- break;
-
- case RSVG_ATTRIBUTE_REQUIRED_EXTENSIONS:
- required_extensions_ok = rsvg_cond_fulfills_requirement (value, implemented_extensions,
- nb_implemented_extensions);
- has_cond = TRUE;
- break;
-
- case RSVG_ATTRIBUTE_SYSTEM_LANGUAGE:
- system_language_ok = rsvg_cond_parse_system_language (value);
- has_cond = TRUE;
- break;
-
- default:
- break;
- }
- }
-
- rsvg_property_bag_iter_end (iter);
-
- if (p_has_cond)
- *p_has_cond = has_cond;
-
- return required_features_ok && required_extensions_ok && system_language_ok;
-}
diff --git a/librsvg/rsvg-css.c b/librsvg/rsvg-css.c
index 467fb363..17e3ae96 100644
--- a/librsvg/rsvg-css.c
+++ b/librsvg/rsvg-css.c
@@ -254,89 +254,6 @@ rsvg_css_parse_font_family (const char *str, gboolean * inherit)
return str;
}
-#if !defined(HAVE_STRTOK_R)
-
-static char *
-strtok_r (char *s, const char *delim, char **last)
-{
- char *p;
-
- if (s == NULL)
- s = *last;
-
- if (s == NULL)
- return NULL;
-
- while (*s && strchr (delim, *s))
- s++;
-
- if (*s == '\0') {
- *last = NULL;
- return NULL;
- }
-
- p = s;
- while (*p && !strchr (delim, *p))
- p++;
-
- if (*p == '\0')
- *last = NULL;
- else {
- *p = '\0';
- p++;
- *last = p;
- }
-
- return s;
-}
-
-#endif /* !HAVE_STRTOK_R */
-
-gchar **
-rsvg_css_parse_list (const char *in_str, guint * out_list_len)
-{
- char *ptr, *tok;
- char *str;
-
- guint n = 0;
- GSList *string_list = NULL;
- gchar **string_array = NULL;
-
- str = g_strdup (in_str);
- tok = strtok_r (str, ", \t", &ptr);
- if (tok != NULL) {
- if (strcmp (tok, " ") != 0) {
- string_list = g_slist_prepend (string_list, g_strdup (tok));
- n++;
- }
-
- while ((tok = strtok_r (NULL, ", \t", &ptr)) != NULL) {
- if (strcmp (tok, " ") != 0) {
- string_list = g_slist_prepend (string_list, g_strdup (tok));
- n++;
- }
- }
- }
- g_free (str);
-
- if (out_list_len)
- *out_list_len = n;
-
- if (string_list) {
- GSList *slist;
-
- string_array = g_new0 (gchar *, n + 1);
-
- string_array[n--] = NULL;
- for (slist = string_list; slist; slist = slist->next)
- string_array[n--] = (gchar *) slist->data;
-
- g_slist_free (string_list);
- }
-
- return string_array;
-}
-
gboolean
rsvg_css_parse_overflow (const char *str, gboolean * inherit)
{
diff --git a/librsvg/rsvg-css.h b/librsvg/rsvg-css.h
index 088521da..3ada0f08 100644
--- a/librsvg/rsvg-css.h
+++ b/librsvg/rsvg-css.h
@@ -104,9 +104,6 @@ const char *rsvg_css_parse_font_family (const char *str, gboolean * inherit
G_GNUC_INTERNAL
gboolean rsvg_css_parse_number_optional_number (const char *str, double *out_x, double *out_y);
-G_GNUC_INTERNAL
-gchar **rsvg_css_parse_list (const char *in_str, guint * out_list_len);
-
/* Keep in sync with rust/src/parsers.rs:NumberListLength */
typedef enum {
NUMBER_LIST_LENGTH_EXACT,
diff --git a/librsvg/rsvg-private.h b/librsvg/rsvg-private.h
index 0ce62284..e529d3ca 100644
--- a/librsvg/rsvg-private.h
+++ b/librsvg/rsvg-private.h
@@ -472,8 +472,18 @@ GdkPixbuf *rsvg_pixbuf_from_data_with_size_data (const guchar * buff,
size_t len,
gpointer data,
const char *base_uri, GError ** error);
+
+/* Implemented in rust/src/cond.rs */
+G_GNUC_INTERNAL
+gboolean rsvg_cond_check_required_features (const char *value);
+
+/* Implemented in rust/src/cond.rs */
+G_GNUC_INTERNAL
+gboolean rsvg_cond_check_required_extensions (const char *value);
+
+/* Implemented in rust/src/cond.rs */
G_GNUC_INTERNAL
-gboolean rsvg_eval_switch_attributes (RsvgPropertyBag * atts, gboolean * p_has_cond);
+gboolean rsvg_cond_check_system_language (const char *value);
G_GNUC_INTERNAL
void rsvg_pop_discrete_layer (RsvgDrawingCtx * ctx);
diff --git a/librsvg/rsvg-styles.c b/librsvg/rsvg-styles.c
index 4932aeed..cc337bae 100644
--- a/librsvg/rsvg-styles.c
+++ b/librsvg/rsvg-styles.c
@@ -1173,6 +1173,53 @@ rsvg_parse_style_pair (RsvgState *state,
}
}
+/* returns TRUE if this element should be processed according to <switch> semantics
+ http://www.w3.org/TR/SVG/struct.html#SwitchElement */
+static gboolean
+rsvg_eval_switch_attributes (RsvgPropertyBag * atts, gboolean * p_has_cond)
+{
+ gboolean required_features_ok = TRUE;
+ gboolean required_extensions_ok = TRUE;
+ gboolean system_language_ok = TRUE;
+ gboolean has_cond = FALSE;
+
+ RsvgPropertyBagIter *iter;
+ const char *key;
+ RsvgAttribute attr;
+ const char *value;
+
+ iter = rsvg_property_bag_iter_begin (atts);
+
+ while (rsvg_property_bag_iter_next (iter, &key, &attr, &value)) {
+ switch (attr) {
+ case RSVG_ATTRIBUTE_REQUIRED_FEATURES:
+ required_features_ok = rsvg_cond_check_required_features (value);
+ has_cond = TRUE;
+ break;
+
+ case RSVG_ATTRIBUTE_REQUIRED_EXTENSIONS:
+ required_extensions_ok = rsvg_cond_check_required_extensions (value);
+ has_cond = TRUE;
+ break;
+
+ case RSVG_ATTRIBUTE_SYSTEM_LANGUAGE:
+ system_language_ok = rsvg_cond_check_system_language (value);
+ has_cond = TRUE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ rsvg_property_bag_iter_end (iter);
+
+ if (p_has_cond)
+ *p_has_cond = has_cond;
+
+ return required_features_ok && required_extensions_ok && system_language_ok;
+}
+
/* take a pair of the form (fill="#ff00ff") and parse it as a style */
void
rsvg_parse_presentation_attributes (RsvgState * state, RsvgPropertyBag * atts)
diff --git a/rsvg_internals/src/cond.rs b/rsvg_internals/src/cond.rs
new file mode 100644
index 00000000..f9c4d315
--- /dev/null
+++ b/rsvg_internals/src/cond.rs
@@ -0,0 +1,224 @@
+use glib;
+use glib_sys;
+use libc;
+
+use error::*;
+use parsers::Parse;
+use std::marker::PhantomData;
+use util::utf8_cstr;
+
+use self::glib::translate::*;
+
+// No extensions at the moment.
+static IMPLEMENTED_EXTENSIONS: &[&str] = &[];
+
+#[derive(Debug, PartialEq)]
+struct RequiredExtensions(bool);
+
+impl Parse for RequiredExtensions {
+ type Data = ();
+ type Err = AttributeError;
+
+ // Parse a requiredExtensions attribute
+ // http://www.w3.org/TR/SVG/struct.html#RequiredExtensionsAttribute
+ fn parse(s: &str, _: ()) -> Result<RequiredExtensions, AttributeError> {
+ Ok(RequiredExtensions(
+ s.split_whitespace()
+ .all(|f| IMPLEMENTED_EXTENSIONS.binary_search(&f).is_ok()),
+ ))
+ }
+}
+
+// Keep these sorted alphabetically for binary_search.
+static IMPLEMENTED_FEATURES: &[&str] = &[
+ "http://www.w3.org/TR/SVG11/feature#BasicFilter",
+ "http://www.w3.org/TR/SVG11/feature#BasicGraphicsAttribute",
+ "http://www.w3.org/TR/SVG11/feature#BasicPaintAttribute",
+ "http://www.w3.org/TR/SVG11/feature#BasicStructure",
+ "http://www.w3.org/TR/SVG11/feature#BasicText",
+ "http://www.w3.org/TR/SVG11/feature#ConditionalProcessing",
+ "http://www.w3.org/TR/SVG11/feature#ContainerAttribute",
+ "http://www.w3.org/TR/SVG11/feature#Filter",
+ "http://www.w3.org/TR/SVG11/feature#Gradient",
+ "http://www.w3.org/TR/SVG11/feature#Image",
+ "http://www.w3.org/TR/SVG11/feature#Marker",
+ "http://www.w3.org/TR/SVG11/feature#Mask",
+ "http://www.w3.org/TR/SVG11/feature#OpacityAttribute",
+ "http://www.w3.org/TR/SVG11/feature#Pattern",
+ "http://www.w3.org/TR/SVG11/feature#SVG",
+ "http://www.w3.org/TR/SVG11/feature#SVG-static",
+ "http://www.w3.org/TR/SVG11/feature#Shape",
+ "http://www.w3.org/TR/SVG11/feature#Structure",
+ "http://www.w3.org/TR/SVG11/feature#Style",
+ "http://www.w3.org/TR/SVG11/feature#View",
+ "org.w3c.svg.static", // deprecated SVG 1.0 feature string
+];
+
+#[derive(Debug, PartialEq)]
+struct RequiredFeatures(bool);
+
+impl Parse for RequiredFeatures {
+ type Data = ();
+ type Err = AttributeError;
+
+ // Parse a requiredFeatures attribute
+ // http://www.w3.org/TR/SVG/struct.html#RequiredFeaturesAttribute
+ fn parse(s: &str, _: ()) -> Result<RequiredFeatures, AttributeError> {
+ Ok(RequiredFeatures(
+ s.split_whitespace()
+ .all(|f| IMPLEMENTED_FEATURES.binary_search(&f).is_ok()),
+ ))
+ }
+}
+
+#[derive(Debug, PartialEq)]
+struct SystemLanguage<'a>(bool, PhantomData<&'a i8>);
+
+impl<'a> Parse for SystemLanguage<'a> {
+ type Data = &'a [String];
+ type Err = AttributeError;
+
+ // Parse a systemLanguage attribute
+ // http://www.w3.org/TR/SVG/struct.html#SystemLanguageAttribute
+ fn parse(s: &str, system_languages: &[String]) -> Result<SystemLanguage<'a>, AttributeError> {
+ Ok(SystemLanguage(
+ s.split(',')
+ .map(|s| s.trim())
+ .filter(|s| !s.is_empty())
+ .any(|l| {
+ system_languages.iter().any(|sl| {
+ if sl.eq_ignore_ascii_case(l) {
+ return true;
+ }
+
+ if let Some(offset) = l.find('-') {
+ return sl.eq_ignore_ascii_case(&l[..offset]);
+ }
+
+ false
+ })
+ }),
+ PhantomData,
+ ))
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn rsvg_cond_check_required_extensions(
+ raw_value: *const libc::c_char,
+) -> glib_sys::gboolean {
+ let value = unsafe { utf8_cstr(raw_value) };
+
+ match RequiredExtensions::parse(value, ()) {
+ Ok(RequiredExtensions(res)) => res.to_glib(),
+ Err(_) => false.to_glib(),
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn rsvg_cond_check_required_features(
+ raw_value: *const libc::c_char,
+) -> glib_sys::gboolean {
+ let value = unsafe { utf8_cstr(raw_value) };
+
+ match RequiredFeatures::parse(value, ()) {
+ Ok(RequiredFeatures(res)) => res.to_glib(),
+ Err(_) => false.to_glib(),
+ }
+}
+
+#[no_mangle]
+pub extern "C" fn rsvg_cond_check_system_language(
+ raw_value: *const libc::c_char,
+) -> glib_sys::gboolean {
+ let value = unsafe { utf8_cstr(raw_value) };
+
+ match SystemLanguage::parse(value, &glib::get_language_names()) {
+ Ok(SystemLanguage(res, _)) => res.to_glib(),
+ Err(_) => false.to_glib(),
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn parse_required_extensions() {
+ assert_eq!(
+ RequiredExtensions::parse("http://test.org/NotExisting/1.0", ()),
+ Ok(RequiredExtensions(false))
+ );
+ }
+
+ #[test]
+ fn parse_required_features() {
+ assert_eq!(
+ RequiredFeatures::parse("http://www.w3.org/TR/SVG11/feature#NotExisting", ()),
+ Ok(RequiredFeatures(false))
+ );
+
+ assert_eq!(
+ RequiredFeatures::parse("http://www.w3.org/TR/SVG11/feature#BasicFilter", ()),
+ Ok(RequiredFeatures(true))
+ );
+
+ assert_eq!(
+ RequiredFeatures::parse(
+ "http://www.w3.org/TR/SVG11/feature#BasicFilter \
+ http://www.w3.org/TR/SVG11/feature#NotExisting",
+ ()
+ ),
+ Ok(RequiredFeatures(false))
+ );
+
+ assert_eq!(
+ RequiredFeatures::parse(
+ "http://www.w3.org/TR/SVG11/feature#BasicFilter \
+ http://www.w3.org/TR/SVG11/feature#BasicText",
+ ()
+ ),
+ Ok(RequiredFeatures(true))
+ );
+ }
+
+ #[test]
+ fn parse_system_language() {
+ let system_languages = vec![String::from("de"), String::from("en_US")];
+
+ assert_eq!(
+ SystemLanguage::parse("", &system_languages),
+ Ok(SystemLanguage(false, PhantomData))
+ );
+
+ assert_eq!(
+ SystemLanguage::parse("fr", &system_languages),
+ Ok(SystemLanguage(false, PhantomData))
+ );
+
+ assert_eq!(
+ SystemLanguage::parse("de", &system_languages),
+ Ok(SystemLanguage(true, PhantomData))
+ );
+
+ assert_eq!(
+ SystemLanguage::parse("en_US", &system_languages),
+ Ok(SystemLanguage(true, PhantomData))
+ );
+
+ assert_eq!(
+ SystemLanguage::parse("DE", &system_languages),
+ Ok(SystemLanguage(true, PhantomData))
+ );
+
+ assert_eq!(
+ SystemLanguage::parse("de-LU", &system_languages),
+ Ok(SystemLanguage(true, PhantomData))
+ );
+
+ assert_eq!(
+ SystemLanguage::parse("fr, de", &system_languages),
+ Ok(SystemLanguage(true, PhantomData))
+ );
+ }
+}
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 282b349c..be3d6a1d 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -33,6 +33,12 @@ pub use cnode::{rsvg_rust_cnode_get_impl, rsvg_rust_cnode_new};
pub use color::{rsvg_css_parse_color, AllowCurrentColor, AllowInherit, ColorKind, ColorSpec};
+pub use cond::{
+ rsvg_cond_check_required_extensions,
+ rsvg_cond_check_required_features,
+ rsvg_cond_check_system_language,
+};
+
pub use draw::{rsvg_draw_pango_layout, rsvg_draw_path_builder};
pub use gradient::{rsvg_node_linear_gradient_new, rsvg_node_radial_gradient_new};
@@ -149,6 +155,7 @@ mod chars;
mod clip_path;
mod cnode;
mod color;
+mod cond;
mod draw;
mod drawing_ctx;
mod error;