LibWeb: Use saveLayer compositing for background-clip: text
Instead of rendering text glyphs into a separate mask surface and using clipShader, paint the backgrounds first and then composite the text glyphs via saveLayer with SkBlendMode::kDstIn. Skia's saveLayer automatically sizes its backing at device resolution including CSS transforms, so no manual scale computation is needed. Fixes pixelation when zooming in on clipped backgrounds on e.g. the title of https://modern-css.com/.
This commit is contained in:
parent
7c9b3c08fa
commit
f2e6f70fbb
5 changed files with 53 additions and 10 deletions
|
|
@ -87,20 +87,23 @@ void paint_background(DisplayListRecordingContext& context, PaintableBox const&
|
|||
auto paint_into_isolated_group = any_of(resolved_background.layers, [](auto const& layer) {
|
||||
return layer.blend_mode != CSS::MixBlendMode::Normal;
|
||||
});
|
||||
if (paint_into_isolated_group) {
|
||||
display_list_recorder.save_layer();
|
||||
}
|
||||
|
||||
bool is_root_element = paintable_box.layout_node().is_root_element();
|
||||
bool needs_text_clip = resolved_background.needs_text_clip && !is_root_element;
|
||||
|
||||
RefPtr<DisplayList> text_clip_display_list;
|
||||
Gfx::IntRect text_clip_rect;
|
||||
if (needs_text_clip) {
|
||||
text_clip_display_list = compute_text_clip_paths(context, paintable_box, resolved_background.background_rect.location());
|
||||
text_clip_rect = context.rounded_device_rect(resolved_background.background_rect).to_type<int>();
|
||||
display_list_recorder.save();
|
||||
auto display_list = compute_text_clip_paths(context, paintable_box, resolved_background.background_rect.location());
|
||||
auto rect = context.rounded_device_rect(resolved_background.background_rect);
|
||||
display_list_recorder.add_mask(move(display_list), rect.to_type<int>(), Gfx::MaskKind::Alpha);
|
||||
display_list_recorder.add_clip_rect(text_clip_rect);
|
||||
display_list_recorder.save_layer();
|
||||
}
|
||||
|
||||
if (paint_into_isolated_group)
|
||||
display_list_recorder.save_layer();
|
||||
|
||||
BackgroundBox border_box {
|
||||
resolved_background.background_rect,
|
||||
border_radii
|
||||
|
|
@ -323,10 +326,14 @@ void paint_background(DisplayListRecordingContext& context, PaintableBox const&
|
|||
}
|
||||
}
|
||||
|
||||
if (needs_text_clip) {
|
||||
if (paint_into_isolated_group)
|
||||
display_list_recorder.restore();
|
||||
|
||||
if (needs_text_clip) {
|
||||
display_list_recorder.apply_effects(1.0f, Gfx::CompositingAndBlendingOperator::DestinationIn);
|
||||
display_list_recorder.paint_nested_display_list(move(text_clip_display_list), text_clip_rect);
|
||||
display_list_recorder.restore();
|
||||
display_list_recorder.restore();
|
||||
}
|
||||
if (paint_into_isolated_group) {
|
||||
display_list_recorder.restore();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
body { margin: 0; }
|
||||
.scaled {
|
||||
transform: scale(3);
|
||||
transform-origin: left top;
|
||||
}
|
||||
.text {
|
||||
font-size: 20px;
|
||||
font-weight: 800;
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
<div class="scaled">
|
||||
<div class="text">Abcdefg</div>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<meta name="fuzzy" content="maxDifference=0-17;totalPixels=0-1097" />
|
||||
<link rel="match" href="../expected/background-clip-text-in-scaled-ancestor-ref.html" />
|
||||
<style>
|
||||
body { margin: 0; }
|
||||
.scaled {
|
||||
transform: scale(3);
|
||||
transform-origin: left top;
|
||||
}
|
||||
.text {
|
||||
font-size: 20px;
|
||||
font-weight: 800;
|
||||
color: transparent;
|
||||
background: red;
|
||||
background-clip: text;
|
||||
}
|
||||
</style>
|
||||
<div class="scaled">
|
||||
<div class="text">Abcdefg</div>
|
||||
</div>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 245 KiB After Width: | Height: | Size: 246 KiB |
|
|
@ -3,7 +3,7 @@
|
|||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="match" href="../expected/css-background-clip-text-ref.html" />
|
||||
<meta name="fuzzy" content="maxDifference=0-3;totalPixels=0-27676">
|
||||
<meta name="fuzzy" content="maxDifference=0-3;totalPixels=0-27725">
|
||||
|
||||
<style>
|
||||
html {
|
||||
|
|
|
|||
Loading…
Reference in a new issue