mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-19 08:15:31 +00:00
Bug 770780 - Add support for parsing of the CSS text-underline-position property. r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D54722 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
03dfefdf7e
commit
3b87f01682
@ -153,6 +153,7 @@ exports.ANIMATION_TYPE_FOR_LONGHANDS = [
|
||||
"-moz-text-size-adjust",
|
||||
"-webkit-text-stroke-width",
|
||||
"text-transform",
|
||||
"text-underline-position",
|
||||
"touch-action",
|
||||
"transform-box",
|
||||
"transform-style",
|
||||
|
@ -3206,6 +3206,7 @@ exports.CSS_PROPERTIES = {
|
||||
"text-rendering",
|
||||
"-moz-control-character-visibility",
|
||||
"text-underline-offset",
|
||||
"text-underline-position",
|
||||
"text-decoration-skip-ink",
|
||||
"cursor",
|
||||
"pointer-events",
|
||||
@ -10865,6 +10866,10 @@ exports.PREFERENCES = [
|
||||
"text-justify",
|
||||
"layout.css.text-justify.enabled"
|
||||
],
|
||||
[
|
||||
"text-underline-position",
|
||||
"layout.css.text-underline-position.enabled"
|
||||
],
|
||||
[
|
||||
"touch-action",
|
||||
"layout.css.touch_action.enabled"
|
||||
|
@ -56,6 +56,7 @@ hide-types = [
|
||||
bitfield-enums = [
|
||||
"nsChangeHint",
|
||||
"mozilla::OriginFlags",
|
||||
"mozilla::StyleTextUnderlinePosition",
|
||||
]
|
||||
rusty-enums = [
|
||||
"nsCompatibility",
|
||||
@ -479,6 +480,7 @@ cbindgen-types = [
|
||||
{ gecko = "StyleWillChange", servo = "values::specified::box_::WillChange" },
|
||||
{ gecko = "StyleTextDecorationLine", servo = "values::computed::TextDecorationLine" },
|
||||
{ gecko = "StyleTextTransform", servo = "values::computed::TextTransform" },
|
||||
{ gecko = "StyleTextUnderlinePosition", servo = "values::computed::TextUnderlinePosition" },
|
||||
{ gecko = "StyleMozListReversed", servo = "values::computed::MozListReversed" },
|
||||
{ gecko = "StyleOwned", servo = "gecko_bindings::sugar::ownership::Owned" },
|
||||
{ gecko = "StyleOwnedOrNull", servo = "gecko_bindings::sugar::ownership::OwnedOrNull" },
|
||||
|
@ -3426,6 +3426,7 @@ nsStyleText::nsStyleText(const Document& aDocument)
|
||||
mTextIndent(LengthPercentage::Zero()),
|
||||
mTextUnderlineOffset(StyleTextDecorationLength::Auto()),
|
||||
mTextDecorationSkipInk(StyleTextDecorationSkipInk::Auto),
|
||||
mTextUnderlinePosition(StyleTextUnderlinePosition::Auto()),
|
||||
mWebkitTextStrokeWidth(0),
|
||||
mTextEmphasisStyle(StyleTextEmphasisStyle::None()) {
|
||||
MOZ_COUNT_CTOR(nsStyleText);
|
||||
@ -3464,6 +3465,7 @@ nsStyleText::nsStyleText(const nsStyleText& aSource)
|
||||
mTextIndent(aSource.mTextIndent),
|
||||
mTextUnderlineOffset(aSource.mTextUnderlineOffset),
|
||||
mTextDecorationSkipInk(aSource.mTextDecorationSkipInk),
|
||||
mTextUnderlinePosition(aSource.mTextUnderlinePosition),
|
||||
mWebkitTextStrokeWidth(aSource.mWebkitTextStrokeWidth),
|
||||
mTextShadow(aSource.mTextShadow),
|
||||
mTextEmphasisStyle(aSource.mTextEmphasisStyle) {
|
||||
@ -3524,7 +3526,8 @@ nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aNewData) const {
|
||||
|
||||
if (mTextShadow != aNewData.mTextShadow ||
|
||||
mTextEmphasisStyle != aNewData.mTextEmphasisStyle ||
|
||||
mWebkitTextStrokeWidth != aNewData.mWebkitTextStrokeWidth) {
|
||||
mWebkitTextStrokeWidth != aNewData.mWebkitTextStrokeWidth ||
|
||||
mTextUnderlinePosition != aNewData.mTextUnderlinePosition) {
|
||||
hint |= nsChangeHint_UpdateSubtreeOverflow | nsChangeHint_SchedulePaint |
|
||||
nsChangeHint_RepaintFrame;
|
||||
|
||||
|
@ -1166,6 +1166,7 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText {
|
||||
|
||||
mozilla::StyleTextDecorationLength mTextUnderlineOffset;
|
||||
mozilla::StyleTextDecorationSkipInk mTextDecorationSkipInk;
|
||||
mozilla::StyleTextUnderlinePosition mTextUnderlinePosition;
|
||||
|
||||
nscoord mWebkitTextStrokeWidth; // coord
|
||||
|
||||
@ -1290,6 +1291,22 @@ inline StyleTextTransform StyleTextTransform::None() {
|
||||
|
||||
inline bool StyleTextTransform::IsNone() const { return *this == None(); }
|
||||
|
||||
inline StyleTextUnderlinePosition StyleTextUnderlinePosition::Auto() {
|
||||
return StyleTextUnderlinePosition_AUTO;
|
||||
}
|
||||
inline bool StyleTextUnderlinePosition::IsAuto() const {
|
||||
return *this == Auto();
|
||||
}
|
||||
inline bool StyleTextUnderlinePosition::IsUnder() const {
|
||||
return bool(*this & StyleTextUnderlinePosition_UNDER);
|
||||
}
|
||||
inline bool StyleTextUnderlinePosition::IsLeft() const {
|
||||
return bool(*this & StyleTextUnderlinePosition_LEFT);
|
||||
}
|
||||
inline bool StyleTextUnderlinePosition::IsRight() const {
|
||||
return bool(*this & StyleTextUnderlinePosition_RIGHT);
|
||||
}
|
||||
|
||||
struct StyleTransition {
|
||||
StyleTransition() { /* leaves uninitialized; see also SetInitialValues */
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ prefs =
|
||||
layout.css.overflow-logical.enabled=true
|
||||
layout.css.step-position-jump.enabled=true
|
||||
layout.css.text-underline-offset.enabled=true
|
||||
layout.css.text-underline-position.enabled=true
|
||||
layout.css.text-decoration-thickness.enabled=true
|
||||
layout.css.backdrop-filter.enabled=true
|
||||
layout.css.text-decoration-skip-ink.enabled=true
|
||||
|
@ -7757,6 +7757,34 @@ var gCSSProperties = {
|
||||
"from font",
|
||||
],
|
||||
},
|
||||
"text-underline-position": {
|
||||
domProp: "textUnderlinePosition",
|
||||
inherited: true,
|
||||
type: CSS_TYPE_LONGHAND,
|
||||
applies_to_first_letter: true,
|
||||
applies_to_first_line: true,
|
||||
applies_to_placeholder: true,
|
||||
initial_values: ["auto"],
|
||||
other_values: [
|
||||
"under",
|
||||
"left",
|
||||
"right",
|
||||
"left under",
|
||||
"under left",
|
||||
"right under",
|
||||
"under right",
|
||||
],
|
||||
invalid_values: [
|
||||
"none",
|
||||
"auto under",
|
||||
"left right",
|
||||
"right auto",
|
||||
"0",
|
||||
"1px",
|
||||
"10%",
|
||||
"from-font",
|
||||
],
|
||||
},
|
||||
"text-emphasis": {
|
||||
domProp: "textEmphasis",
|
||||
inherited: true,
|
||||
|
@ -4853,6 +4853,12 @@
|
||||
value: true
|
||||
mirror: always
|
||||
|
||||
# text underline position
|
||||
- name: layout.css.text-underline-position.enabled
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# text decoration thickness
|
||||
- name: layout.css.text-decoration-thickness.enabled
|
||||
type: bool
|
||||
|
@ -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",
|
||||
@ -40,7 +41,6 @@ COUNTED_UNKNOWN_PROPERTIES = [
|
||||
"baseline-shift",
|
||||
"-webkit-hyphenate-character",
|
||||
"page",
|
||||
"text-underline-position",
|
||||
"-webkit-highlight",
|
||||
"background-repeat-x",
|
||||
"-webkit-padding-end",
|
||||
|
@ -385,6 +385,7 @@ class Longhand(object):
|
||||
"TextDecorationLine",
|
||||
"TextEmphasisPosition",
|
||||
"TextTransform",
|
||||
"TextUnderlinePosition",
|
||||
"TouchAction",
|
||||
"TransformStyle",
|
||||
"UserSelect",
|
||||
|
@ -392,6 +392,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",
|
||||
|
@ -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};
|
||||
|
@ -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>;
|
||||
|
@ -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};
|
||||
|
@ -1053,3 +1053,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(())
|
||||
}
|
||||
}
|
||||
|
@ -130,6 +130,7 @@ include = [
|
||||
"TouchAction",
|
||||
"WillChange",
|
||||
"TextDecorationLine",
|
||||
"TextUnderlinePosition",
|
||||
"TextTransform",
|
||||
"TextOverflow",
|
||||
"MozListReversed",
|
||||
@ -338,6 +339,14 @@ renaming_overrides_prefixing = true
|
||||
inline bool IsNone() const;
|
||||
"""
|
||||
|
||||
"TextUnderlinePosition" = """
|
||||
static inline StyleTextUnderlinePosition Auto();
|
||||
inline bool IsAuto() const;
|
||||
inline bool IsUnder() const;
|
||||
inline bool IsLeft() const;
|
||||
inline bool IsRight() const;
|
||||
"""
|
||||
|
||||
# TODO(emilio): Add hooks to cbindgen to be able to generate MOZ_MUST_USE_TYPE
|
||||
# or MOZ_MUST_USE on the functions.
|
||||
"Owned" = """
|
||||
|
@ -1,4 +1,5 @@
|
||||
[first-letter-property-whitelist.html]
|
||||
prefs: [layout.css.text-underline-position.enabled:true]
|
||||
[Whitelisted property backgroundPosition should be applied to first-letter pseudo elements.]
|
||||
expected: FAIL
|
||||
|
||||
@ -31,6 +32,3 @@
|
||||
[Whitelisted property textJustify should be applied to first-letter pseudo elements.]
|
||||
expected: FAIL
|
||||
|
||||
[Whitelisted property textUnderlinePosition should be applied to first-letter pseudo elements.]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -1,8 +1,2 @@
|
||||
[inheritance.html]
|
||||
prefs: [layout.css.text-decoration-skip-ink.enabled:true]
|
||||
[Property text-underline-position has initial value auto]
|
||||
expected: FAIL
|
||||
|
||||
[Property text-underline-position inherits]
|
||||
expected: FAIL
|
||||
|
||||
prefs: [layout.css.text-decoration-skip-ink.enabled:true, layout.css.text-underline-position.enabled:true]
|
||||
|
@ -1,16 +1,2 @@
|
||||
[text-underline-position-computed.html]
|
||||
[Property text-underline-position value 'under left' computes to 'under left']
|
||||
expected: FAIL
|
||||
|
||||
[Property text-underline-position value 'under' computes to 'under']
|
||||
expected: FAIL
|
||||
|
||||
[Property text-underline-position value 'right' computes to 'right']
|
||||
expected: FAIL
|
||||
|
||||
[Property text-underline-position value 'left' computes to 'left']
|
||||
expected: FAIL
|
||||
|
||||
[Property text-underline-position value 'auto' computes to 'auto']
|
||||
expected: FAIL
|
||||
|
||||
prefs: [layout.css.text-underline-position.enabled:true]
|
||||
|
@ -1,19 +1,2 @@
|
||||
[text-underline-position-valid.html]
|
||||
[e.style['text-underline-position'\] = "right under" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['text-underline-position'\] = "under left" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['text-underline-position'\] = "auto" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['text-underline-position'\] = "left" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['text-underline-position'\] = "right" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
[e.style['text-underline-position'\] = "under" should set the property value]
|
||||
expected: FAIL
|
||||
|
||||
prefs: [layout.css.text-underline-position.enabled:true]
|
||||
|
Loading…
Reference in New Issue
Block a user