[librsvg: 3/5] Move rsvg_css_parse_color() and its machinery to librsvg_c_api



commit 3b235a3bd8b71636787fe4fe920b1105586096fd
Author: Federico Mena Quintero <federico gnome org>
Date:   Tue Jan 14 10:47:46 2020 -0600

    Move rsvg_css_parse_color() and its machinery to librsvg_c_api
    
    This is only used by rsvg-convert now; no need to have it in the main
    internals library.

 Makefile.am                 |   1 +
 librsvg/color_utils.rs      | 186 ++++++++++++++++++++++++++++++++++++++++++++
 librsvg/lib.rs              |   3 +
 rsvg_internals/src/color.rs | 186 --------------------------------------------
 rsvg_internals/src/lib.rs   |   6 +-
 5 files changed, 194 insertions(+), 188 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index d2ab8a3e..c51b2e1d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -117,6 +117,7 @@ LIBRSVG_CRATE_SRC =                                                 \
 LIBRSVG_C_API_SRC =                                            \
        librsvg/Cargo.toml                                      \
        librsvg/c_api.rs                                        \
+       librsvg/color_utils.rs                                  \
        librsvg/lib.rs                                          \
        librsvg/pixbuf_utils.rs                                 \
        $(NULL)
diff --git a/librsvg/color_utils.rs b/librsvg/color_utils.rs
new file mode 100644
index 00000000..be8d12c9
--- /dev/null
+++ b/librsvg/color_utils.rs
@@ -0,0 +1,186 @@
+use libc;
+
+use std::ffi::CStr;
+
+use rsvg_internals::{Color, Parse, ParseError};
+
+// There are two quirks here:
+//
+// First, we need to expose the Color algebraic type *and* a parse
+// error to C, but we can't repr(C) them plainly.  So, we define a
+// ColorKind enum and a ColorSpec struct that can both be represented
+// in C.
+//
+// Second, the C code in librsvg expects ARGB colors passed around as
+// guint32.  However, in Rust we'd prefer to use cssparser's RGBA
+// structure, which has explicit fields for red/green/blue/alpha.
+// We'll do those conversions here, for the benefit of the C code, and
+// then just wait until the C code gradually disappears.
+
+// Keep this in sync with rsvg-css.h:RsvgCssColorKind
+#[repr(C)]
+#[derive(Clone, Copy, PartialEq, Debug)]
+pub enum ColorKind {
+    ARGB,
+    ParseError,
+}
+
+// Keep this in sync with rsvg-css.h:RsvgCssColorSpec
+#[repr(C)]
+#[derive(Clone, Copy, PartialEq, Debug)]
+pub struct ColorSpec {
+    kind: ColorKind,
+    argb: u32,
+}
+
+fn rgba_to_argb(r: u8, g: u8, b: u8, a: u8) -> u32 {
+    u32::from(a) << 24 | u32::from(r) << 16 | u32::from(g) << 8 | u32::from(b)
+}
+
+impl<'i> From<Result<Color, ParseError<'i>>> for ColorSpec {
+    fn from(result: Result<Color, ParseError<'i>>) -> ColorSpec {
+        match result {
+            Ok(Color::RGBA(rgba)) => ColorSpec {
+                kind: ColorKind::ARGB,
+                argb: rgba_to_argb(rgba.red, rgba.green, rgba.blue, rgba.alpha),
+            },
+
+            _ => ColorSpec {
+                kind: ColorKind::ParseError,
+                argb: 0,
+            },
+        }
+    }
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn rsvg_css_parse_color(string: *const libc::c_char) -> ColorSpec {
+    let s = CStr::from_ptr(string).to_string_lossy();
+
+    ColorSpec::from(<Color as Parse>::parse_str(&s))
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use glib::translate::*;
+
+    fn parse(s: &str) -> ColorSpec {
+        unsafe { rsvg_css_parse_color(s.to_glib_none().0) }
+    }
+
+    #[test]
+    fn parses_hash_hex_colors() {
+        assert_eq!(
+            parse("#AB10fa20"),
+            ColorSpec {
+                kind: ColorKind::ARGB,
+                argb: 0x20ab10fa,
+            }
+        );
+        assert_eq!(
+            parse("#10fa20"),
+            ColorSpec {
+                kind: ColorKind::ARGB,
+                argb: 0xff10fa20,
+            }
+        );
+        assert_eq!(
+            parse("#abcd"),
+            ColorSpec {
+                kind: ColorKind::ARGB,
+                argb: 0xddaabbcc,
+            }
+        );
+        assert_eq!(
+            parse("#123"),
+            ColorSpec {
+                kind: ColorKind::ARGB,
+                argb: 0xff112233,
+            }
+        );
+    }
+
+    #[test]
+    fn parses_color_keywords() {
+        assert_eq!(
+            parse("red"),
+            ColorSpec {
+                kind: ColorKind::ARGB,
+                argb: 0xffff0000,
+            }
+        );
+        assert_eq!(
+            parse("lime"),
+            ColorSpec {
+                kind: ColorKind::ARGB,
+                argb: 0xff00ff00,
+            }
+        );
+        assert_eq!(
+            parse("blue"),
+            ColorSpec {
+                kind: ColorKind::ARGB,
+                argb: 0xff0000ff,
+            }
+        );
+    }
+
+    #[test]
+    fn parses_color_functions() {
+        assert_eq!(
+            parse("rgb(255, 0, 0)"),
+            ColorSpec {
+                kind: ColorKind::ARGB,
+                argb: 0xffff0000,
+            }
+        );
+        assert_eq!(
+            parse("rgb(0, 255, 0)"),
+            ColorSpec {
+                kind: ColorKind::ARGB,
+                argb: 0xff00ff00,
+            }
+        );
+        assert_eq!(
+            parse("rgb(0, 0, 255)"),
+            ColorSpec {
+                kind: ColorKind::ARGB,
+                argb: 0xff0000ff,
+            }
+        );
+    }
+
+    #[test]
+    fn current_color_is_error() {
+        assert_eq!(
+            parse("currentColor"),
+            ColorSpec {
+                kind: ColorKind::ParseError,
+                argb: 0,
+            }
+        );
+    }
+
+    fn make_error() -> ColorSpec {
+        ColorSpec {
+            kind: ColorKind::ParseError,
+            argb: 0,
+        }
+    }
+
+    #[test]
+    fn invalid_hash_hex_colors_yield_error() {
+        assert_eq!(parse("#"), make_error());
+        assert_eq!(parse("#xyz"), make_error());
+        assert_eq!(parse("#112233gg"), make_error());
+    }
+
+    #[test]
+    fn invalid_colors_yield_error() {
+        assert_eq!(parse(""), make_error());
+        assert_eq!(parse("foo"), make_error());
+        assert_eq!(parse("rgb(chilaquil)"), make_error());
+        assert_eq!(parse("rgb(1, 2, 3, 4, 5)"), make_error());
+    }
+}
diff --git a/librsvg/lib.rs b/librsvg/lib.rs
index 770ea939..60efd427 100644
--- a/librsvg/lib.rs
+++ b/librsvg/lib.rs
@@ -38,6 +38,8 @@ pub use crate::c_api::{
     rsvg_rust_handle_write,
 };
 
+pub use crate::color_utils::rsvg_css_parse_color;
+
 pub use crate::pixbuf_utils::{
     rsvg_rust_pixbuf_from_file_at_max_size,
     rsvg_rust_pixbuf_from_file_at_size,
@@ -46,4 +48,5 @@ pub use crate::pixbuf_utils::{
 };
 
 mod c_api;
+mod color_utils;
 mod pixbuf_utils;
diff --git a/rsvg_internals/src/color.rs b/rsvg_internals/src/color.rs
index 3807075c..b83b76f4 100644
--- a/rsvg_internals/src/color.rs
+++ b/rsvg_internals/src/color.rs
@@ -1,11 +1,9 @@
 //! CSS color values.
 
 use cssparser::Parser;
-use libc;
 
 use crate::error::*;
 use crate::parsers::Parse;
-use crate::util::utf8_cstr;
 
 pub use cssparser::Color;
 
@@ -27,187 +25,3 @@ impl Parse for cssparser::RGBA {
         }
     }
 }
