mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
style: Add support for parsing of the CSS text-underline-position property.
Differential Revision: https://phabricator.services.mozilla.com/D54722
This commit is contained in:
parent
3bd62cf0cd
commit
51c1dfee2d
7 changed files with 113 additions and 2 deletions
|
@ -10,7 +10,8 @@
|
||||||
# "offset-distance",
|
# "offset-distance",
|
||||||
# "offset-path",
|
# "offset-path",
|
||||||
# "offset-rotate",
|
# "offset-rotate",
|
||||||
# "offset"
|
# "offset",
|
||||||
|
# "text-underline-position",
|
||||||
COUNTED_UNKNOWN_PROPERTIES = [
|
COUNTED_UNKNOWN_PROPERTIES = [
|
||||||
"-webkit-font-smoothing",
|
"-webkit-font-smoothing",
|
||||||
"-webkit-tap-highlight-color",
|
"-webkit-tap-highlight-color",
|
||||||
|
@ -40,7 +41,6 @@ COUNTED_UNKNOWN_PROPERTIES = [
|
||||||
"baseline-shift",
|
"baseline-shift",
|
||||||
"-webkit-hyphenate-character",
|
"-webkit-hyphenate-character",
|
||||||
"page",
|
"page",
|
||||||
"text-underline-position",
|
|
||||||
"-webkit-highlight",
|
"-webkit-highlight",
|
||||||
"background-repeat-x",
|
"background-repeat-x",
|
||||||
"-webkit-padding-end",
|
"-webkit-padding-end",
|
||||||
|
|
|
@ -385,6 +385,7 @@ class Longhand(object):
|
||||||
"TextDecorationLine",
|
"TextDecorationLine",
|
||||||
"TextEmphasisPosition",
|
"TextEmphasisPosition",
|
||||||
"TextTransform",
|
"TextTransform",
|
||||||
|
"TextUnderlinePosition",
|
||||||
"TouchAction",
|
"TouchAction",
|
||||||
"TransformStyle",
|
"TransformStyle",
|
||||||
"UserSelect",
|
"UserSelect",
|
||||||
|
|
|
@ -391,6 +391,18 @@ ${helpers.predefined_type(
|
||||||
spec="https://drafts.csswg.org/css-text-decor-4/#underline-offset",
|
spec="https://drafts.csswg.org/css-text-decor-4/#underline-offset",
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
// text underline position
|
||||||
|
${helpers.predefined_type(
|
||||||
|
"text-underline-position",
|
||||||
|
"TextUnderlinePosition",
|
||||||
|
"computed::TextUnderlinePosition::AUTO",
|
||||||
|
engines="gecko",
|
||||||
|
animation_value_type="discrete",
|
||||||
|
gecko_pref="layout.css.text-underline-position.enabled",
|
||||||
|
has_effect_on_gecko_scrollbars=False,
|
||||||
|
spec="https://drafts.csswg.org/css-text-decor-3/#text-underline-position-property",
|
||||||
|
)}
|
||||||
|
|
||||||
// text decoration skip ink
|
// text decoration skip ink
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"text-decoration-skip-ink",
|
"text-decoration-skip-ink",
|
||||||
|
|
|
@ -79,6 +79,7 @@ pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight};
|
||||||
pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing};
|
pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing};
|
||||||
pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle};
|
pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle};
|
||||||
pub use self::text::{TextDecorationLength, TextDecorationSkipInk};
|
pub use self::text::{TextDecorationLength, TextDecorationSkipInk};
|
||||||
|
pub use self::text::TextUnderlinePosition;
|
||||||
pub use self::time::Time;
|
pub use self::time::Time;
|
||||||
pub use self::transform::{Rotate, Scale, Transform, TransformOperation};
|
pub use self::transform::{Rotate, Scale, Transform, TransformOperation};
|
||||||
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
|
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
|
||||||
|
|
|
@ -22,6 +22,7 @@ pub use crate::values::specified::TextAlignKeyword as TextAlign;
|
||||||
pub use crate::values::specified::{LineBreak, OverflowWrap, WordBreak};
|
pub use crate::values::specified::{LineBreak, OverflowWrap, WordBreak};
|
||||||
pub use crate::values::specified::{TextDecorationLine, TextEmphasisPosition};
|
pub use crate::values::specified::{TextDecorationLine, TextEmphasisPosition};
|
||||||
pub use crate::values::specified::{TextDecorationSkipInk, TextTransform};
|
pub use crate::values::specified::{TextDecorationSkipInk, TextTransform};
|
||||||
|
pub use crate::values::specified::TextUnderlinePosition;
|
||||||
|
|
||||||
/// A computed value for the `initial-letter` property.
|
/// A computed value for the `initial-letter` property.
|
||||||
pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
|
pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
|
||||||
|
|
|
@ -84,6 +84,7 @@ pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight, TextAl
|
||||||
pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle, WordBreak};
|
pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle, WordBreak};
|
||||||
pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
|
pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
|
||||||
pub use self::text::{TextDecorationLength, TextDecorationSkipInk, TextTransform};
|
pub use self::text::{TextDecorationLength, TextDecorationSkipInk, TextTransform};
|
||||||
|
pub use self::text::TextUnderlinePosition;
|
||||||
pub use self::time::Time;
|
pub use self::time::Time;
|
||||||
pub use self::transform::{Rotate, Scale, Transform};
|
pub use self::transform::{Rotate, Scale, Transform};
|
||||||
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
|
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
|
||||||
|
|
|
@ -1054,3 +1054,98 @@ impl TextDecorationLength {
|
||||||
matches!(*self, GenericTextDecorationLength::Auto)
|
matches!(*self, GenericTextDecorationLength::Auto)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)]
|
||||||
|
#[value_info(other_values = "auto,under,left,right")]
|
||||||
|
#[repr(C)]
|
||||||
|
/// Specified keyword values for the text-underline-position property.
|
||||||
|
/// (Non-exclusive, but not all combinations are allowed: only `under` may occur
|
||||||
|
/// together with either `left` or `right`.)
|
||||||
|
/// https://drafts.csswg.org/css-text-decor-3/#text-underline-position-property
|
||||||
|
pub struct TextUnderlinePosition: u8 {
|
||||||
|
/// Use automatic positioning below the alphabetic baseline.
|
||||||
|
const AUTO = 0;
|
||||||
|
/// Below the glyph box.
|
||||||
|
const UNDER = 1 << 0;
|
||||||
|
/// In vertical mode, place to the left of the text.
|
||||||
|
const LEFT = 1 << 1;
|
||||||
|
/// In vertical mode, place to the right of the text.
|
||||||
|
const RIGHT = 1 << 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for TextUnderlinePosition {
|
||||||
|
fn parse<'i, 't>(
|
||||||
|
_context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
) -> Result<TextUnderlinePosition, ParseError<'i>> {
|
||||||
|
let mut result = TextUnderlinePosition::empty();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let location = input.current_source_location();
|
||||||
|
let ident = match input.next() {
|
||||||
|
Ok(&Token::Ident(ref ident)) => ident,
|
||||||
|
Ok(other) => return Err(location.new_unexpected_token_error(other.clone())),
|
||||||
|
Err(..) => break,
|
||||||
|
};
|
||||||
|
|
||||||
|
match_ignore_ascii_case! { ident,
|
||||||
|
"auto" if result.is_empty() => {
|
||||||
|
return Ok(result);
|
||||||
|
},
|
||||||
|
"under" if !result.intersects(TextUnderlinePosition::UNDER) => {
|
||||||
|
result.insert(TextUnderlinePosition::UNDER);
|
||||||
|
},
|
||||||
|
"left" if !result.intersects(TextUnderlinePosition::LEFT |
|
||||||
|
TextUnderlinePosition::RIGHT) => {
|
||||||
|
result.insert(TextUnderlinePosition::LEFT);
|
||||||
|
},
|
||||||
|
"right" if !result.intersects(TextUnderlinePosition::LEFT |
|
||||||
|
TextUnderlinePosition::RIGHT) => {
|
||||||
|
result.insert(TextUnderlinePosition::RIGHT);
|
||||||
|
},
|
||||||
|
_ => return Err(location.new_custom_error(
|
||||||
|
SelectorParseErrorKind::UnexpectedIdent(ident.clone())
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !result.is_empty() {
|
||||||
|
Ok(result)
|
||||||
|
} else {
|
||||||
|
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for TextUnderlinePosition {
|
||||||
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
|
where
|
||||||
|
W: Write,
|
||||||
|
{
|
||||||
|
if self.is_empty() {
|
||||||
|
return dest.write_str("auto");
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut writer = SequenceWriter::new(dest, " ");
|
||||||
|
let mut any = false;
|
||||||
|
|
||||||
|
macro_rules! maybe_write {
|
||||||
|
($ident:ident => $str:expr) => {
|
||||||
|
if self.contains(TextUnderlinePosition::$ident) {
|
||||||
|
any = true;
|
||||||
|
writer.raw_item($str)?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_write!(UNDER => "under");
|
||||||
|
maybe_write!(LEFT => "left");
|
||||||
|
maybe_write!(RIGHT => "right");
|
||||||
|
|
||||||
|
debug_assert!(any);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue