aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <infra@servo.org>2023-05-11 18:41:09 +0200
committerGitHub <noreply@github.com>2023-05-11 18:41:09 +0200
commitfeaa66b5972c3e31d77c2acce7d626c455320535 (patch)
tree0599544c17bd29578ccdb6d03272bf843dc4e406
parent425b0fe641e16083507c459041ff5dd19256ed7c (diff)
parent6785c57c788dd08fc128f0c72758d60c9b8bcfc4 (diff)
downloadservo-feaa66b5972c3e31d77c2acce7d626c455320535.tar.gz
servo-feaa66b5972c3e31d77c2acce7d626c455320535.zip
Auto merge of #29729 - Loirooriol:sync-cap-D133101, r=mrobinson
Add support for the 'cap' font-relative unit This is a backport of https://phabricator.services.mozilla.com/D133101, by Jonathan Kew. Note that Servo isn't using font metrics yet, so the unit still won't really work. <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [ ] These changes fix #___ (GitHub issue number if applicable) <!-- Either: --> - [ ] There are tests for these changes OR - [ ] These changes do not require tests because ___ <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
-rw-r--r--components/style/font_metrics.rs24
-rw-r--r--components/style/gecko/wrapper.rs13
-rw-r--r--components/style/values/generics/calc.rs1
-rw-r--r--components/style/values/specified/calc.rs1
-rw-r--r--components/style/values/specified/length.rs37
5 files changed, 68 insertions, 8 deletions
diff --git a/components/style/font_metrics.rs b/components/style/font_metrics.rs
index b521fdf76c9..db435539735 100644
--- a/components/style/font_metrics.rs
+++ b/components/style/font_metrics.rs
@@ -12,20 +12,38 @@ use crate::Atom;
/// Represents the font metrics that style needs from a font to compute the
/// value of certain CSS units like `ex`.
-#[derive(Clone, Debug, Default, PartialEq)]
+#[derive(Clone, Debug, PartialEq)]
pub struct FontMetrics {
/// The x-height of the font.
pub x_height: Option<Length>,
/// The zero advance. This is usually writing mode dependent
pub zero_advance_measure: Option<Length>,
+ /// The cap-height of the font.
+ pub cap_height: Option<Length>,
+ /// The ascent of the font (a value is always available for this).
+ pub ascent: Length,
+}
+
+impl Default for FontMetrics {
+ fn default() -> Self {
+ FontMetrics {
+ x_height: None,
+ zero_advance_measure: None,
+ cap_height: None,
+ ascent: Length::new(0.0),
+ }
+ }
}
/// Type of font metrics to retrieve.
#[derive(Clone, Debug, PartialEq)]
pub enum FontMetricsOrientation {
/// Get metrics for horizontal or vertical according to the Context's
- /// writing mode.
- MatchContext,
+ /// writing mode, using horizontal metrics for vertical/mixed
+ MatchContextPreferHorizontal,
+ /// Get metrics for horizontal or vertical according to the Context's
+ /// writing mode, using vertical metrics for vertical/mixed
+ MatchContextPreferVertical,
/// Force getting horizontal metrics.
Horizontal,
}
diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs
index 1813c225c57..78e41cf767f 100644
--- a/components/style/gecko/wrapper.rs
+++ b/components/style/gecko/wrapper.rs
@@ -979,7 +979,12 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
};
let vertical_metrics = match orientation {
- FontMetricsOrientation::MatchContext => wm.is_vertical() && wm.is_upright(),
+ FontMetricsOrientation::MatchContextPreferHorizontal => {
+ wm.is_vertical() && wm.is_upright()
+ },
+ FontMetricsOrientation::MatchContextPreferVertical => {
+ wm.is_vertical() && !wm.is_sideways()
+ },
FontMetricsOrientation::Horizontal => false,
};
let gecko_metrics = unsafe {
@@ -999,6 +1004,12 @@ impl FontMetricsProvider for GeckoFontMetricsProvider {
} else {
None
},
+ cap_height: if gecko_metrics.mCapHeight.px() >= 0. {
+ Some(gecko_metrics.mCapHeight)
+ } else {
+ None
+ },
+ ascent: gecko_metrics.mAscent,
}
}
}
diff --git a/components/style/values/generics/calc.rs b/components/style/values/generics/calc.rs
index 0d791e5d00d..d2bc2a85523 100644
--- a/components/style/values/generics/calc.rs
+++ b/components/style/values/generics/calc.rs
@@ -42,6 +42,7 @@ pub enum MinMaxOp {
pub enum SortKey {
Number,
Percentage,
+ Cap,
Ch,
Deg,
Em,
diff --git a/components/style/values/specified/calc.rs b/components/style/values/specified/calc.rs
index eb8b2fe4217..c42683bce1f 100644
--- a/components/style/values/specified/calc.rs
+++ b/components/style/values/specified/calc.rs
@@ -168,6 +168,7 @@ impl generic::CalcNodeLeaf for Leaf {
FontRelativeLength::Ch(..) => SortKey::Ch,
FontRelativeLength::Em(..) => SortKey::Em,
FontRelativeLength::Ex(..) => SortKey::Ex,
+ FontRelativeLength::Cap(..) => SortKey::Cap,
FontRelativeLength::Rem(..) => SortKey::Rem,
},
NoCalcLength::ViewportPercentage(ref vp) => match *vp {
diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs
index 7c03e8dce42..62f070893a6 100644
--- a/components/style/values/specified/length.rs
+++ b/components/style/values/specified/length.rs
@@ -57,6 +57,9 @@ pub enum FontRelativeLength {
/// A "ch" value: https://drafts.csswg.org/css-values/#ch
#[css(dimension)]
Ch(CSSFloat),
+ /// A "cap" value: https://drafts.csswg.org/css-values/#cap
+ #[css(dimension)]
+ Cap(CSSFloat),
/// A "rem" value: https://drafts.csswg.org/css-values/#rem
#[css(dimension)]
Rem(CSSFloat),
@@ -90,6 +93,7 @@ impl FontRelativeLength {
FontRelativeLength::Em(v) |
FontRelativeLength::Ex(v) |
FontRelativeLength::Ch(v) |
+ FontRelativeLength::Cap(v) |
FontRelativeLength::Rem(v) => v == 0.,
}
}
@@ -99,6 +103,7 @@ impl FontRelativeLength {
FontRelativeLength::Em(v) |
FontRelativeLength::Ex(v) |
FontRelativeLength::Ch(v) |
+ FontRelativeLength::Cap(v) |
FontRelativeLength::Rem(v) => v < 0.,
}
}
@@ -114,12 +119,13 @@ impl FontRelativeLength {
(&Em(one), &Em(other)) => Em(one + other),
(&Ex(one), &Ex(other)) => Ex(one + other),
(&Ch(one), &Ch(other)) => Ch(one + other),
+ (&Cap(one), &Cap(other)) => Cap(one + other),
(&Rem(one), &Rem(other)) => Rem(one + other),
// See https://github.com/rust-lang/rust/issues/68867. rustc isn't
// able to figure it own on its own so we help.
_ => unsafe {
match *self {
- Em(..) | Ex(..) | Ch(..) | Rem(..) => {},
+ Em(..) | Ex(..) | Ch(..) | Cap(..) | Rem(..) => {},
}
debug_unreachable!("Forgot to handle unit in try_sum()")
},
@@ -207,8 +213,11 @@ impl FontRelativeLength {
// measure of a glyph is its advance width or height,
// whichever is in the inline axis of the element.)
//
- let metrics =
- query_font_metrics(context, base_size, FontMetricsOrientation::MatchContext);
+ let metrics = query_font_metrics(
+ context,
+ base_size,
+ FontMetricsOrientation::MatchContextPreferHorizontal,
+ );
let reference_size = metrics.zero_advance_measure.unwrap_or_else(|| {
// https://drafts.csswg.org/css-values/#ch
//
@@ -229,6 +238,23 @@ impl FontRelativeLength {
});
(reference_size, length)
},
+ FontRelativeLength::Cap(length) => {
+ if context.for_non_inherited_property.is_some() {
+ context.rule_cache_conditions.borrow_mut().set_uncacheable();
+ }
+ context.builder.add_flags(font_metrics_flag);
+ let metrics =
+ query_font_metrics(context, base_size, FontMetricsOrientation::Horizontal);
+ let reference_size = metrics.cap_height.unwrap_or_else(|| {
+ // https://drafts.csswg.org/css-values/#cap
+ //
+ // In the cases where it is impossible or impractical to
+ // determine the cap-height, the font’s ascent must be used.
+ //
+ metrics.ascent
+ });
+ (reference_size, length)
+ },
FontRelativeLength::Rem(length) => {
// https://drafts.csswg.org/css-values/#rem:
//
@@ -540,6 +566,7 @@ impl NoCalcLength {
"em" => NoCalcLength::FontRelative(FontRelativeLength::Em(value)),
"ex" => NoCalcLength::FontRelative(FontRelativeLength::Ex(value)),
"ch" => NoCalcLength::FontRelative(FontRelativeLength::Ch(value)),
+ "cap" => NoCalcLength::FontRelative(FontRelativeLength::Cap(value)),
"rem" => NoCalcLength::FontRelative(FontRelativeLength::Rem(value)),
// viewport percentages
"vw" if !context.in_page_rule() => {
@@ -699,12 +726,13 @@ impl PartialOrd for FontRelativeLength {
(&Em(ref one), &Em(ref other)) => one.partial_cmp(other),
(&Ex(ref one), &Ex(ref other)) => one.partial_cmp(other),
(&Ch(ref one), &Ch(ref other)) => one.partial_cmp(other),
+ (&Cap(ref one), &Cap(ref other)) => one.partial_cmp(other),
(&Rem(ref one), &Rem(ref other)) => one.partial_cmp(other),
// See https://github.com/rust-lang/rust/issues/68867. rustc isn't
// able to figure it own on its own so we help.
_ => unsafe {
match *self {
- Em(..) | Ex(..) | Ch(..) | Rem(..) => {},
+ Em(..) | Ex(..) | Ch(..) | Cap(..) | Rem(..) => {},
}
debug_unreachable!("Forgot an arm in partial_cmp?")
},
@@ -721,6 +749,7 @@ impl Mul<CSSFloat> for FontRelativeLength {
FontRelativeLength::Em(v) => FontRelativeLength::Em(v * scalar),
FontRelativeLength::Ex(v) => FontRelativeLength::Ex(v * scalar),
FontRelativeLength::Ch(v) => FontRelativeLength::Ch(v * scalar),
+ FontRelativeLength::Cap(v) => FontRelativeLength::Cap(v * scalar),
FontRelativeLength::Rem(v) => FontRelativeLength::Rem(v * scalar),
}
}