mirror of
https://github.com/servo/servo.git
synced 2025-06-04 07:35:36 +00:00
layout: Support wavy
and double
for text-decoration-line
(#37079)
- Add support for `text-decoration-line: double`: Line drawing is done similar to how it works in Firefox and Chromium. A gap of half of line thickness is added between each line. - Fix support for `text-decoration-line: wavy`: Wavy lines rectangles were not calcualted properly, which meant they were rendered as solid lines. Now the amplitude of the wave is 1.5 times line thickness. Testing: A manual test is updated `tests/html/text_deco_simple.html` to cover more cases. In general, rendering of text-decorations is difficult to test via reftesting. Fixes #17887. Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
0ea40d6365
commit
7f0cebd442
3 changed files with 84 additions and 20 deletions
|
@ -125,11 +125,15 @@ impl ToWebRender for ComputedTextDecorationStyle {
|
|||
type Type = LineStyle;
|
||||
fn to_webrender(&self) -> Self::Type {
|
||||
match *self {
|
||||
ComputedTextDecorationStyle::Solid => LineStyle::Solid,
|
||||
ComputedTextDecorationStyle::Solid | ComputedTextDecorationStyle::Double => {
|
||||
LineStyle::Solid
|
||||
},
|
||||
ComputedTextDecorationStyle::Dotted => LineStyle::Dotted,
|
||||
ComputedTextDecorationStyle::Dashed => LineStyle::Dashed,
|
||||
ComputedTextDecorationStyle::Wavy => LineStyle::Wavy,
|
||||
_ => LineStyle::Solid,
|
||||
ComputedTextDecorationStyle::MozNone => {
|
||||
unreachable!("Should never try to draw a moz-none text decoration")
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use base::id::ScrollTreeNodeId;
|
|||
use clip::{Clip, ClipId};
|
||||
use compositing_traits::display_list::{CompositorDisplayListInfo, SpatialTreeNodeInfo};
|
||||
use embedder_traits::Cursor;
|
||||
use euclid::{Point2D, SideOffsets2D, Size2D, UnknownUnit};
|
||||
use euclid::{Point2D, SideOffsets2D, Size2D, UnknownUnit, Vector2D};
|
||||
use fonts::GlyphStore;
|
||||
use gradient::WebRenderGradient;
|
||||
use range::Range as ServoRange;
|
||||
|
@ -21,7 +21,9 @@ use servo_geometry::MaxRect;
|
|||
use style::Zero;
|
||||
use style::color::{AbsoluteColor, ColorSpace};
|
||||
use style::computed_values::border_image_outset::T as BorderImageOutset;
|
||||
use style::computed_values::text_decoration_style::T as ComputedTextDecorationStyle;
|
||||
use style::computed_values::text_decoration_style::{
|
||||
T as ComputedTextDecorationStyle, T as TextDecorationStyle,
|
||||
};
|
||||
use style::dom::OpaqueNode;
|
||||
use style::properties::ComputedValues;
|
||||
use style::properties::longhands::visibility::computed_value::T as Visibility;
|
||||
|
@ -737,6 +739,7 @@ impl Fragment {
|
|||
let rect = fragment.rect.translate(containing_block.origin.to_vector());
|
||||
let mut baseline_origin = rect.origin;
|
||||
baseline_origin.y += fragment.font_metrics.ascent;
|
||||
|
||||
let glyphs = glyphs(
|
||||
&fragment.glyphs,
|
||||
baseline_origin,
|
||||
|
@ -785,11 +788,13 @@ impl Fragment {
|
|||
rect.origin.y += font_metrics.ascent - font_metrics.underline_offset;
|
||||
rect.size.height =
|
||||
Au::from_f32_px(font_metrics.underline_size.to_nearest_pixel(dppx));
|
||||
|
||||
self.build_display_list_for_text_decoration(
|
||||
&parent_style,
|
||||
builder,
|
||||
&rect,
|
||||
text_decoration,
|
||||
TextDecorationLine::UNDERLINE,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -804,6 +809,7 @@ impl Fragment {
|
|||
builder,
|
||||
&rect,
|
||||
text_decoration,
|
||||
TextDecorationLine::OVERLINE,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -896,6 +902,7 @@ impl Fragment {
|
|||
builder,
|
||||
&rect,
|
||||
text_decoration,
|
||||
TextDecorationLine::LINE_THROUGH,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -911,22 +918,46 @@ impl Fragment {
|
|||
builder: &mut DisplayListBuilder,
|
||||
rect: &PhysicalRect<Au>,
|
||||
text_decoration: &FragmentTextDecoration,
|
||||
line: TextDecorationLine,
|
||||
) {
|
||||
let rect = rect.to_webrender();
|
||||
let wavy_line_thickness = (0.33 * rect.size().height).ceil();
|
||||
if text_decoration.style == ComputedTextDecorationStyle::MozNone {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut rect = rect.to_webrender();
|
||||
let line_thickness = rect.height().ceil();
|
||||
|
||||
if text_decoration.style == ComputedTextDecorationStyle::Wavy {
|
||||
rect = rect.inflate(0.0, line_thickness * 1.0);
|
||||
}
|
||||
|
||||
let common_properties = builder.common_properties(rect, parent_style);
|
||||
builder.wr().push_line(
|
||||
&common_properties,
|
||||
&rect,
|
||||
wavy_line_thickness,
|
||||
line_thickness,
|
||||
wr::LineOrientation::Horizontal,
|
||||
&rgba(text_decoration.color),
|
||||
text_decoration.style.to_webrender(),
|
||||
);
|
||||
// XXX(ferjm) support text-decoration-style: double
|
||||
|
||||
if text_decoration.style == TextDecorationStyle::Double {
|
||||
let half_height = (rect.height() / 2.0).floor().max(1.0);
|
||||
let y_offset = match line {
|
||||
TextDecorationLine::OVERLINE => -rect.height() - half_height,
|
||||
_ => rect.height() + half_height,
|
||||
};
|
||||
let rect = rect.translate(Vector2D::new(0.0, y_offset));
|
||||
let common_properties = builder.common_properties(rect, parent_style);
|
||||
builder.wr().push_line(
|
||||
&common_properties,
|
||||
&rect,
|
||||
line_thickness,
|
||||
wr::LineOrientation::Horizontal,
|
||||
&rgba(text_decoration.color),
|
||||
text_decoration.style.to_webrender(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,17 +1,46 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
<p style="text-decoration:none;"> none </p>
|
||||
<p style="text-decoration:underline;"> text underline </p>
|
||||
<p style="text-decoration:overline;"> text underline </p>
|
||||
<p style="text-decoration:line-through;"> text underline </p>
|
||||
<p>
|
||||
<p style="font-size:40px; text-decoration:underline; font-family:Verdana;"> text underline pqrstg </p>
|
||||
<p style="text-decoration:overline;"> text overline xxxxxxxxXXXXXXX</p>
|
||||
<p style="font-size:50px; text-decoration:line-through;"> text line-through xxxxxxxxXXXXX</p>
|
||||
<p style="text-decoration:blink;"> text blink </p>
|
||||
|
||||
<style>
|
||||
p {
|
||||
font-family: "Times New Roman";
|
||||
background: lightgrey;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p style="text-decoration: none blue;">text-decoration: </p>
|
||||
<p style="text-decoration: underline blue;">text-decoration: </p>
|
||||
<p style="text-decoration: overline blue;">text-decoration: </p>
|
||||
<p style="text-decoration: line-through blue;">text-decoration: </p>
|
||||
|
||||
<p style="text-decoration: underline double blue;">text-decoration: </p>
|
||||
<p style="text-decoration: overline double blue;">text-decoration: </p>
|
||||
<p style="text-decoration: line-through double blue;">text-decoration: </p>
|
||||
|
||||
<p style="text-decoration: underline wavy blue;">text-decoration: </p>
|
||||
<p style="text-decoration: overline wavy blue;">text-decoration: </p>
|
||||
<p style="text-decoration: line-through wavy blue;">text-decoration: </p>
|
||||
|
||||
<p style="text-decoration: underline dashed blue;">text-decoration: </p>
|
||||
<p style="text-decoration: overline dashed blue;">text-decoration: </p>
|
||||
<p style="text-decoration: line-through dashed blue;">text-decoration: </p>
|
||||
|
||||
<p style="text-decoration: underline dotted blue;">text-decoration: </p>
|
||||
<p style="text-decoration: overline dotted blue;">text-decoration: </p>
|
||||
<p style="text-decoration: line-through dotted blue;">text-decoration: </p>
|
||||
|
||||
<script>
|
||||
for (paragraph of document.querySelectorAll("p")) {
|
||||
paragraph.innerText += " " +
|
||||
getComputedStyle(paragraph).textDecorationLine + " " +
|
||||
getComputedStyle(paragraph).textDecorationStyle;
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue