render: honor generated controls and border resets
This commit is contained in:
1 parent
2c12b5a03a
commit
9ec43134ae
4 files changed
+181
-35
No files matched your search
@@ -271,7 +271,10 @@ pub fn paint_dom(tree: &DomTree, viewport: (f32, f32), base_url: Option<&str>) -
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(pseudo) = style.before_pseudo.as_deref() {
|
||||
for pseudo in [style.before_pseudo.as_deref(), style.after_pseudo.as_deref()]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
{
|
||||
paint_positioned_pseudo(
|
||||
&mut pixmap,
|
||||
pseudo,
|
||||
@@ -1788,12 +1791,16 @@ fn paint_positioned_pseudo(
|
||||
None => Some(rect),
|
||||
};
|
||||
let Some(visible) = visible else { return };
|
||||
let Some(sk_rect) = Rect::from_xywh(visible.x, visible.y, visible.width, visible.height) else {
|
||||
return;
|
||||
let path = if style.border_radius > 0.5 {
|
||||
rounded_rect_path(visible.x, visible.y, visible.width, visible.height, style.border_radius)
|
||||
} else {
|
||||
Rect::from_xywh(visible.x, visible.y, visible.width, visible.height).and_then(|rect| {
|
||||
let mut builder = PathBuilder::new();
|
||||
builder.push_rect(rect);
|
||||
builder.finish()
|
||||
})
|
||||
};
|
||||
let mut builder = PathBuilder::new();
|
||||
builder.push_rect(sk_rect);
|
||||
let Some(path) = builder.finish() else { return };
|
||||
let Some(path) = path else { return };
|
||||
if let Some(color) = style.background_color {
|
||||
let mut paint = Paint::default();
|
||||
paint.set_color(Color::from_rgba8(color[0], color[1], color[2], color[3]));
|
||||
@@ -1808,6 +1815,37 @@ fn paint_positioned_pseudo(
|
||||
if let Some((angle, stops)) = &style.background_gradient {
|
||||
paint_linear_gradient(pixmap, &path, &rect, *angle, stops);
|
||||
}
|
||||
if let Some(content) = style.before_content.as_deref().filter(|content| !content.is_empty()) {
|
||||
let font_size = style.font_size.unwrap_or(16.0);
|
||||
let bold = crate::style::used_font_weight(style) >= 600;
|
||||
let text_width = measure_text(content, font_size, bold, style.font_family.as_deref());
|
||||
let line_height = crate::inline::used_line_height(style);
|
||||
let x = match style.justify_content {
|
||||
Some(taffy::JustifyContent::CENTER) => rect.x + (rect.width - text_width) / 2.0,
|
||||
Some(taffy::JustifyContent::FLEX_END | taffy::JustifyContent::END) => {
|
||||
rect.x + rect.width - style.padding.right - text_width
|
||||
}
|
||||
_ => rect.x + style.padding.left,
|
||||
};
|
||||
let y = match style.align_items {
|
||||
Some(taffy::AlignItems::CENTER) => rect.y + (rect.height - line_height) / 2.0,
|
||||
Some(taffy::AlignItems::FLEX_END | taffy::AlignItems::END) => {
|
||||
rect.y + rect.height - style.padding.bottom - line_height
|
||||
}
|
||||
_ => rect.y + style.padding.top,
|
||||
};
|
||||
draw_text(
|
||||
pixmap,
|
||||
content,
|
||||
x,
|
||||
y,
|
||||
style.color.unwrap_or([0, 0, 0, 255]),
|
||||
font_size,
|
||||
bold,
|
||||
style.font_family.as_deref(),
|
||||
Some(visible),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch every `<img>` once (seeding `cache` for the paint pass) and record its
|
||||
@@ -2874,6 +2912,42 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn paints_positioned_attr_content_over_the_host_background() {
|
||||
let tree = parse_html(
|
||||
r#"<html><head><style>
|
||||
body { margin:0 }
|
||||
#cta {
|
||||
position:relative; width:120px; height:40px; border:0;
|
||||
padding:0; color:transparent; background:red;
|
||||
}
|
||||
#cta::before {
|
||||
content:attr(data-label);
|
||||
position:absolute; inset:1px;
|
||||
display:flex; align-items:center; justify-content:center;
|
||||
border-radius:4px; color:black; background:white;
|
||||
}
|
||||
</style></head><body>
|
||||
<button id="cta" data-label="Get Started">Get Started</button>
|
||||
</body></html>"#,
|
||||
);
|
||||
let pixmap = paint_dom(&tree, (140.0, 60.0), None).expect("pixmap");
|
||||
let inner = pixmap.pixel(5, 5).expect("inner pixel");
|
||||
assert_eq!(
|
||||
(inner.red(), inner.green(), inner.blue()),
|
||||
(255, 255, 255),
|
||||
"the generated box must cover the red host background"
|
||||
);
|
||||
let dark_pixels = (35..85)
|
||||
.flat_map(|x| (8..32).map(move |y| (x, y)))
|
||||
.filter(|&(x, y)| {
|
||||
let pixel = pixmap.pixel(x, y).unwrap();
|
||||
pixel.red() < 100 && pixel.green() < 100 && pixel.blue() < 100
|
||||
})
|
||||
.count();
|
||||
assert!(dark_pixels > 10, "generated attr() text must be painted");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn later_element_paints_over_earlier() {
|
||||
// A blue div nested inside a red one: both cover the origin, and blue
|
||||
|
||||
Reference in new issue
Block a user