summaryrefslogtreecommitdiff
path: root/rsvg_internals/src/cond.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rsvg_internals/src/cond.rs')
-rw-r--r--rsvg_internals/src/cond.rs224
1 files changed, 224 insertions, 0 deletions
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))
+ );
+ }
+}