-
-// There are two quirks here:
-//
-// First, we need to expose the Color algebraic type *and* a parse
-// error to C, but we can't repr(C) them plainly.  So, we define a
-// ColorKind enum and a ColorSpec struct that can both be represented
-// in C.
-//
-// Second, the C code in librsvg expects ARGB colors passed around as
-// guint32.  However, in Rust we'd prefer to use cssparser's RGBA
-// structure, which has explicit fields for red/green/blue/alpha.
-// We'll do those conversions here, for the benefit of the C code, and
-// then just wait until the C code gradually disappears.
-
-// Keep this in sync with rsvg-css.h:RsvgCssColorKind
-#[repr(C)]
-#[derive(Clone, Copy, PartialEq, Debug)]
-pub enum ColorKind {
-    ARGB,
-    ParseError,
-}
-
-// Keep this in sync with rsvg-css.h:RsvgCssColorSpec
-#[repr(C)]
-#[derive(Clone, Copy, PartialEq, Debug)]
-pub struct ColorSpec {
-    kind: ColorKind,
-    argb: u32,
-}
-
-fn rgba_to_argb(rgba: cssparser::RGBA) -> u32 {
-    u32::from(rgba.alpha) << 24
-        | u32::from(rgba.red) << 16
-        | u32::from(rgba.green) << 8
-        | u32::from(rgba.blue)
-}
-
-impl<'i> From<Result<cssparser::Color, ParseError<'i>>> for ColorSpec {
-    fn from(result: Result<cssparser::Color, ParseError<'i>>) -> ColorSpec {
-        match result {
-            Ok(cssparser::Color::RGBA(rgba)) => ColorSpec {
-                kind: ColorKind::ARGB,
-                argb: rgba_to_argb(rgba),
-            },
-
-            _ => ColorSpec {
-                kind: ColorKind::ParseError,
-                argb: 0,
-            },
-        }
-    }
-}
-
-#[no_mangle]
-pub extern "C" fn rsvg_css_parse_color(string: *const libc::c_char) -> ColorSpec {
-    let s = unsafe { utf8_cstr(string) };
-
-    ColorSpec::from(<Color as Parse>::parse_str(s))
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-    use glib::translate::*;
-
-    fn parse(s: &str) -> ColorSpec {
-        rsvg_css_parse_color(s.to_glib_none().0)
-    }
-
-    #[test]
-    fn parses_hash_hex_colors() {
-        assert_eq!(
-            parse("#AB10fa20"),
-            ColorSpec {
-                kind: ColorKind::ARGB,
-                argb: 0x20ab10fa,
-            }
-        );
-        assert_eq!(
-            parse("#10fa20"),
-            ColorSpec {
-                kind: ColorKind::ARGB,
-                argb: 0xff10fa20,
-            }
-        );
-        assert_eq!(
-            parse("#abcd"),
-            ColorSpec {
-                kind: ColorKind::ARGB,
-                argb: 0xddaabbcc,
-            }
-        );
-        assert_eq!(
-            parse("#123"),
-            ColorSpec {
-                kind: ColorKind::ARGB,
-                argb: 0xff112233,
-            }
-        );
-    }
-
-    #[test]
-    fn parses_color_keywords() {
-        assert_eq!(
-            parse("red"),
-            ColorSpec {
-                kind: ColorKind::ARGB,
-                argb: 0xffff0000,
-            }
-        );
-        assert_eq!(
-            parse("lime"),
-            ColorSpec {
-                kind: ColorKind::ARGB,
-                argb: 0xff00ff00,
-            }
-        );
-        assert_eq!(
-            parse("blue"),
-            ColorSpec {
-                kind: ColorKind::ARGB,
-                argb: 0xff0000ff,
-            }
-        );
-    }
-
-    #[test]
-    fn parses_color_functions() {
-        assert_eq!(
-            parse("rgb(255, 0, 0)"),
-            ColorSpec {
-                kind: ColorKind::ARGB,
-                argb: 0xffff0000,
-            }
-        );
-        assert_eq!(
-            parse("rgb(0, 255, 0)"),
-            ColorSpec {
-                kind: ColorKind::ARGB,
-                argb: 0xff00ff00,
-            }
-        );
-        assert_eq!(
-            parse("rgb(0, 0, 255)"),
-            ColorSpec {
-                kind: ColorKind::ARGB,
-                argb: 0xff0000ff,
-            }
-        );
-    }
-
-    #[test]
-    fn current_color_is_error() {
-        assert_eq!(
-            parse("currentColor"),
-            ColorSpec {
-                kind: ColorKind::ParseError,
-                argb: 0,
-            }
-        );
-    }
-
-    fn make_error() -> ColorSpec {
-        ColorSpec {
-            kind: ColorKind::ParseError,
-            argb: 0,
-        }
-    }
-
-    #[test]
-    fn invalid_hash_hex_colors_yield_error() {
-        assert_eq!(parse("#"), make_error());
-        assert_eq!(parse("#xyz"), make_error());
-        assert_eq!(parse("#112233gg"), make_error());
-    }
-
-    #[test]
-    fn invalid_colors_yield_error() {
-        assert_eq!(parse(""), make_error());
-        assert_eq!(parse("foo"), make_error());
-        assert_eq!(parse("rgb(chilaquil)"), make_error());
-        assert_eq!(parse("rgb(1, 2, 3, 4, 5)"), make_error());
-    }
-}
diff --git a/rsvg_internals/src/lib.rs b/rsvg_internals/src/lib.rs
index 4fc29d48..d8075c3f 100644
--- a/rsvg_internals/src/lib.rs
+++ b/rsvg_internals/src/lib.rs
@@ -40,11 +40,11 @@
 #![warn(unused)]
 use ::xml as xml_rs;
 
-pub use crate::color::{rsvg_css_parse_color, ColorKind, ColorSpec};
+pub use crate::color::Color;
 
 pub use crate::dpi::{rsvg_rust_set_default_dpi_x_y, Dpi};
 
-pub use crate::error::{DefsLookupErrorKind, HrefError, LoadingError, RenderingError};
+pub use crate::error::{DefsLookupErrorKind, HrefError, LoadingError, ParseError, RenderingError};
 
 pub use crate::handle::{
     Handle, LoadOptions, RsvgDimensionData, RsvgPositionData, RsvgSizeFunc, SizeCallback,
@@ -52,6 +52,8 @@ pub use crate::handle::{
 
 pub use crate::length::{Length, LengthUnit, RsvgLength};
 
+pub use crate::parsers::Parse;
+
 pub use crate::rect::IRect;
 
 pub use crate::structure::IntrinsicDimensions;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]