[librsvg: 2/3] (#558): Compute cascaded font-size values correctly for relative units
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 2/3] (#558): Compute cascaded font-size values correctly for relative units
- Date: Sat, 15 Feb 2020 02:59:41 +0000 (UTC)
commit f1db361e346cc58e40be5fd836ead7a1454e924d
Author: Federico Mena Quintero <federico gnome org>
Date: Fri Feb 14 20:51:52 2020 -0600
(#558): Compute cascaded font-size values correctly for relative units
We were ignoring Em and Ex as cases that need to be derived from the
parent element's computed font-size.
Fixes https://gitlab.gnome.org/GNOME/librsvg/issues/558
rsvg_internals/src/font_props.rs | 88 ++++++++++++++++++++++++++++++++++------
1 file changed, 75 insertions(+), 13 deletions(-)
---
diff --git a/rsvg_internals/src/font_props.rs b/rsvg_internals/src/font_props.rs
index 1feab115..6a0a300b 100644
--- a/rsvg_internals/src/font_props.rs
+++ b/rsvg_internals/src/font_props.rs
@@ -34,22 +34,44 @@ impl FontSizeSpec {
pub fn compute(&self, v: &ComputedValues) -> Self {
let compute_points = |p| 12.0 * 1.2f64.powf(p) / POINTS_PER_INCH;
- let size = v.font_size.0.value();
+ let parent = v.font_size.0.value();
+ // The parent must already have resolved to an absolute unit
+ assert!(
+ parent.unit != LengthUnit::Percent
+ && parent.unit != LengthUnit::Em
+ && parent.unit != LengthUnit::Ex
+ );
+
+ use FontSizeSpec::*;
+
+ #[rustfmt::skip]
let new_size = match self {
- FontSizeSpec::Smaller => Length::<Both>::new(size.length / 1.2, size.unit),
- FontSizeSpec::Larger => Length::<Both>::new(size.length * 1.2, size.unit),
- FontSizeSpec::XXSmall => Length::<Both>::new(compute_points(-3.0), LengthUnit::In),
- FontSizeSpec::XSmall => Length::<Both>::new(compute_points(-2.0), LengthUnit::In),
- FontSizeSpec::Small => Length::<Both>::new(compute_points(-1.0), LengthUnit::In),
- FontSizeSpec::Medium => Length::<Both>::new(compute_points(0.0), LengthUnit::In),
- FontSizeSpec::Large => Length::<Both>::new(compute_points(1.0), LengthUnit::In),
- FontSizeSpec::XLarge => Length::<Both>::new(compute_points(2.0), LengthUnit::In),
- FontSizeSpec::XXLarge => Length::<Both>::new(compute_points(3.0), LengthUnit::In),
- FontSizeSpec::Value(s) if s.unit == LengthUnit::Percent => {
- Length::<Both>::new(size.length * s.length, size.unit)
+ Smaller => Length::<Both>::new(parent.length / 1.2, parent.unit),
+ Larger => Length::<Both>::new(parent.length * 1.2, parent.unit),
+ XXSmall => Length::<Both>::new(compute_points(-3.0), LengthUnit::In),
+ XSmall => Length::<Both>::new(compute_points(-2.0), LengthUnit::In),
+ Small => Length::<Both>::new(compute_points(-1.0), LengthUnit::In),
+ Medium => Length::<Both>::new(compute_points(0.0), LengthUnit::In),
+ Large => Length::<Both>::new(compute_points(1.0), LengthUnit::In),
+ XLarge => Length::<Both>::new(compute_points(2.0), LengthUnit::In),
+ XXLarge => Length::<Both>::new(compute_points(3.0), LengthUnit::In),
+
+ Value(s) if s.unit == LengthUnit::Percent => {
+ Length::<Both>::new(parent.length * s.length, parent.unit)
}
- FontSizeSpec::Value(s) => *s,
+
+ Value(s) if s.unit == LengthUnit::Em => {
+ Length::<Both>::new(parent.length * s.length, parent.unit)
+ }
+
+ Value(s) if s.unit == LengthUnit::Ex => {
+ // FIXME: it would be nice to know the actual Ex-height
+ // of the font.
+ Length::<Both>::new(parent.length * s.length / 2.0, parent.unit)
+ }
+
+ Value(s) => *s,
};
FontSizeSpec::Value(new_size)
@@ -209,11 +231,51 @@ impl Parse for SingleFontFamily {
mod tests {
use super::*;
+ use crate::property_defs::FontSize;
+ use crate::property_macros::Property;
+
#[test]
fn detects_invalid_invalid_font_size() {
assert!(FontSizeSpec::parse_str("furlong").is_err());
}
+ #[test]
+ fn computes_parent_relative_font_size() {
+ let mut values = ComputedValues::default();
+ values.font_size = FontSize::parse_str("10px").unwrap();
+
+ assert_eq!(
+ FontSize::parse_str("150%").unwrap().compute(&values),
+ FontSize::parse_str("15px").unwrap()
+ );
+
+ assert_eq!(
+ FontSize::parse_str("1.5em").unwrap().compute(&values),
+ FontSize::parse_str("15px").unwrap()
+ );
+
+ assert_eq!(
+ FontSize::parse_str("1ex").unwrap().compute(&values),
+ FontSize::parse_str("5px").unwrap()
+ );
+
+ let smaller = FontSize::parse_str("smaller").unwrap().compute(&values).0;
+ if let FontSizeSpec::Value(v) = smaller {
+ assert!(v.length < 10.0);
+ assert_eq!(v.unit, LengthUnit::Px);
+ } else {
+ unreachable!();
+ }
+
+ let larger = FontSize::parse_str("larger").unwrap().compute(&values).0;
+ if let FontSizeSpec::Value(v) = larger {
+ assert!(v.length > 10.0);
+ assert_eq!(v.unit, LengthUnit::Px);
+ } else {
+ unreachable!();
+ }
+ }
+
#[test]
fn parses_font_weight() {
assert_eq!(
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]