[librsvg: 2/5] (#577): Parse multiple fonts in font-family



commit 8c6dd5bc60ed12a67f875299795881c9f83ddb20
Author: Bastien Orivel <eijebong bananium fr>
Date:   Fri May 1 15:26:27 2020 +0200

    (#577): Parse multiple fonts in font-family
    
    Fixes https://gitlab.gnome.org/GNOME/librsvg/-/issues/577

 rsvg_internals/src/font_props.rs    | 70 +++++++++++++++++++++----------------
 rsvg_internals/src/property_defs.rs |  6 ++--
 2 files changed, 43 insertions(+), 33 deletions(-)
---
diff --git a/rsvg_internals/src/font_props.rs b/rsvg_internals/src/font_props.rs
index 24d60087..c34ed7db 100644
--- a/rsvg_internals/src/font_props.rs
+++ b/rsvg_internals/src/font_props.rs
@@ -198,32 +198,34 @@ impl Parse for LetterSpacingSpec {
 
 /// https://www.w3.org/TR/2008/REC-CSS2-20080411/fonts.html#propdef-font-family
 #[derive(Debug, Clone, PartialEq)]
-pub struct SingleFontFamily(pub String);
+pub struct MultiFontFamily(pub String);
 
-impl Parse for SingleFontFamily {
-    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<SingleFontFamily, ParseError<'i>> {
+impl Parse for MultiFontFamily {
+    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<MultiFontFamily, ParseError<'i>> {
         let loc = parser.current_source_location();
 
-        if let Ok(cow) = parser.try_parse(|p| p.expect_string_cloned()) {
-            if cow == "" {
-                return Err(loc.new_custom_error(ValueErrorKind::value_error(
-                    "empty string is not a valid font family name",
-                )));
-            }
-
-            return Ok(SingleFontFamily((*cow).to_owned()));
-        }
+        let fonts = parser.parse_comma_separated(|parser| {
+            if let Ok(cow) = parser.try_parse(|p| p.expect_string_cloned()) {
+                if cow == "" {
+                    return Err(loc.new_custom_error(ValueErrorKind::value_error(
+                        "empty string is not a valid font family name",
+                    )));
+                }
 
-        let first_ident = parser.expect_ident()?.clone();
+                return Ok(cow);
+            }
 
-        let mut value = first_ident.as_ref().to_owned();
+            let first_ident = parser.expect_ident()?.clone();
+            let mut value = first_ident.as_ref().to_owned();
 
-        while let Ok(cow) = parser.try_parse(|p| p.expect_ident_cloned()) {
-            value.push(' ');
-            value.push_str(&cow);
-        }
+            while let Ok(cow) = parser.try_parse(|p| p.expect_ident_cloned()) {
+                value.push(' ');
+                value.push_str(&cow);
+            }
+            Ok(cssparser::CowRcStr::from(value))
+        })?;
 
-        Ok(SingleFontFamily(value))
+        Ok(MultiFontFamily(fonts.join(",")))
     }
 }
 
@@ -347,30 +349,38 @@ mod tests {
     #[test]
     fn parses_font_family() {
         assert_eq!(
-            <SingleFontFamily as Parse>::parse_str("'Hello world'"),
-            Ok(SingleFontFamily("Hello world".to_owned()))
+            <MultiFontFamily as Parse>::parse_str("'Hello world'"),
+            Ok(MultiFontFamily("Hello world".to_owned()))
+        );
+
+        assert_eq!(
+            <MultiFontFamily as Parse>::parse_str("\"Hello world\""),
+            Ok(MultiFontFamily("Hello world".to_owned()))
         );
 
         assert_eq!(
-            <SingleFontFamily as Parse>::parse_str("\"Hello world\""),
-            Ok(SingleFontFamily("Hello world".to_owned()))
+            <MultiFontFamily as Parse>::parse_str("  Hello  world  "),
+            Ok(MultiFontFamily("Hello world".to_owned()))
         );
 
         assert_eq!(
-            <SingleFontFamily as Parse>::parse_str("  Hello  world  "),
-            Ok(SingleFontFamily("Hello world".to_owned()))
+            <MultiFontFamily as Parse>::parse_str("Plonk"),
+            Ok(MultiFontFamily("Plonk".to_owned()))
         );
+    }
 
+    #[test]
+    fn parses_multiple_font_family() {
         assert_eq!(
-            <SingleFontFamily as Parse>::parse_str("Plonk"),
-            Ok(SingleFontFamily("Plonk".to_owned()))
+            <MultiFontFamily as Parse>::parse_str("serif,monospace,\"Hello world\""),
+            Ok(MultiFontFamily("serif,monospace,Hello world".to_owned()))
         );
     }
 
     #[test]
     fn detects_invalid_font_family() {
-        assert!(<SingleFontFamily as Parse>::parse_str("").is_err());
-        assert!(<SingleFontFamily as Parse>::parse_str("''").is_err());
-        assert!(<SingleFontFamily as Parse>::parse_str("42").is_err());
+        assert!(<MultiFontFamily as Parse>::parse_str("").is_err());
+        assert!(<MultiFontFamily as Parse>::parse_str("''").is_err());
+        assert!(<MultiFontFamily as Parse>::parse_str("42").is_err());
     }
 }
diff --git a/rsvg_internals/src/property_defs.rs b/rsvg_internals/src/property_defs.rs
index 1bc0ce0c..dc67eacc 100644
--- a/rsvg_internals/src/property_defs.rs
+++ b/rsvg_internals/src/property_defs.rs
@@ -4,7 +4,7 @@ use cssparser::{Parser, Token};
 
 use crate::dasharray::Dasharray;
 use crate::error::*;
-use crate::font_props::{FontSizeSpec, FontWeightSpec, LetterSpacingSpec, SingleFontFamily};
+use crate::font_props::{FontSizeSpec, FontWeightSpec, LetterSpacingSpec, MultiFontFamily};
 use crate::iri::IRI;
 use crate::length::*;
 use crate::paint_server::PaintServer;
@@ -234,9 +234,9 @@ make_property!(
 make_property!(
     ComputedValues,
     FontFamily,
-    default: SingleFontFamily("Times New Roman".to_string()),
+    default: MultiFontFamily("Times New Roman".to_string()),
     inherits_automatically: true,
-    newtype_parse: SingleFontFamily,
+    newtype_parse: MultiFontFamily,
 );
 
 // https://www.w3.org/TR/SVG/text.html#FontSizeProperty


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