mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #25888 - ferjm:text.decoration.2020, r=nox
Partial text decoration support for layout 2020 - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix #25166 - [X] There are tests for these changes
This commit is contained in:
commit
acd14672e1
84 changed files with 743 additions and 53 deletions
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use crate::geom::{PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalSize};
|
use crate::geom::{PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalSize};
|
||||||
use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode;
|
use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode;
|
||||||
|
use style::computed_values::text_decoration_style::T as ComputedTextDecorationStyle;
|
||||||
use style::computed_values::transform_style::T as ComputedTransformStyle;
|
use style::computed_values::transform_style::T as ComputedTransformStyle;
|
||||||
use style::values::computed::Filter as ComputedFilter;
|
use style::values::computed::Filter as ComputedFilter;
|
||||||
use style::values::computed::Length;
|
use style::values::computed::Length;
|
||||||
|
@ -100,3 +101,16 @@ impl ToWebRender for PhysicalSides<Length> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ToWebRender for ComputedTextDecorationStyle {
|
||||||
|
type Type = webrender_api::LineStyle;
|
||||||
|
fn to_webrender(&self) -> Self::Type {
|
||||||
|
match *self {
|
||||||
|
ComputedTextDecorationStyle::Solid => wr::LineStyle::Solid,
|
||||||
|
ComputedTextDecorationStyle::Dotted => wr::LineStyle::Dotted,
|
||||||
|
ComputedTextDecorationStyle::Dashed => wr::LineStyle::Dashed,
|
||||||
|
ComputedTextDecorationStyle::Wavy => wr::LineStyle::Wavy,
|
||||||
|
_ => wr::LineStyle::Solid,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
use crate::context::LayoutContext;
|
use crate::context::LayoutContext;
|
||||||
use crate::display_list::conversions::ToWebRender;
|
use crate::display_list::conversions::ToWebRender;
|
||||||
use crate::fragments::{BoxFragment, Fragment};
|
use crate::fragments::{BoxFragment, Fragment, TextFragment};
|
||||||
use crate::geom::{PhysicalPoint, PhysicalRect};
|
use crate::geom::{PhysicalPoint, PhysicalRect};
|
||||||
use crate::replaced::IntrinsicSizes;
|
use crate::replaced::IntrinsicSizes;
|
||||||
use embedder_traits::Cursor;
|
use embedder_traits::Cursor;
|
||||||
|
@ -13,10 +13,11 @@ use gfx::text::glyph::GlyphStore;
|
||||||
use mitochondria::OnceCell;
|
use mitochondria::OnceCell;
|
||||||
use net_traits::image_cache::UsePlaceholder;
|
use net_traits::image_cache::UsePlaceholder;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use style::computed_values::text_decoration_style::T as ComputedTextDecorationStyle;
|
||||||
use style::dom::OpaqueNode;
|
use style::dom::OpaqueNode;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
|
||||||
use style::values::computed::{BorderStyle, Length, LengthPercentage};
|
use style::values::computed::{BorderStyle, Length, LengthPercentage};
|
||||||
|
use style::values::specified::text::TextDecorationLine;
|
||||||
use style::values::specified::ui::CursorKind;
|
use style::values::specified::ui::CursorKind;
|
||||||
use webrender_api::{self as wr, units};
|
use webrender_api::{self as wr, units};
|
||||||
|
|
||||||
|
@ -80,30 +81,6 @@ impl Fragment {
|
||||||
Fragment::Box(b) => BuilderForBoxFragment::new(b, containing_block).build(builder),
|
Fragment::Box(b) => BuilderForBoxFragment::new(b, containing_block).build(builder),
|
||||||
Fragment::AbsoluteOrFixedPositioned(_) => {},
|
Fragment::AbsoluteOrFixedPositioned(_) => {},
|
||||||
Fragment::Anonymous(_) => {},
|
Fragment::Anonymous(_) => {},
|
||||||
Fragment::Text(t) => {
|
|
||||||
builder.is_contentful = true;
|
|
||||||
let rect = t
|
|
||||||
.rect
|
|
||||||
.to_physical(t.parent_style.writing_mode, containing_block)
|
|
||||||
.translate(containing_block.origin.to_vector());
|
|
||||||
let mut baseline_origin = rect.origin.clone();
|
|
||||||
baseline_origin.y += t.ascent;
|
|
||||||
let glyphs = glyphs(&t.glyphs, baseline_origin);
|
|
||||||
if glyphs.is_empty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let mut common = builder.common_properties(rect.clone().to_webrender());
|
|
||||||
common.hit_info = hit_info(&t.parent_style, t.tag, Cursor::Text);
|
|
||||||
let color = t.parent_style.clone_color();
|
|
||||||
builder.wr.push_text(
|
|
||||||
&common,
|
|
||||||
rect.to_webrender(),
|
|
||||||
&glyphs,
|
|
||||||
t.font_key,
|
|
||||||
rgba(color),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
Fragment::Image(i) => {
|
Fragment::Image(i) => {
|
||||||
builder.is_contentful = true;
|
builder.is_contentful = true;
|
||||||
let rect = i
|
let rect = i
|
||||||
|
@ -120,8 +97,111 @@ impl Fragment {
|
||||||
wr::ColorF::WHITE,
|
wr::ColorF::WHITE,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
Fragment::Text(t) => {
|
||||||
|
self.build_display_list_for_text_fragment(t, builder, containing_block)
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_display_list_for_text_fragment(
|
||||||
|
&self,
|
||||||
|
fragment: &TextFragment,
|
||||||
|
builder: &mut DisplayListBuilder,
|
||||||
|
containing_block: &PhysicalRect<Length>,
|
||||||
|
) {
|
||||||
|
// NB: The order of painting text components (CSS Text Decoration Module Level 3) is:
|
||||||
|
// shadows, underline, overline, text, text-emphasis, and then line-through.
|
||||||
|
|
||||||
|
builder.is_contentful = true;
|
||||||
|
|
||||||
|
let rect = fragment
|
||||||
|
.rect
|
||||||
|
.to_physical(fragment.parent_style.writing_mode, containing_block)
|
||||||
|
.translate(containing_block.origin.to_vector());
|
||||||
|
let mut baseline_origin = rect.origin.clone();
|
||||||
|
baseline_origin.y += fragment.font_metrics.ascent;
|
||||||
|
let glyphs = glyphs(&fragment.glyphs, baseline_origin);
|
||||||
|
if glyphs.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut common = builder.common_properties(rect.to_webrender());
|
||||||
|
common.hit_info = hit_info(&fragment.parent_style, fragment.tag, Cursor::Text);
|
||||||
|
|
||||||
|
let color = fragment.parent_style.clone_color();
|
||||||
|
let font_metrics = &fragment.font_metrics;
|
||||||
|
|
||||||
|
// Underline.
|
||||||
|
if fragment
|
||||||
|
.text_decoration_line
|
||||||
|
.contains(TextDecorationLine::UNDERLINE)
|
||||||
|
{
|
||||||
|
let mut rect = rect;
|
||||||
|
rect.origin.y = rect.origin.y + font_metrics.ascent - font_metrics.underline_offset;
|
||||||
|
rect.size.height = font_metrics.underline_size;
|
||||||
|
self.build_display_list_for_text_decoration(fragment, builder, &rect, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overline.
|
||||||
|
if fragment
|
||||||
|
.text_decoration_line
|
||||||
|
.contains(TextDecorationLine::OVERLINE)
|
||||||
|
{
|
||||||
|
let mut rect = rect;
|
||||||
|
rect.size.height = font_metrics.underline_size;
|
||||||
|
self.build_display_list_for_text_decoration(fragment, builder, &rect, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Text.
|
||||||
|
builder.wr.push_text(
|
||||||
|
&common,
|
||||||
|
rect.to_webrender(),
|
||||||
|
&glyphs,
|
||||||
|
fragment.font_key,
|
||||||
|
rgba(color),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Line-through.
|
||||||
|
if fragment
|
||||||
|
.text_decoration_line
|
||||||
|
.contains(TextDecorationLine::LINE_THROUGH)
|
||||||
|
{
|
||||||
|
let mut rect = rect;
|
||||||
|
rect.origin.y = rect.origin.y + font_metrics.ascent - font_metrics.strikeout_offset;
|
||||||
|
// XXX(ferjm) This does not work on MacOS #942
|
||||||
|
rect.size.height = font_metrics.strikeout_size;
|
||||||
|
self.build_display_list_for_text_decoration(fragment, builder, &rect, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_display_list_for_text_decoration(
|
||||||
|
&self,
|
||||||
|
fragment: &TextFragment,
|
||||||
|
builder: &mut DisplayListBuilder,
|
||||||
|
rect: &PhysicalRect<Length>,
|
||||||
|
color: cssparser::RGBA,
|
||||||
|
) {
|
||||||
|
let rect = rect.to_webrender();
|
||||||
|
let wavy_line_thickness = (0.33 * rect.size.height).ceil();
|
||||||
|
let text_decoration_color = fragment
|
||||||
|
.parent_style
|
||||||
|
.clone_text_decoration_color()
|
||||||
|
.to_rgba(color);
|
||||||
|
let text_decoration_style = fragment.parent_style.clone_text_decoration_style();
|
||||||
|
if text_decoration_style == ComputedTextDecorationStyle::MozNone {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
builder.wr.push_line(
|
||||||
|
&builder.common_properties(rect),
|
||||||
|
&rect,
|
||||||
|
wavy_line_thickness,
|
||||||
|
wr::LineOrientation::Horizontal,
|
||||||
|
&rgba(text_decoration_color),
|
||||||
|
text_decoration_style.to_webrender(),
|
||||||
|
);
|
||||||
|
// XXX(ferjm) support text-decoration-style: double
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BuilderForBoxFragment<'a> {
|
struct BuilderForBoxFragment<'a> {
|
||||||
|
|
|
@ -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,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::flow::FlowLayout;
|
||||||
use crate::formatting_contexts::IndependentFormattingContext;
|
use crate::formatting_contexts::IndependentFormattingContext;
|
||||||
use crate::fragments::{
|
use crate::fragments::{
|
||||||
AbsoluteOrFixedPositionedFragment, AnonymousFragment, BoxFragment, CollapsedBlockMargins,
|
AbsoluteOrFixedPositionedFragment, AnonymousFragment, BoxFragment, CollapsedBlockMargins,
|
||||||
DebugId, Fragment, TextFragment,
|
DebugId, FontMetrics, Fragment, TextFragment,
|
||||||
};
|
};
|
||||||
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
use crate::geom::flow_relative::{Rect, Sides, Vec2};
|
||||||
use crate::positioned::{
|
use crate::positioned::{
|
||||||
|
@ -26,12 +26,14 @@ use style::dom::OpaqueNode;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::values::computed::{Length, LengthPercentage, Percentage};
|
use style::values::computed::{Length, LengthPercentage, Percentage};
|
||||||
use style::values::specified::text::TextAlignKeyword;
|
use style::values::specified::text::TextAlignKeyword;
|
||||||
|
use style::values::specified::text::TextDecorationLine;
|
||||||
use style::Zero;
|
use style::Zero;
|
||||||
use webrender_api::FontInstanceKey;
|
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)]
|
||||||
|
@ -68,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> {
|
||||||
|
@ -122,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.
|
||||||
|
@ -256,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() {
|
||||||
|
@ -385,6 +401,7 @@ impl Lines {
|
||||||
block: line_block_size,
|
block: line_block_size,
|
||||||
};
|
};
|
||||||
self.next_line_block_position += size.block;
|
self.next_line_block_position += size.block;
|
||||||
|
|
||||||
self.fragments
|
self.fragments
|
||||||
.push(Fragment::Anonymous(AnonymousFragment::new(
|
.push(Fragment::Anonymous(AnonymousFragment::new(
|
||||||
Rect { start_corner, size },
|
Rect { start_corner, size },
|
||||||
|
@ -423,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,
|
||||||
|
@ -441,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,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -631,8 +651,7 @@ fn layout_atomic(
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BreakAndShapeResult {
|
struct BreakAndShapeResult {
|
||||||
font_ascent: Au,
|
font_metrics: FontMetrics,
|
||||||
font_line_gap: Au,
|
|
||||||
font_key: FontInstanceKey,
|
font_key: FontInstanceKey,
|
||||||
runs: Vec<GlyphRun>,
|
runs: Vec<GlyphRun>,
|
||||||
break_at_start: bool,
|
break_at_start: bool,
|
||||||
|
@ -699,8 +718,7 @@ impl TextRun {
|
||||||
);
|
);
|
||||||
|
|
||||||
BreakAndShapeResult {
|
BreakAndShapeResult {
|
||||||
font_ascent: font.metrics.ascent,
|
font_metrics: (&font.metrics).into(),
|
||||||
font_line_gap: font.metrics.line_gap,
|
|
||||||
font_key: font.font_key,
|
font_key: font.font_key,
|
||||||
runs,
|
runs,
|
||||||
break_at_start,
|
break_at_start,
|
||||||
|
@ -712,8 +730,7 @@ impl TextRun {
|
||||||
use style::values::generics::text::LineHeight;
|
use style::values::generics::text::LineHeight;
|
||||||
|
|
||||||
let BreakAndShapeResult {
|
let BreakAndShapeResult {
|
||||||
font_ascent,
|
font_metrics,
|
||||||
font_line_gap,
|
|
||||||
font_key,
|
font_key,
|
||||||
runs,
|
runs,
|
||||||
break_at_start: _,
|
break_at_start: _,
|
||||||
|
@ -750,7 +767,7 @@ impl TextRun {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let line_height = match self.parent_style.get_inherited_text().line_height {
|
let line_height = match self.parent_style.get_inherited_text().line_height {
|
||||||
LineHeight::Normal => font_line_gap.into(),
|
LineHeight::Normal => font_metrics.line_gap,
|
||||||
LineHeight::Number(n) => font_size * n.0,
|
LineHeight::Number(n) => font_size * n.0,
|
||||||
LineHeight::Length(l) => l.0,
|
LineHeight::Length(l) => l.0,
|
||||||
};
|
};
|
||||||
|
@ -775,9 +792,10 @@ impl TextRun {
|
||||||
debug_id: DebugId::new(),
|
debug_id: DebugId::new(),
|
||||||
parent_style: self.parent_style.clone(),
|
parent_style: self.parent_style.clone(),
|
||||||
rect,
|
rect,
|
||||||
ascent: font_ascent.into(),
|
font_metrics,
|
||||||
font_key,
|
font_key,
|
||||||
glyphs,
|
glyphs,
|
||||||
|
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(),
|
||||||
|
|
|
@ -7,6 +7,7 @@ use crate::geom::{PhysicalPoint, PhysicalRect};
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
use crate::layout_debug;
|
use crate::layout_debug;
|
||||||
use crate::positioned::HoistedFragmentId;
|
use crate::positioned::HoistedFragmentId;
|
||||||
|
use gfx::font::FontMetrics as GfxFontMetrics;
|
||||||
use gfx::text::glyph::GlyphStore;
|
use gfx::text::glyph::GlyphStore;
|
||||||
use gfx_traits::print_tree::PrintTree;
|
use gfx_traits::print_tree::PrintTree;
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
|
@ -18,6 +19,7 @@ use style::dom::OpaqueNode;
|
||||||
use style::logical_geometry::WritingMode;
|
use style::logical_geometry::WritingMode;
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
use style::values::computed::Length;
|
use style::values::computed::Length;
|
||||||
|
use style::values::specified::text::TextDecorationLine;
|
||||||
use style::Zero;
|
use style::Zero;
|
||||||
use webrender_api::{FontInstanceKey, ImageKey};
|
use webrender_api::{FontInstanceKey, ImageKey};
|
||||||
|
|
||||||
|
@ -86,6 +88,29 @@ pub(crate) struct AnonymousFragment {
|
||||||
pub scrollable_overflow: PhysicalRect<Length>,
|
pub scrollable_overflow: PhysicalRect<Length>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Serialize)]
|
||||||
|
pub(crate) struct FontMetrics {
|
||||||
|
pub ascent: Length,
|
||||||
|
pub line_gap: Length,
|
||||||
|
pub underline_offset: Length,
|
||||||
|
pub underline_size: Length,
|
||||||
|
pub strikeout_offset: Length,
|
||||||
|
pub strikeout_size: Length,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&GfxFontMetrics> for FontMetrics {
|
||||||
|
fn from(metrics: &GfxFontMetrics) -> FontMetrics {
|
||||||
|
FontMetrics {
|
||||||
|
ascent: metrics.ascent.into(),
|
||||||
|
line_gap: metrics.line_gap.into(),
|
||||||
|
underline_offset: metrics.underline_offset.into(),
|
||||||
|
underline_size: metrics.underline_size.into(),
|
||||||
|
strikeout_offset: metrics.strikeout_offset.into(),
|
||||||
|
strikeout_size: metrics.strikeout_size.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub(crate) struct TextFragment {
|
pub(crate) struct TextFragment {
|
||||||
pub debug_id: DebugId,
|
pub debug_id: DebugId,
|
||||||
|
@ -93,10 +118,12 @@ pub(crate) struct TextFragment {
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
pub parent_style: ServoArc<ComputedValues>,
|
pub parent_style: ServoArc<ComputedValues>,
|
||||||
pub rect: Rect<Length>,
|
pub rect: Rect<Length>,
|
||||||
pub ascent: Length,
|
pub font_metrics: FontMetrics,
|
||||||
#[serde(skip_serializing)]
|
#[serde(skip_serializing)]
|
||||||
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.
|
||||||
|
pub text_decoration_line: TextDecorationLine,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
|
|
|
@ -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,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ ${helpers.predefined_type(
|
||||||
"TextDecorationLine",
|
"TextDecorationLine",
|
||||||
"specified::TextDecorationLine::none()",
|
"specified::TextDecorationLine::none()",
|
||||||
engines="gecko servo-2013 servo-2020",
|
engines="gecko servo-2013 servo-2020",
|
||||||
servo_2020_pref="layout.2020.unimplemented",
|
|
||||||
initial_specified_value="specified::TextDecorationLine::none()",
|
initial_specified_value="specified::TextDecorationLine::none()",
|
||||||
animation_value_type="discrete",
|
animation_value_type="discrete",
|
||||||
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line",
|
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line",
|
||||||
|
@ -42,7 +41,7 @@ ${helpers.predefined_type(
|
||||||
${helpers.single_keyword(
|
${helpers.single_keyword(
|
||||||
"text-decoration-style",
|
"text-decoration-style",
|
||||||
"solid double dotted dashed wavy -moz-none",
|
"solid double dotted dashed wavy -moz-none",
|
||||||
engines="gecko",
|
engines="gecko servo-2020",
|
||||||
animation_value_type="discrete",
|
animation_value_type="discrete",
|
||||||
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style",
|
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style",
|
||||||
)}
|
)}
|
||||||
|
@ -51,7 +50,7 @@ ${helpers.predefined_type(
|
||||||
"text-decoration-color",
|
"text-decoration-color",
|
||||||
"Color",
|
"Color",
|
||||||
"computed_value::T::currentcolor()",
|
"computed_value::T::currentcolor()",
|
||||||
engines="gecko",
|
engines="gecko servo-2020",
|
||||||
initial_specified_value="specified::Color::currentcolor()",
|
initial_specified_value="specified::Color::currentcolor()",
|
||||||
animation_value_type="AnimatedColor",
|
animation_value_type="AnimatedColor",
|
||||||
ignored_when_colors_disabled=True,
|
ignored_when_colors_disabled=True,
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<%namespace name="helpers" file="/helpers.mako.rs" />
|
<%namespace name="helpers" file="/helpers.mako.rs" />
|
||||||
|
|
||||||
<%helpers:shorthand name="text-decoration"
|
<%helpers:shorthand name="text-decoration"
|
||||||
engines="gecko servo-2013"
|
engines="gecko servo-2013 servo-2020"
|
||||||
flags="SHORTHAND_IN_GETCS"
|
flags="SHORTHAND_IN_GETCS"
|
||||||
sub_properties="text-decoration-line
|
sub_properties="text-decoration-line
|
||||||
${' text-decoration-style text-decoration-color text-decoration-thickness' if engine == 'gecko' else ''}"
|
${' text-decoration-style text-decoration-color text-decoration-thickness' if engine == 'gecko' else ''}"
|
||||||
|
|
|
@ -217,7 +217,7 @@ impl ToComputedValue for TextOverflow {
|
||||||
}
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)]
|
#[derive(MallocSizeOf, Serialize, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)]
|
||||||
#[value_info(other_values = "none,underline,overline,line-through,blink")]
|
#[value_info(other_values = "none,underline,overline,line-through,blink")]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
/// Specified keyword values for the text-decoration-line property.
|
/// Specified keyword values for the text-decoration-line property.
|
||||||
|
@ -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>(
|
||||||
|
|
|
@ -15,6 +15,8 @@ skip: true
|
||||||
skip: false
|
skip: false
|
||||||
[css-color]
|
[css-color]
|
||||||
skip: false
|
skip: false
|
||||||
|
[css-text-decor]
|
||||||
|
skip: false
|
||||||
[css-transforms]
|
[css-transforms]
|
||||||
skip: false
|
skip: false
|
||||||
[filter-effects]
|
[filter-effects]
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
[content-070.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[content-082.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,55 @@
|
||||||
|
[inheritance.html]
|
||||||
|
[Property text-emphasis-style inherits]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-emphasis-style has initial value none]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-style has initial value solid]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-underline-position has initial value auto]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line has initial value none]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-emphasis-color has initial value rgba(2, 3, 4, 0.5)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-shadow has initial value none]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-color has initial value rgba(2, 3, 4, 0.5)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-skip-ink inherits]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-skip-ink has initial value auto]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line does not inherit]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-underline-position inherits]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-emphasis-position inherits]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-color does not inherit]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-emphasis-position has initial value over right]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-style does not inherit]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-shadow inherits]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-emphasis-color inherits]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
[text-decoration-color-computed.html]
|
||||||
|
[Property text-decoration-color value 'inherit']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-color value 'rgb(0, 0, 255)']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-color value 'currentcolor']
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
[text-decoration-computed.html]
|
||||||
|
[Property text-decoration value 'auto']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration value 'currentcolor']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration value 'double overline underline']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration value 'line-through']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration value 'underline dashed rgb(0, 255, 0)']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration value 'underline overline line-through red']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration value 'rgba(10, 20, 30, 0.4) dotted']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration value 'none']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration value '10px']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration value 'underline red from-font']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration value 'solid']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration value 'from-font']
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
[text-decoration-line-computed.html]
|
||||||
|
[Property text-decoration-line value 'underline overline']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'overline blink']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'underline line-through blink']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'underline overline blink']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'blink']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'line-through blink']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'underline']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'underline line-through']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'overline line-through blink']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'line-through']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'underline blink']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'overline line-through']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'spelling-error']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'underline overline line-through']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'none']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'grammar-error']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'underline overline line-through blink']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-line value 'overline']
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[text-decoration-line-valid.html]
|
||||||
|
[e.style['text-decoration-line'\] = "spelling-error" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration-line'\] = "grammar-error" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
[text-decoration-shorthand.html]
|
||||||
|
[e.style['text-decoration'\] = "overline dotted green" should set text-decoration-line]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "overline dotted green" should set text-decoration-style]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "overline dotted green" should set text-decoration-color]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "overline dotted green" should not set unrelated longhands]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[text-decoration-skip-ink-computed.html]
|
||||||
|
[Property text-decoration-skip-ink value 'none']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-skip-ink value 'auto']
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
[text-decoration-skip-ink-valid.html]
|
||||||
|
[e.style['text-decoration-skip-ink'\] = "none" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration-skip-ink'\] = "auto" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
[text-decoration-style-computed.html]
|
||||||
|
[Property text-decoration-style value 'wavy']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-style value 'dashed']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-style value 'dotted']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-style value 'double']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-style value 'solid']
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
[text-decoration-valid.html]
|
||||||
|
[e.style['text-decoration'\] = "underline auto" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "auto" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "underline dashed green" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "10px" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "double overline underline" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "rgba(10, 20, 30, 0.4) dotted" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "solid" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "line-through 20px" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "underline overline line-through red" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "overline 3em" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "currentcolor" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "from-font" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration'\] = "overline green from-font" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
[text-shadow-computed.html]
|
||||||
|
[Property text-shadow value 'calc(0.5em + 10px) calc(0.5em + 10px) calc(0.5em + 10px)']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-shadow value '10px 20px, 30px 40px']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-shadow value 'lime 10px 20px 30px, red 40px 50px']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-shadow value 'calc(-0.5em + 10px) calc(-0.5em + 10px) calc(-0.5em + 10px)']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-shadow value 'red 10px 20px 30px']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-shadow value 'none']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-shadow value '10px 20px']
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
[text-shadow-valid.html]
|
||||||
|
[e.style['text-shadow'\] = "rgb(255, 0, 0) 10px 20px" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-shadow'\] = "lime 10px 20px 30px, blue 40px 50px" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-shadow'\] = "10px 20px 30px" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-shadow'\] = "10px -20px 30px" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-shadow'\] = "-10px 20px 30px" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-shadow'\] = "10px 20px 30px lime" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-shadow'\] = "10px 20px" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-shadow'\] = "none" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-shadow'\] = "10px 20px, 30px 40px" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-shadow'\] = "calc(1em + 2px) calc(3em + 4px) calc(5em + 6px)" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
[text-underline-position-computed.html]
|
||||||
|
[Property text-underline-position value 'under left']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-underline-position value 'left']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-underline-position value 'under']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-underline-position value 'right']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-underline-position value 'auto']
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
[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
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-color.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,4 @@
|
||||||
|
[text-decoration-serialization.tentative.html]
|
||||||
|
[text-decoration shorthand serialization]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-skip-ink-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-skip-ink-003.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-skip-ink-004.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-skip-ink-005.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-skip-ink-sidewayslr-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-skip-ink-sidewaysrl-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-skip-ink-upright-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-skip-ink-upright-002.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-skip-ink-vertical-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-skip-ink-vertical-002.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,7 @@
|
||||||
|
[text-decoration-skip-ink.html]
|
||||||
|
[Body must have text-decoration-skip-ink auto by default.]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-skip-ink must support values auto, none and all.]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-subelements-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-subelements-002.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-thickness-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,10 @@
|
||||||
|
[text-decoration-thickness-computed.html]
|
||||||
|
[Property text-decoration-thickness value 'auto']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-thickness value 'from-font']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-decoration-thickness value 'calc(10px - 8px)']
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[text-decoration-thickness-initial.html]
|
||||||
|
[Initial value of text-decoration-thickness should be auto]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-thickness-linethrough-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-thickness-overline-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-thickness-scroll-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-thickness-underline-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,25 @@
|
||||||
|
[text-decoration-thickness-valid.html]
|
||||||
|
[e.style['text-decoration-thickness'\] = "from-font" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration-thickness'\] = "2001em" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration-thickness'\] = "-49em" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration-thickness'\] = "auto" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration-thickness'\] = "calc(-50em + 13px)" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration-thickness'\] = "53px" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration-thickness'\] = "calc(40em - 10px)" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-decoration-thickness'\] = "-10px" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-thickness-vertical-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-thickness-vertical-002.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-underline-position-vertical-ja.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-decoration-underline-position-vertical.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-color-001.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-position-above-left-001.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-position-above-left-002.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-position-above-right-001.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-position-above-right-002.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-position-below-left-001.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-position-below-left-002.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-position-below-right-001.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-position-below-right-002.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-style-002.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-style-006.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-style-007.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-style-008.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-style-010.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-style-012.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-style-021.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-style-filled-001.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-style-open-001.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-style-shape-001.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-emphasis-style-string-001.xht]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-underline-offset-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,7 @@
|
||||||
|
[text-underline-offset-computed.html]
|
||||||
|
[Property text-underline-offset value 'auto']
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Property text-underline-offset value 'calc(10px - 8px)']
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[text-underline-offset-initial.html]
|
||||||
|
[Initial value of text-underline-offset]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
[text-underline-offset-scroll-001.html]
|
||||||
|
expected: FAIL
|
|
@ -0,0 +1,22 @@
|
||||||
|
[text-underline-offset-valid.html]
|
||||||
|
[e.style['text-underline-offset'\] = "53px" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-underline-offset'\] = "calc(-13em + 50px)" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-underline-offset'\] = "2001em" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-underline-offset'\] = "auto" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-underline-offset'\] = "-10px" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-underline-offset'\] = "calc(40em - 10px)" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[e.style['text-underline-offset'\] = "-49em" should set the property value]
|
||||||
|
expected: FAIL
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
[text_decoration_smoke_a.html]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[text_decoration_underline_subpx_a.html]
|
|
||||||
expected: FAIL
|
|
|
@ -2,4 +2,3 @@
|
||||||
bug: https://github.com/servo/servo/issues/25802
|
bug: https://github.com/servo/servo/issues/25802
|
||||||
[localeCompare should return the same as other browsers, even though it's implementation-dependent]
|
[localeCompare should return the same as other browsers, even though it's implementation-dependent]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue