mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Propagate text decoration where needed
This commit is contained in:
parent
83fc9943d3
commit
17948f3b39
9 changed files with 75 additions and 40 deletions
|
@ -133,7 +133,7 @@ impl Fragment {
|
||||||
|
|
||||||
// Underline.
|
// Underline.
|
||||||
if fragment
|
if fragment
|
||||||
.text_decorations_in_effect
|
.text_decoration_line
|
||||||
.contains(TextDecorationLine::UNDERLINE)
|
.contains(TextDecorationLine::UNDERLINE)
|
||||||
{
|
{
|
||||||
let mut rect = rect;
|
let mut rect = rect;
|
||||||
|
@ -144,7 +144,7 @@ impl Fragment {
|
||||||
|
|
||||||
// Overline.
|
// Overline.
|
||||||
if fragment
|
if fragment
|
||||||
.text_decorations_in_effect
|
.text_decoration_line
|
||||||
.contains(TextDecorationLine::OVERLINE)
|
.contains(TextDecorationLine::OVERLINE)
|
||||||
{
|
{
|
||||||
let mut rect = rect;
|
let mut rect = rect;
|
||||||
|
@ -164,7 +164,7 @@ impl Fragment {
|
||||||
|
|
||||||
// Line-through.
|
// Line-through.
|
||||||
if fragment
|
if fragment
|
||||||
.text_decorations_in_effect
|
.text_decoration_line
|
||||||
.contains(TextDecorationLine::LINE_THROUGH)
|
.contains(TextDecorationLine::LINE_THROUGH)
|
||||||
{
|
{
|
||||||
let mut rect = rect;
|
let mut rect = rect;
|
||||||
|
|
|
@ -19,6 +19,7 @@ use servo_arc::Arc;
|
||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::selector_parser::PseudoElement;
|
use style::selector_parser::PseudoElement;
|
||||||
|
use style::values::specified::text::TextDecorationLine;
|
||||||
|
|
||||||
impl BlockFormattingContext {
|
impl BlockFormattingContext {
|
||||||
pub fn construct<'dom>(
|
pub fn construct<'dom>(
|
||||||
|
@ -27,9 +28,16 @@ impl BlockFormattingContext {
|
||||||
style: &Arc<ComputedValues>,
|
style: &Arc<ComputedValues>,
|
||||||
contents: NonReplacedContents,
|
contents: NonReplacedContents,
|
||||||
content_sizes: ContentSizesRequest,
|
content_sizes: ContentSizesRequest,
|
||||||
|
propagated_text_decoration_line: TextDecorationLine,
|
||||||
) -> (Self, BoxContentSizes) {
|
) -> (Self, BoxContentSizes) {
|
||||||
let (contents, contains_floats, inline_content_sizes) =
|
let (contents, contains_floats, inline_content_sizes) = BlockContainer::construct(
|
||||||
BlockContainer::construct(context, node, style, contents, content_sizes);
|
context,
|
||||||
|
node,
|
||||||
|
style,
|
||||||
|
contents,
|
||||||
|
content_sizes,
|
||||||
|
propagated_text_decoration_line,
|
||||||
|
);
|
||||||
// FIXME: add contribution to `inline_content_sizes` of floats in this formatting context
|
// FIXME: add contribution to `inline_content_sizes` of floats in this formatting context
|
||||||
// https://dbaron.org/css/intrinsic/#intrinsic
|
// https://dbaron.org/css/intrinsic/#intrinsic
|
||||||
let bfc = Self {
|
let bfc = Self {
|
||||||
|
@ -52,6 +60,7 @@ enum BlockLevelCreator {
|
||||||
Independent {
|
Independent {
|
||||||
display_inside: DisplayInside,
|
display_inside: DisplayInside,
|
||||||
contents: Contents,
|
contents: Contents,
|
||||||
|
propagated_text_decoration_line: TextDecorationLine,
|
||||||
},
|
},
|
||||||
OutOfFlowAbsolutelyPositionedBox {
|
OutOfFlowAbsolutelyPositionedBox {
|
||||||
display_inside: DisplayInside,
|
display_inside: DisplayInside,
|
||||||
|
@ -72,7 +81,7 @@ enum BlockLevelCreator {
|
||||||
/// Deferring allows using rayon’s `into_par_iter`.
|
/// Deferring allows using rayon’s `into_par_iter`.
|
||||||
enum IntermediateBlockContainer {
|
enum IntermediateBlockContainer {
|
||||||
InlineFormattingContext(InlineFormattingContext),
|
InlineFormattingContext(InlineFormattingContext),
|
||||||
Deferred(NonReplacedContents),
|
Deferred(NonReplacedContents, TextDecorationLine),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A builder for a block container.
|
/// A builder for a block container.
|
||||||
|
@ -140,13 +149,16 @@ impl BlockContainer {
|
||||||
block_container_style: &Arc<ComputedValues>,
|
block_container_style: &Arc<ComputedValues>,
|
||||||
contents: NonReplacedContents,
|
contents: NonReplacedContents,
|
||||||
content_sizes: ContentSizesRequest,
|
content_sizes: ContentSizesRequest,
|
||||||
|
propagated_text_decoration_line: TextDecorationLine,
|
||||||
) -> (BlockContainer, ContainsFloats, BoxContentSizes) {
|
) -> (BlockContainer, ContainsFloats, BoxContentSizes) {
|
||||||
|
let text_decoration_line =
|
||||||
|
propagated_text_decoration_line | block_container_style.clone_text_decoration_line();
|
||||||
let mut builder = BlockContainerBuilder {
|
let mut builder = BlockContainerBuilder {
|
||||||
context,
|
context,
|
||||||
root,
|
root,
|
||||||
block_container_style,
|
block_container_style,
|
||||||
block_level_boxes: Vec::new(),
|
block_level_boxes: Vec::new(),
|
||||||
ongoing_inline_formatting_context: InlineFormattingContext::default(),
|
ongoing_inline_formatting_context: InlineFormattingContext::new(text_decoration_line),
|
||||||
ongoing_inline_boxes_stack: Vec::new(),
|
ongoing_inline_boxes_stack: Vec::new(),
|
||||||
anonymous_style: None,
|
anonymous_style: None,
|
||||||
contains_floats: ContainsFloats::No,
|
contains_floats: ContainsFloats::No,
|
||||||
|
@ -439,6 +451,8 @@ where
|
||||||
display_inside,
|
display_inside,
|
||||||
contents,
|
contents,
|
||||||
ContentSizesRequest::inline_if(!style.inline_size_is_length()),
|
ContentSizesRequest::inline_if(!style.inline_size_is_length()),
|
||||||
|
// Text decorations are not propagated to atomic inline-level descendants.
|
||||||
|
TextDecorationLine::NONE,
|
||||||
),
|
),
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
@ -494,6 +508,9 @@ where
|
||||||
.push(ArcRefCell::new(fragmented_inline));
|
.push(ArcRefCell::new(fragmented_inline));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let propagated_text_decoration_line =
|
||||||
|
self.ongoing_inline_formatting_context.text_decoration_line;
|
||||||
|
|
||||||
// We found a block level element, so the ongoing inline formatting
|
// We found a block level element, so the ongoing inline formatting
|
||||||
// context needs to be ended.
|
// context needs to be ended.
|
||||||
self.end_ongoing_inline_formatting_context();
|
self.end_ongoing_inline_formatting_context();
|
||||||
|
@ -501,11 +518,12 @@ where
|
||||||
let kind = match contents.try_into() {
|
let kind = match contents.try_into() {
|
||||||
Ok(contents) => match display_inside {
|
Ok(contents) => match display_inside {
|
||||||
DisplayInside::Flow => BlockLevelCreator::SameFormattingContextBlock(
|
DisplayInside::Flow => BlockLevelCreator::SameFormattingContextBlock(
|
||||||
IntermediateBlockContainer::Deferred(contents),
|
IntermediateBlockContainer::Deferred(contents, propagated_text_decoration_line),
|
||||||
),
|
),
|
||||||
_ => BlockLevelCreator::Independent {
|
_ => BlockLevelCreator::Independent {
|
||||||
display_inside,
|
display_inside,
|
||||||
contents: contents.into(),
|
contents: contents.into(),
|
||||||
|
propagated_text_decoration_line,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Err(contents) => {
|
Err(contents) => {
|
||||||
|
@ -513,6 +531,7 @@ where
|
||||||
BlockLevelCreator::Independent {
|
BlockLevelCreator::Independent {
|
||||||
display_inside,
|
display_inside,
|
||||||
contents,
|
contents,
|
||||||
|
propagated_text_decoration_line,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -680,6 +699,7 @@ where
|
||||||
BlockLevelCreator::Independent {
|
BlockLevelCreator::Independent {
|
||||||
display_inside,
|
display_inside,
|
||||||
contents,
|
contents,
|
||||||
|
propagated_text_decoration_line,
|
||||||
} => {
|
} => {
|
||||||
let content_sizes = ContentSizesRequest::inline_if(
|
let content_sizes = ContentSizesRequest::inline_if(
|
||||||
max_assign_in_flow_outer_content_sizes_to.is_some() &&
|
max_assign_in_flow_outer_content_sizes_to.is_some() &&
|
||||||
|
@ -692,6 +712,7 @@ where
|
||||||
display_inside,
|
display_inside,
|
||||||
contents,
|
contents,
|
||||||
content_sizes,
|
content_sizes,
|
||||||
|
propagated_text_decoration_line,
|
||||||
);
|
);
|
||||||
if let Some(to) = max_assign_in_flow_outer_content_sizes_to {
|
if let Some(to) = max_assign_in_flow_outer_content_sizes_to {
|
||||||
to.max_assign(&contents.content_sizes.outer_inline(&contents.style))
|
to.max_assign(&contents.content_sizes.outer_inline(&contents.style))
|
||||||
|
@ -742,8 +763,15 @@ impl IntermediateBlockContainer {
|
||||||
content_sizes: ContentSizesRequest,
|
content_sizes: ContentSizesRequest,
|
||||||
) -> (BlockContainer, ContainsFloats, BoxContentSizes) {
|
) -> (BlockContainer, ContainsFloats, BoxContentSizes) {
|
||||||
match self {
|
match self {
|
||||||
IntermediateBlockContainer::Deferred(contents) => {
|
IntermediateBlockContainer::Deferred(contents, propagated_text_decoration_line) => {
|
||||||
BlockContainer::construct(context, node, style, contents, content_sizes)
|
BlockContainer::construct(
|
||||||
|
context,
|
||||||
|
node,
|
||||||
|
style,
|
||||||
|
contents,
|
||||||
|
content_sizes,
|
||||||
|
propagated_text_decoration_line,
|
||||||
|
)
|
||||||
},
|
},
|
||||||
IntermediateBlockContainer::InlineFormattingContext(ifc) => {
|
IntermediateBlockContainer::InlineFormattingContext(ifc) => {
|
||||||
let content_sizes = content_sizes.compute(|| ifc.inline_content_sizes(context));
|
let content_sizes = content_sizes.compute(|| ifc.inline_content_sizes(context));
|
||||||
|
|
|
@ -9,6 +9,7 @@ use crate::sizing::ContentSizesRequest;
|
||||||
use crate::style_ext::{ComputedValuesExt, DisplayInside};
|
use crate::style_ext::{ComputedValuesExt, DisplayInside};
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
use style::values::specified::text::TextDecorationLine;
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub(crate) struct FloatBox {
|
pub(crate) struct FloatBox {
|
||||||
|
@ -43,6 +44,8 @@ impl FloatBox {
|
||||||
display_inside,
|
display_inside,
|
||||||
contents,
|
contents,
|
||||||
content_sizes,
|
content_sizes,
|
||||||
|
// Text decorations are not propagated to any out-of-flow descendants
|
||||||
|
TextDecorationLine::NONE,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ use webrender_api::FontInstanceKey;
|
||||||
#[derive(Debug, Default, Serialize)]
|
#[derive(Debug, Default, Serialize)]
|
||||||
pub(crate) struct InlineFormattingContext {
|
pub(crate) struct InlineFormattingContext {
|
||||||
pub(super) inline_level_boxes: Vec<ArcRefCell<InlineLevelBox>>,
|
pub(super) inline_level_boxes: Vec<ArcRefCell<InlineLevelBox>>,
|
||||||
|
pub(super) text_decoration_line: TextDecorationLine,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
|
@ -69,6 +70,11 @@ struct InlineNestingLevelState<'box_tree> {
|
||||||
inline_start: Length,
|
inline_start: Length,
|
||||||
max_block_size_of_fragments_so_far: Length,
|
max_block_size_of_fragments_so_far: Length,
|
||||||
positioning_context: Option<PositioningContext>,
|
positioning_context: Option<PositioningContext>,
|
||||||
|
/// Indicates whether this nesting level have text decorations in effect.
|
||||||
|
/// From https://drafts.csswg.org/css-text-decor/#line-decoration
|
||||||
|
// "When specified on or propagated to a block container that establishes
|
||||||
|
// an IFC..."
|
||||||
|
text_decoration_line: TextDecorationLine,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PartialInlineBoxFragment<'box_tree> {
|
struct PartialInlineBoxFragment<'box_tree> {
|
||||||
|
@ -123,6 +129,13 @@ struct Lines {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineFormattingContext {
|
impl InlineFormattingContext {
|
||||||
|
pub(super) fn new(text_decoration_line: TextDecorationLine) -> InlineFormattingContext {
|
||||||
|
InlineFormattingContext {
|
||||||
|
inline_level_boxes: Default::default(),
|
||||||
|
text_decoration_line,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// This works on an already-constructed `InlineFormattingContext`,
|
// This works on an already-constructed `InlineFormattingContext`,
|
||||||
// Which would have to change if/when
|
// Which would have to change if/when
|
||||||
// `BlockContainer::construct` parallelize their construction.
|
// `BlockContainer::construct` parallelize their construction.
|
||||||
|
@ -257,8 +270,10 @@ impl InlineFormattingContext {
|
||||||
inline_start: Length::zero(),
|
inline_start: Length::zero(),
|
||||||
max_block_size_of_fragments_so_far: Length::zero(),
|
max_block_size_of_fragments_so_far: Length::zero(),
|
||||||
positioning_context: None,
|
positioning_context: None,
|
||||||
|
text_decoration_line: self.text_decoration_line,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if let Some(child) = ifc.current_nesting_level.remaining_boxes.next() {
|
if let Some(child) = ifc.current_nesting_level.remaining_boxes.next() {
|
||||||
match &*child.borrow() {
|
match &*child.borrow() {
|
||||||
|
@ -387,17 +402,6 @@ impl Lines {
|
||||||
};
|
};
|
||||||
self.next_line_block_position += size.block;
|
self.next_line_block_position += size.block;
|
||||||
|
|
||||||
// From https://drafts.csswg.org/css-text-decor/#line-decoration
|
|
||||||
// "When specified on or propagated to an inline box,
|
|
||||||
// that box becomes a decorating box for that decoration,
|
|
||||||
// applying the decoration to all its fragments..."
|
|
||||||
let text_decoration_line = containing_block.style.clone_text_decoration_line();
|
|
||||||
if text_decoration_line != TextDecorationLine::NONE {
|
|
||||||
for fragment in &mut line_contents {
|
|
||||||
fragment.set_text_decorations_in_effect(text_decoration_line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
self.fragments
|
self.fragments
|
||||||
.push(Fragment::Anonymous(AnonymousFragment::new(
|
.push(Fragment::Anonymous(AnonymousFragment::new(
|
||||||
Rect { start_corner, size },
|
Rect { start_corner, size },
|
||||||
|
@ -436,6 +440,8 @@ impl InlineBox {
|
||||||
start_corner += &relative_adjustement(&style, ifc.containing_block)
|
start_corner += &relative_adjustement(&style, ifc.containing_block)
|
||||||
}
|
}
|
||||||
let positioning_context = PositioningContext::new_for_style(&style);
|
let positioning_context = PositioningContext::new_for_style(&style);
|
||||||
|
let text_decoration_line =
|
||||||
|
ifc.current_nesting_level.text_decoration_line | style.clone_text_decoration_line();
|
||||||
PartialInlineBoxFragment {
|
PartialInlineBoxFragment {
|
||||||
tag: self.tag,
|
tag: self.tag,
|
||||||
style,
|
style,
|
||||||
|
@ -454,6 +460,7 @@ impl InlineBox {
|
||||||
inline_start: ifc.inline_position,
|
inline_start: ifc.inline_position,
|
||||||
max_block_size_of_fragments_so_far: Length::zero(),
|
max_block_size_of_fragments_so_far: Length::zero(),
|
||||||
positioning_context,
|
positioning_context,
|
||||||
|
text_decoration_line: text_decoration_line,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -788,7 +795,7 @@ impl TextRun {
|
||||||
font_metrics,
|
font_metrics,
|
||||||
font_key,
|
font_key,
|
||||||
glyphs,
|
glyphs,
|
||||||
text_decorations_in_effect: TextDecorationLine::NONE,
|
text_decoration_line: ifc.current_nesting_level.text_decoration_line,
|
||||||
}));
|
}));
|
||||||
if runs.is_empty() {
|
if runs.is_empty() {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -104,6 +104,7 @@ fn construct_for_root_element<'dom>(
|
||||||
))],
|
))],
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
let propagated_text_decoration_line = style.clone_text_decoration_line();
|
||||||
(
|
(
|
||||||
ContainsFloats::No,
|
ContainsFloats::No,
|
||||||
vec![ArcRefCell::new(BlockLevelBox::Independent(
|
vec![ArcRefCell::new(BlockLevelBox::Independent(
|
||||||
|
@ -114,6 +115,7 @@ fn construct_for_root_element<'dom>(
|
||||||
display_inside,
|
display_inside,
|
||||||
contents,
|
contents,
|
||||||
ContentSizesRequest::None,
|
ContentSizesRequest::None,
|
||||||
|
propagated_text_decoration_line,
|
||||||
),
|
),
|
||||||
))],
|
))],
|
||||||
)
|
)
|
||||||
|
|
|
@ -16,6 +16,7 @@ use std::convert::TryInto;
|
||||||
use style::dom::OpaqueNode;
|
use style::dom::OpaqueNode;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::values::computed::Length;
|
use style::values::computed::Length;
|
||||||
|
use style::values::specified::text::TextDecorationLine;
|
||||||
|
|
||||||
/// https://drafts.csswg.org/css-display/#independent-formatting-context
|
/// https://drafts.csswg.org/css-display/#independent-formatting-context
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
|
@ -62,6 +63,7 @@ impl IndependentFormattingContext {
|
||||||
display_inside: DisplayInside,
|
display_inside: DisplayInside,
|
||||||
contents: Contents,
|
contents: Contents,
|
||||||
content_sizes: ContentSizesRequest,
|
content_sizes: ContentSizesRequest,
|
||||||
|
propagated_text_decoration_line: TextDecorationLine,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
match contents.try_into() {
|
match contents.try_into() {
|
||||||
Ok(non_replaced) => match display_inside {
|
Ok(non_replaced) => match display_inside {
|
||||||
|
@ -72,6 +74,7 @@ impl IndependentFormattingContext {
|
||||||
&style,
|
&style,
|
||||||
non_replaced,
|
non_replaced,
|
||||||
content_sizes,
|
content_sizes,
|
||||||
|
propagated_text_decoration_line,
|
||||||
);
|
);
|
||||||
Self {
|
Self {
|
||||||
tag: node.as_opaque(),
|
tag: node.as_opaque(),
|
||||||
|
|
|
@ -123,7 +123,7 @@ pub(crate) struct TextFragment {
|
||||||
pub font_key: FontInstanceKey,
|
pub font_key: FontInstanceKey,
|
||||||
pub glyphs: Vec<Arc<GlyphStore>>,
|
pub glyphs: Vec<Arc<GlyphStore>>,
|
||||||
/// A flag that represents the _used_ value of the text-decoration property.
|
/// A flag that represents the _used_ value of the text-decoration property.
|
||||||
pub text_decorations_in_effect: TextDecorationLine,
|
pub text_decoration_line: TextDecorationLine,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
@ -195,23 +195,6 @@ impl AbsoluteOrFixedPositionedFragment {
|
||||||
pub fn print(&self, tree: &mut PrintTree) {
|
pub fn print(&self, tree: &mut PrintTree) {
|
||||||
tree.add_item(format!("AbsoluteOrFixedPositionedFragment({:?})", self.0));
|
tree.add_item(format!("AbsoluteOrFixedPositionedFragment({:?})", self.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_text_decorations_in_effect(&mut self, text_decorations: TextDecorationLine) {
|
|
||||||
match self {
|
|
||||||
Fragment::Text(fragment) => fragment.text_decorations_in_effect = text_decorations,
|
|
||||||
Fragment::Box(fragment) => {
|
|
||||||
for child in &mut fragment.children {
|
|
||||||
child.set_text_decorations_in_effect(text_decorations);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Fragment::Anonymous(fragment) => {
|
|
||||||
for child in &mut fragment.children {
|
|
||||||
child.set_text_decorations_in_effect(text_decorations);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnonymousFragment {
|
impl AnonymousFragment {
|
||||||
|
|
|
@ -17,6 +17,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use style::computed_values::position::T as Position;
|
use style::computed_values::position::T as Position;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::values::computed::{Length, LengthOrAuto, LengthPercentage, LengthPercentageOrAuto};
|
use style::values::computed::{Length, LengthOrAuto, LengthPercentage, LengthPercentageOrAuto};
|
||||||
|
use style::values::specified::text::TextDecorationLine;
|
||||||
use style::Zero;
|
use style::Zero;
|
||||||
|
|
||||||
static HOISTED_FRAGMENT_ID_COUNTER: AtomicUsize = AtomicUsize::new(0);
|
static HOISTED_FRAGMENT_ID_COUNTER: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
@ -104,6 +105,8 @@ impl AbsolutelyPositionedBox {
|
||||||
display_inside,
|
display_inside,
|
||||||
contents,
|
contents,
|
||||||
content_sizes,
|
content_sizes,
|
||||||
|
// Text decorations are not propagated to any out-of-flow descendants.
|
||||||
|
TextDecorationLine::NONE,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -244,6 +244,12 @@ bitflags! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for TextDecorationLine {
|
||||||
|
fn default() -> Self {
|
||||||
|
TextDecorationLine::NONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Parse for TextDecorationLine {
|
impl Parse for TextDecorationLine {
|
||||||
/// none | [ underline || overline || line-through || blink ]
|
/// none | [ underline || overline || line-through || blink ]
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue