gitlab#319 - Parse font-family correctly

We were just using cssparser.expect_string(), which takes quoted
strings.  In CSS/SVG, however, font-family can take quoted or unquoted
strings.

We now have a SingleFontFamily type that can parse a font-family.

#319
parent 08daccbb
Pipeline #26375 failed with stages
in 15 minutes and 52 seconds
use cssparser::{Parser, Token};
use cssparser::{BasicParseError, Parser, Token};
use drawing_ctx::DrawingCtx;
use error::*;
......@@ -242,6 +242,39 @@ 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);
impl Parse for SingleFontFamily {
type Data = ();
type Err = AttributeError;
fn parse(parser: &mut Parser, _: Self::Data) -> Result<SingleFontFamily, AttributeError> {
parse_single_font_family(parser)
.map_err(|_| AttributeError::from(ParseError::new("expected font family")))
}
}
fn parse_single_font_family<'i>(
parser: &'i mut Parser,
) -> Result<SingleFontFamily, BasicParseError<'i>> {
if let Ok(cow) = parser.try(|p| p.expect_string_cloned()) {
return Ok(SingleFontFamily((*cow).to_owned()));
}
let first_ident = parser.expect_ident()?.clone();
let mut value = first_ident.as_ref().to_owned();
while let Ok(cow) = parser.try(|p| p.expect_ident_cloned()) {
value.push(' ');
value.push_str(&cow);
}
Ok(SingleFontFamily(value))
}
#[cfg(test)]
mod tests {
use super::*;
......@@ -315,4 +348,36 @@ mod tests {
fn detects_invalid_invalid_letter_spacing() {
assert!(is_parse_error(&LetterSpacingSpec::parse_str("furlong", ())));
}
#[test]
fn parses_font_family() {
assert_eq!(
<SingleFontFamily as Parse>::parse_str("'Hello world'", ()),
Ok(SingleFontFamily("Hello world".to_owned()))
);
assert_eq!(
<SingleFontFamily as Parse>::parse_str("\"Hello world\"", ()),
Ok(SingleFontFamily("Hello world".to_owned()))
);
assert_eq!(
<SingleFontFamily as Parse>::parse_str(" Hello world ", ()),
Ok(SingleFontFamily("Hello world".to_owned()))
);
assert_eq!(
<SingleFontFamily as Parse>::parse_str("Plonk", ()),
Ok(SingleFontFamily("Plonk".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());
}
}
......@@ -8,7 +8,7 @@ use std::str::FromStr;
use attributes::Attribute;
use error::*;
use font_props::{FontSizeSpec, FontWeightSpec, LetterSpacingSpec};
use font_props::{FontSizeSpec, FontWeightSpec, LetterSpacingSpec, SingleFontFamily};
use handle::RsvgHandle;
use iri::IRI;
use length::{Dasharray, Length, LengthDir, LengthUnit};
......@@ -954,9 +954,9 @@ make_property!(
make_property!(
ComputedValues,
FontFamily,
default: "Times New Roman".to_string(),
default: SingleFontFamily("Times New Roman".to_string()),
inherits_automatically: true,
newtype_parse: String,
newtype_parse: SingleFontFamily,
parse_data_type: ()
);
......
......@@ -508,7 +508,7 @@ fn create_pango_layout(
let mut font_desc = pango_context.get_font_description().unwrap();
font_desc.set_family(&values.font_family.0);
font_desc.set_family(&(values.font_family.0).0);
font_desc.set_style(pango::Style::from(values.font_style));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment