Browse Source

Fix backdrop-filter clipping to border background, add visual test

Michael Ragazzon 2 years ago
parent
commit
aec3f2ac73

+ 3 - 3
Source/Core/ElementDecoration.cpp

@@ -229,7 +229,7 @@ void ElementDecoration::RenderDecorators(RenderStage render_stage)
 	RenderManager& render_manager = context->GetRenderManager();
 	Rectanglei initial_scissor_region = render_manager.GetState().scissor_region;
 
-	auto ApplyClippingRegion = [this, &render_manager, initial_scissor_region](PropertyId filter_id) {
+	auto ApplyClippingRegion = [this, &render_manager](PropertyId filter_id) {
 		RMLUI_ASSERT(filter_id == PropertyId::Filter || filter_id == PropertyId::BackdropFilter);
 
 		const bool force_clip_to_self_border_box = (filter_id == PropertyId::BackdropFilter);
@@ -237,7 +237,7 @@ void ElementDecoration::RenderDecorators(RenderStage render_stage)
 
 		// Find the region being affected by the active filters and apply it as a scissor.
 		Rectanglef filter_region = Rectanglef::MakeInvalid();
-		ElementUtilities::GetBoundingBox(filter_region, element, BoxArea::Auto);
+		ElementUtilities::GetBoundingBox(filter_region, element, force_clip_to_self_border_box ? BoxArea::Border : BoxArea::Auto);
 
 		// The filter property may draw outside our normal clipping region due to ink overflow.
 		if (filter_id == PropertyId::Filter)
@@ -249,7 +249,7 @@ void ElementDecoration::RenderDecorators(RenderStage render_stage)
 		Math::ExpandToPixelGrid(filter_region);
 
 		Rectanglei scissor_region = Rectanglei(filter_region);
-		scissor_region.IntersectIfValid(initial_scissor_region);
+		scissor_region.IntersectIfValid(render_manager.GetState().scissor_region);
 		render_manager.SetScissorRegion(scissor_region);
 	};
 

+ 2 - 2
Source/Core/ElementUtilities.cpp

@@ -290,8 +290,8 @@ bool ElementUtilities::GetBoundingBox(Rectanglef& out_rectangle, Element* elemen
 	Vector2f shadow_extent_top_left, shadow_extent_bottom_right;
 	if (box_area == BoxArea::Auto)
 	{
-		// 'Auto' acts like border box extended to encompass any ink overflow, which includes the element's box-shadow.
-		// TODO: Include ink overflow due to filters (e.g. blur or drop-shadow).
+		// 'Auto' acts like border box extended to encompass any ink overflow, including the element's box-shadow.
+		// Note: Does not currently include ink overflow due to filters, as that is handled manually in ElementDecoration.
 		box_area = BoxArea::Border;
 
 		if (const Property* p_box_shadow = element->GetLocalProperty(PropertyId::BoxShadow))

+ 44 - 0
Tests/Data/VisualTests/filter_backdrop_filter_box_shadow.rml

@@ -0,0 +1,44 @@
+<rml>
+<head>
+	<title>Filter, backdrop filter, and box shadow combinations</title>
+	<link type="text/rcss" href="../style.rcss"/>
+	<meta name="Description" content="Test various combinations of filter, backdrop-filter, and box-shadow effects." />
+	<style>
+		body { width: 900dp; }
+		.box {
+			width: 200dp;
+			height: 70dp;
+			border: 2dp #777;
+			margin: 120dp auto;
+			padding: 15dp;
+			border-radius: 30dp 8dp;
+			box-sizing: border-box;
+		}
+		.filter {
+			filter: drop-shadow(#fe3f 250dp 50dp 0px);
+		}
+		.backdrop {
+			backdrop-filter: invert(100%);
+		}
+		.boxshadow {
+			box-shadow: #f008  40px  30px 0px 0px, #00f8 -40px -30px 0px 0px;
+		}
+	</style>
+</head>
+
+<body>
+<div class="box boxshadow filter backdrop"></div>
+<div class="box boxshadow filter"></div>
+
+<div class="box boxshadow backdrop"></div>
+<div class="box boxshadow"></div>
+
+<div class="box backdrop filter"></div>
+<div class="box filter"></div>
+
+<div class="box backdrop"></div>
+<div class="box"></div>
+
+<handle size_target="#document"/>
+</body>
+</rml>