mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
style: Use cbindgen for text-decoration-line.
Differential Revision: https://phabricator.services.mozilla.com/D23412
This commit is contained in:
parent
4b07af2240
commit
b0af565656
6 changed files with 110 additions and 158 deletions
|
@ -105,6 +105,7 @@ include = [
|
||||||
"WordBreak",
|
"WordBreak",
|
||||||
"Contain",
|
"Contain",
|
||||||
"RestyleHint",
|
"RestyleHint",
|
||||||
|
"TextDecorationLine",
|
||||||
]
|
]
|
||||||
item_types = ["enums", "structs", "typedefs"]
|
item_types = ["enums", "structs", "typedefs"]
|
||||||
|
|
||||||
|
|
|
@ -3996,9 +3996,7 @@ fn static_assert() {
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="Text"
|
<%self:impl_trait style_struct_name="Text"
|
||||||
skip_longhands="text-decoration-line text-overflow initial-letter">
|
skip_longhands="text-overflow initial-letter">
|
||||||
|
|
||||||
${impl_simple_type_with_conversion("text_decoration_line")}
|
|
||||||
|
|
||||||
fn clear_overflow_sides_if_string(&mut self) {
|
fn clear_overflow_sides_if_string(&mut self) {
|
||||||
use crate::gecko_bindings::structs::nsStyleTextOverflowSide;
|
use crate::gecko_bindings::structs::nsStyleTextOverflowSide;
|
||||||
|
@ -4112,21 +4110,6 @@ fn static_assert() {
|
||||||
InitialLetter::Specified(self.gecko.mInitialLetterSize, Some(self.gecko.mInitialLetterSink))
|
InitialLetter::Specified(self.gecko.mInitialLetterSize, Some(self.gecko.mInitialLetterSink))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn has_underline(&self) -> bool {
|
|
||||||
(self.gecko.mTextDecorationLine & (structs::NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE as u8)) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn has_overline(&self) -> bool {
|
|
||||||
(self.gecko.mTextDecorationLine & (structs::NS_STYLE_TEXT_DECORATION_LINE_OVERLINE as u8)) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn has_line_through(&self) -> bool {
|
|
||||||
(self.gecko.mTextDecorationLine & (structs::NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH as u8)) != 0
|
|
||||||
}
|
|
||||||
</%self:impl_trait>
|
</%self:impl_trait>
|
||||||
|
|
||||||
// Set SVGPathData to StyleShapeSource.
|
// Set SVGPathData to StyleShapeSource.
|
||||||
|
|
|
@ -5,16 +5,7 @@
|
||||||
<%namespace name="helpers" file="/helpers.mako.rs" />
|
<%namespace name="helpers" file="/helpers.mako.rs" />
|
||||||
<% from data import Method %>
|
<% from data import Method %>
|
||||||
|
|
||||||
<% data.new_style_struct(
|
<% data.new_style_struct("Text", inherited=False, gecko_name="TextReset") %>
|
||||||
"Text",
|
|
||||||
inherited=False,
|
|
||||||
gecko_name="TextReset",
|
|
||||||
additional_methods=[
|
|
||||||
Method("has_underline", "bool"),
|
|
||||||
Method("has_overline", "bool"),
|
|
||||||
Method("has_line_through", "bool"),
|
|
||||||
]
|
|
||||||
) %>
|
|
||||||
|
|
||||||
${helpers.predefined_type(
|
${helpers.predefined_type(
|
||||||
"text-overflow",
|
"text-overflow",
|
||||||
|
|
|
@ -2638,24 +2638,6 @@ pub mod style_structs {
|
||||||
use crate::Zero;
|
use crate::Zero;
|
||||||
!self.outline_width.is_zero()
|
!self.outline_width.is_zero()
|
||||||
}
|
}
|
||||||
% elif style_struct.name == "Text":
|
|
||||||
/// Whether the text decoration has an underline.
|
|
||||||
#[inline]
|
|
||||||
pub fn has_underline(&self) -> bool {
|
|
||||||
self.text_decoration_line.contains(longhands::text_decoration_line::SpecifiedValue::UNDERLINE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether the text decoration has an overline.
|
|
||||||
#[inline]
|
|
||||||
pub fn has_overline(&self) -> bool {
|
|
||||||
self.text_decoration_line.contains(longhands::text_decoration_line::SpecifiedValue::OVERLINE)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether the text decoration has a line through.
|
|
||||||
#[inline]
|
|
||||||
pub fn has_line_through(&self) -> bool {
|
|
||||||
self.text_decoration_line.contains(longhands::text_decoration_line::SpecifiedValue::LINE_THROUGH)
|
|
||||||
}
|
|
||||||
% elif style_struct.name == "Box":
|
% elif style_struct.name == "Box":
|
||||||
/// Sets the display property, but without touching original_display,
|
/// Sets the display property, but without touching original_display,
|
||||||
/// except when the adjustment comes from root or item display fixups.
|
/// except when the adjustment comes from root or item display fixups.
|
||||||
|
|
|
@ -19,7 +19,7 @@ use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ToCss};
|
use style_traits::{CssWriter, ToCss};
|
||||||
|
|
||||||
pub use crate::values::specified::TextAlignKeyword as TextAlign;
|
pub use crate::values::specified::TextAlignKeyword as TextAlign;
|
||||||
pub use crate::values::specified::TextEmphasisPosition;
|
pub use crate::values::specified::{TextEmphasisPosition, TextDecorationLine};
|
||||||
pub use crate::values::specified::{OverflowWrap, WordBreak};
|
pub use crate::values::specified::{OverflowWrap, WordBreak};
|
||||||
|
|
||||||
/// A computed value for the `initial-letter` property.
|
/// A computed value for the `initial-letter` property.
|
||||||
|
@ -182,11 +182,11 @@ impl TextDecorationsInEffect {
|
||||||
.clone(),
|
.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let text_style = style.get_text();
|
let line = style.get_text().clone_text_decoration_line();
|
||||||
|
|
||||||
result.underline |= text_style.has_underline();
|
result.underline |= line.contains(TextDecorationLine::UNDERLINE);
|
||||||
result.overline |= text_style.has_overline();
|
result.overline |= line.contains(TextDecorationLine::OVERLINE);
|
||||||
result.line_through |= text_style.has_line_through();
|
result.line_through |= line.contains(TextDecorationLine::LINE_THROUGH);
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,7 @@ use cssparser::{Parser, Token};
|
||||||
use selectors::parser::SelectorParseErrorKind;
|
use selectors::parser::SelectorParseErrorKind;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::values::SequenceWriter;
|
use style_traits::values::SequenceWriter;
|
||||||
use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
|
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||||
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
|
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
/// A specified type for the `initial-letter` property.
|
/// A specified type for the `initial-letter` property.
|
||||||
|
@ -255,119 +254,115 @@ impl ToComputedValue for TextOverflow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_text_decoration_line {
|
bitflags! {
|
||||||
{
|
#[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue)]
|
||||||
$(
|
#[value_info(other_values = "none,underline,overline,line-through,blink")]
|
||||||
$(#[$($meta:tt)+])*
|
#[repr(C)]
|
||||||
$ident:ident / $css:expr => $value:expr,
|
/// Specified keyword values for the text-decoration-line property.
|
||||||
)+
|
pub struct TextDecorationLine: u8 {
|
||||||
} => {
|
/// No text decoration line is specified.
|
||||||
bitflags! {
|
const NONE = 0;
|
||||||
#[derive(MallocSizeOf, ToComputedValue)]
|
/// underline
|
||||||
/// Specified keyword values for the text-decoration-line property.
|
const UNDERLINE = 1 << 0;
|
||||||
pub struct TextDecorationLine: u8 {
|
/// overline
|
||||||
/// No text decoration line is specified
|
const OVERLINE = 1 << 1;
|
||||||
const NONE = 0;
|
/// line-through
|
||||||
$(
|
const LINE_THROUGH = 1 << 2;
|
||||||
$(#[$($meta)+])*
|
/// blink
|
||||||
const $ident = $value;
|
const BLINK = 1 << 3;
|
||||||
)+
|
/// Only set by presentation attributes
|
||||||
#[cfg(feature = "gecko")]
|
///
|
||||||
/// Only set by presentation attributes
|
/// Setting this will mean that text-decorations use the color
|
||||||
///
|
/// specified by `color` in quirks mode.
|
||||||
/// Setting this will mean that text-decorations use the color
|
///
|
||||||
/// specified by `color` in quirks mode.
|
/// For example, this gives <a href=foo><font color="red">text</font></a>
|
||||||
///
|
/// a red text decoration
|
||||||
/// For example, this gives <a href=foo><font color="red">text</font></a>
|
#[cfg(feature = "gecko")]
|
||||||
/// a red text decoration
|
const COLOR_OVERRIDE = 0x10;
|
||||||
const COLOR_OVERRIDE = 0x10;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Parse for TextDecorationLine {
|
||||||
|
/// none | [ underline || overline || line-through || blink ]
|
||||||
|
fn parse<'i, 't>(
|
||||||
|
_context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
let mut result = TextDecorationLine::empty();
|
||||||
|
|
||||||
|
// NOTE(emilio): this loop has this weird structure because we run this
|
||||||
|
// code to parse the text-decoration shorthand as well, so we need to
|
||||||
|
// ensure we don't return an error if we don't consume the whole thing
|
||||||
|
// because we find an invalid identifier or other kind of token.
|
||||||
|
loop {
|
||||||
|
let flag: Result<_, ParseError<'i>> = input.try(|input| {
|
||||||
|
let flag = try_match_ident_ignore_ascii_case! { input,
|
||||||
|
"none" if result.is_empty() => TextDecorationLine::NONE,
|
||||||
|
"underline" => TextDecorationLine::UNDERLINE,
|
||||||
|
"overline" => TextDecorationLine::OVERLINE,
|
||||||
|
"line-through" => TextDecorationLine::LINE_THROUGH,
|
||||||
|
"blink" => TextDecorationLine::BLINK,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(flag)
|
||||||
|
});
|
||||||
|
|
||||||
|
let flag = match flag {
|
||||||
|
Ok(flag) => flag,
|
||||||
|
Err(..) => break,
|
||||||
|
};
|
||||||
|
|
||||||
|
if flag.is_empty() {
|
||||||
|
return Ok(TextDecorationLine::NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if result.contains(flag) {
|
||||||
|
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||||
|
}
|
||||||
|
|
||||||
|
result.insert(flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for TextDecorationLine {
|
if !result.is_empty() {
|
||||||
/// none | [ underline || overline || line-through || blink ]
|
Ok(result)
|
||||||
fn parse<'i, 't>(
|
} else {
|
||||||
_context: &ParserContext,
|
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||||
input: &mut Parser<'i, 't>,
|
|
||||||
) -> Result<TextDecorationLine, ParseError<'i>> {
|
|
||||||
let mut result = TextDecorationLine::NONE;
|
|
||||||
if input
|
|
||||||
.try(|input| input.expect_ident_matching("none"))
|
|
||||||
.is_ok()
|
|
||||||
{
|
|
||||||
return Ok(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let result = input.try(|input| {
|
|
||||||
let ident = input.expect_ident().map_err(|_| ())?;
|
|
||||||
match_ignore_ascii_case! { ident,
|
|
||||||
$(
|
|
||||||
$css => {
|
|
||||||
if result.contains(TextDecorationLine::$ident) {
|
|
||||||
Err(())
|
|
||||||
} else {
|
|
||||||
result.insert(TextDecorationLine::$ident);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)+
|
|
||||||
_ => Err(()),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if result.is_err() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !result.is_empty() {
|
|
||||||
Ok(result)
|
|
||||||
} else {
|
|
||||||
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCss for TextDecorationLine {
|
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
|
||||||
where
|
|
||||||
W: Write,
|
|
||||||
{
|
|
||||||
if self.is_empty() {
|
|
||||||
return dest.write_str("none");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut writer = SequenceWriter::new(dest, " ");
|
|
||||||
$(
|
|
||||||
if self.contains(TextDecorationLine::$ident) {
|
|
||||||
writer.raw_item($css)?;
|
|
||||||
}
|
|
||||||
)+
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SpecifiedValueInfo for TextDecorationLine {
|
|
||||||
fn collect_completion_keywords(f: KeywordsCollectFn) {
|
|
||||||
f(&["none", $($css,)+]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_text_decoration_line! {
|
impl ToCss for TextDecorationLine {
|
||||||
/// Underline
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
UNDERLINE / "underline" => 1 << 0,
|
where
|
||||||
/// Overline
|
W: Write,
|
||||||
OVERLINE / "overline" => 1 << 1,
|
{
|
||||||
/// Line through
|
if self.is_empty() {
|
||||||
LINE_THROUGH / "line-through" => 1 << 2,
|
return dest.write_str("none");
|
||||||
/// Blink
|
}
|
||||||
BLINK / "blink" => 1 << 3,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
let mut writer = SequenceWriter::new(dest, " ");
|
||||||
impl_bitflags_conversions!(TextDecorationLine);
|
let mut any = false;
|
||||||
|
|
||||||
|
macro_rules! maybe_write {
|
||||||
|
($ident:ident => $str:expr) => {
|
||||||
|
if self.contains(TextDecorationLine::$ident) {
|
||||||
|
any = true;
|
||||||
|
writer.raw_item($str)?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_write!(UNDERLINE => "underline");
|
||||||
|
maybe_write!(OVERLINE => "overline");
|
||||||
|
maybe_write!(LINE_THROUGH => "line-through");
|
||||||
|
maybe_write!(BLINK => "blink");
|
||||||
|
|
||||||
|
debug_assert!(any || *self == TextDecorationLine::COLOR_OVERRIDE);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TextDecorationLine {
|
impl TextDecorationLine {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue