mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
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.
This commit is contained in:
parent
61f872e7da
commit
6785c57c78
5 changed files with 68 additions and 8 deletions
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ pub enum MinMaxOp {
|
|||
pub enum SortKey {
|
||||
Number,
|
||||
Percentage,
|
||||
Cap,
|
||||
Ch,
|
||||
Deg,
|
||||
Em,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue