[librsvg: 13/22] Implement parser for the "font" shorthand
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 13/22] Implement parser for the "font" shorthand
- Date: Wed, 1 Jul 2020 00:04:16 +0000 (UTC)
commit b631e37c40f42ed73dece372455855e26de96e6b
Author: Federico Mena Quintero <federico gnome org>
Date: Tue Jun 30 14:26:04 2020 -0500
Implement parser for the "font" shorthand
Mostly stolen from Servo.
rsvg_internals/src/font_props.rs | 120 ++++++++++++++++++++++++++++++++++++
rsvg_internals/src/property_defs.rs | 18 +++++-
2 files changed, 137 insertions(+), 1 deletion(-)
---
diff --git a/rsvg_internals/src/font_props.rs b/rsvg_internals/src/font_props.rs
index 3e232908..ac4ae37c 100644
--- a/rsvg_internals/src/font_props.rs
+++ b/rsvg_internals/src/font_props.rs
@@ -8,6 +8,126 @@ use crate::error::*;
use crate::length::*;
use crate::parsers::{finite_f32, Parse};
use crate::properties::ComputedValues;
+use crate::property_defs::{FontStretch, FontStyle, FontVariant};
+
+// https://www.w3.org/TR/CSS2/fonts.html#font-shorthand
+// https://drafts.csswg.org/css-fonts-4/#font-prop
+// servo/components/style/properties/shorthands/font.mako.rs is a good reference for this
+#[derive(Debug, Clone, PartialEq)]
+pub enum Font {
+ Caption,
+ Icon,
+ Menu,
+ MessageBox,
+ SmallCaption,
+ StatusBar,
+ Spec {
+ style: FontStyle,
+ variant: FontVariant,
+ weight: FontWeight,
+ stretch: FontStretch,
+ size: FontSize,
+ line_height: LineHeight,
+ family: FontFamily,
+ }
+}
+
+impl Parse for Font {
+ fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Font, ParseError<'i>> {
+ if let Ok(f) = parse_font_spec_identifiers(parser) {
+ return Ok(f);
+ }
+
+ // The following is stolen from servo/components/style/properties/shorthands/font.mako.rs
+
+ let mut nb_normals = 0;
+ let mut style = None;
+ let mut variant_caps = None;
+ let mut weight = None;
+ let mut stretch = None;
+ let size;
+
+ loop {
+ // Special-case 'normal' because it is valid in each of
+ // font-style, font-weight, font-variant and font-stretch.
+ // Leaves the values to None, 'normal' is the initial value for each of them.
+ if parser.try_parse(|input| input.expect_ident_matching("normal")).is_ok() {
+ nb_normals += 1;
+ continue;
+ }
+ if style.is_none() {
+ if let Ok(value) = parser.try_parse(FontStyle::parse) {
+ style = Some(value);
+ continue
+ }
+ }
+ if weight.is_none() {
+ if let Ok(value) = parser.try_parse(FontWeight::parse) {
+ weight = Some(value);
+ continue
+ }
+ }
+ if variant_caps.is_none() {
+ if let Ok(value) = parser.try_parse(FontVariant::parse) {
+ variant_caps = Some(value);
+ continue
+ }
+ }
+ if stretch.is_none() {
+ if let Ok(value) = parser.try_parse(FontStretch::parse) {
+ stretch = Some(value);
+ continue
+ }
+ }
+ size = FontSize::parse(parser)?;
+ break
+ }
+
+ let line_height = if parser.try_parse(|input| input.expect_delim('/')).is_ok() {
+ Some(LineHeight::parse(parser)?)
+ } else {
+ None
+ };
+
+ #[inline]
+ fn count<T>(opt: &Option<T>) -> u8 {
+ if opt.is_some() { 1 } else { 0 }
+ }
+
+ if (count(&style) + count(&weight) + count(&variant_caps) + count(&stretch) + nb_normals) > 4 {
+ return Err(parser.new_custom_error(ValueErrorKind::parse_error(
+ "invalid syntax for 'font' property"
+ )))
+ }
+
+ let family = FontFamily::parse(parser)?;
+
+ Ok(Font::Spec {
+ style: style.unwrap_or_default(),
+ variant: variant_caps.unwrap_or_default(),
+ weight: weight.unwrap_or_default(),
+ stretch: stretch.unwrap_or_default(),
+ size,
+ line_height: line_height.unwrap_or_default(),
+ family,
+ })
+ }
+}
+
+#[rustfmt::skip]
+fn parse_font_spec_identifiers<'i>(parser: &mut Parser<'i, '_>) -> Result<Font, ParseError<'i>> {
+ Ok(parser.try_parse(|p| {
+ parse_identifiers! {
+ p,
+ "caption" => Font::Caption,
+ "icon" => Font::Icon,
+ "menu" => Font::Menu,
+ "message-box" => Font::MessageBox,
+ "small-caption" => Font::SmallCaption,
+ "status-bar" => Font::StatusBar,
+ }
+ })?)
+}
// https://www.w3.org/TR/2008/REC-CSS2-20080411/fonts.html#propdef-font-size
#[derive(Debug, Copy, Clone, PartialEq)]
diff --git a/rsvg_internals/src/property_defs.rs b/rsvg_internals/src/property_defs.rs
index 4ca31a28..8ea2e338 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::{FontFamily, FontSize, FontWeight, LetterSpacing, LineHeight};
+use crate::font_props::{Font, FontFamily, FontSize, FontWeight, LetterSpacing, LineHeight};
use crate::iri::IRI;
use crate::length::*;
use crate::paint_server::PaintServer;
@@ -230,6 +230,22 @@ make_property!(
newtype_parse: UnitInterval,
);
+// https://drafts.csswg.org/css-fonts-4/#font-prop
+make_property!(
+ ComputedValues,
+ Font,
+ default: Font::Spec {
+ style: Default::default(),
+ variant: Default::default(),
+ weight: Default::default(),
+ stretch: Default::default(),
+ size: Default::default(),
+ line_height: Default::default(),
+ family: Default::default(),
+ },
+ inherits_automatically: true,
+);
+
// https://www.w3.org/TR/SVG/text.html#FontFamilyProperty
make_property!(
ComputedValues,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]