Skip to content

Commit

Permalink
style: Add support for parsing of the CSS text-underline-position pro…
Browse files Browse the repository at this point in the history
…perty.

Differential Revision: https://phabricator.services.mozilla.com/D54722
  • Loading branch information
jfkthame authored and emilio committed Dec 15, 2019
1 parent 3bd62cf commit 51c1dfe
Show file tree
Hide file tree
Showing 7 changed files with 113 additions and 2 deletions.
4 changes: 2 additions & 2 deletions components/style/properties/counted_unknown_properties.py
Expand Up @@ -10,7 +10,8 @@
# "offset-distance",
# "offset-path",
# "offset-rotate",
# "offset"
# "offset",
# "text-underline-position",
COUNTED_UNKNOWN_PROPERTIES = [
"-webkit-font-smoothing",
"-webkit-tap-highlight-color",
Expand Down Expand Up @@ -40,7 +41,6 @@
"baseline-shift",
"-webkit-hyphenate-character",
"page",
"text-underline-position",
"-webkit-highlight",
"background-repeat-x",
"-webkit-padding-end",
Expand Down
1 change: 1 addition & 0 deletions components/style/properties/data.py
Expand Up @@ -385,6 +385,7 @@ def specified_is_copy(self):
"TextDecorationLine",
"TextEmphasisPosition",
"TextTransform",
"TextUnderlinePosition",
"TouchAction",
"TransformStyle",
"UserSelect",
Expand Down
12 changes: 12 additions & 0 deletions components/style/properties/longhands/inherited_text.mako.rs
Expand Up @@ -391,6 +391,18 @@ ${helpers.predefined_type(
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
${helpers.predefined_type(
"text-decoration-skip-ink",
Expand Down
1 change: 1 addition & 0 deletions components/style/values/computed/mod.rs
Expand Up @@ -79,6 +79,7 @@ pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight};
pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing};
pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle};
pub use self::text::{TextDecorationLength, TextDecorationSkipInk};
pub use self::text::TextUnderlinePosition;
pub use self::time::Time;
pub use self::transform::{Rotate, Scale, Transform, TransformOperation};
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
Expand Down
1 change: 1 addition & 0 deletions components/style/values/computed/text.rs
Expand Up @@ -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::{TextDecorationLine, TextEmphasisPosition};
pub use crate::values::specified::{TextDecorationSkipInk, TextTransform};
pub use crate::values::specified::TextUnderlinePosition;

/// A computed value for the `initial-letter` property.
pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>;
Expand Down
1 change: 1 addition & 0 deletions components/style/values/specified/mod.rs
Expand Up @@ -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::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
pub use self::text::{TextDecorationLength, TextDecorationSkipInk, TextTransform};
pub use self::text::TextUnderlinePosition;
pub use self::time::Time;
pub use self::transform::{Rotate, Scale, Transform};
pub use self::transform::{TransformOrigin, TransformStyle, Translate};
Expand Down
95 changes: 95 additions & 0 deletions components/style/values/specified/text.rs
Expand Up @@ -1054,3 +1054,98 @@ impl TextDecorationLength {
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(())
}
}

0 comments on commit 51c1dfe

Please sign in to comment.