gpu: Change get_opaque() implementation of containers

We want to be able to express opaque grids. This means that the app
provides either a row of columns of opaque nodes or a column of rows,
and then the containers will magically figure it out.

The main use case for this is terminals, which are uilt using cells. And
when there's a transparent background configured but the contents are
opaque, it'd be nice if we could figure that out.

Also remove the 80% requirement. It is rather arbitrary and while it
helps for some cases, the aforementioned grid would suffer.
This commit is contained in:
Benjamin Otte 2024-07-08 10:19:45 +02:00
parent e02de45537
commit 329dc9e0cf
12 changed files with 202 additions and 18 deletions

View File

@ -85,6 +85,81 @@ gsk_rect_intersection (const graphene_rect_t *r1,
}
}
/**
* gsk_rect_coverage:
* @r1: a valid rectangle
* @r2: another valid rectangle
* @res: The result, may be one of r1/r2
*
* Computes the largest rectangle that is fully covered by
* r1 and r2.
*
* Note that this is different from a union, which is the smallest
* rectangle that covers the rectangles.
*
* The use case for this function is joining opaque rectangles.
**/
static inline void
gsk_rect_coverage (const graphene_rect_t *r1,
const graphene_rect_t *r2,
graphene_rect_t *res)
{
float x1min, y1min, x2min, y2min;
float x1max, y1max, x2max, y2max;
float size, size2;
graphene_rect_t r;
/* Assumes both rects are already normalized, as they usually are */
size = r1->size.width * r1->size.height;
size2 = r2->size.width * r2->size.height;
if (size >= size2)
{
r = *r1;
}
else
{
r = *r2;
size = size2;
}
x1min = MIN (r1->origin.x, r2->origin.x);
y1min = MIN (r1->origin.y, r2->origin.y);
x1max = MAX (r1->origin.x, r2->origin.x);
y1max = MAX (r1->origin.y, r2->origin.y);
x2min = MIN (r1->origin.x + r1->size.width, r2->origin.x + r2->size.width);
y2min = MIN (r1->origin.y + r1->size.height, r2->origin.y + r2->size.height);
x2max = MAX (r1->origin.x + r1->size.width, r2->origin.x + r2->size.width);
y2max = MAX (r1->origin.y + r1->size.height, r2->origin.y + r2->size.height);
if (x2min >= x1max)
{
float w, h;
w = x2min - x1max;
h = y2max - y1min;
size2 = w * h;
if (size2 > size)
{
r = GRAPHENE_RECT_INIT (x1max, y1min, w, h);
size = size2;
}
}
if (y2min >= y1max)
{
float w, h;
w = x2max - x1min;
h = y2min - y1max;
size2 = w * h;
if (size2 > size)
{
r = GRAPHENE_RECT_INIT (x1min, y1max, w, h);
size = size2;
}
}
*res = r;
}
static inline gboolean G_GNUC_PURE
gsk_rect_is_empty (const graphene_rect_t *rect)
{

View File

@ -3315,7 +3315,6 @@ gsk_container_node_get_opaque_rect (GskRenderNode *node,
{
GskContainerNode *self = (GskContainerNode *) node;
graphene_rect_t child_opaque;
double size, child_size, desired_size;
guint i;
for (i = 0; i < self->n_children; i++)
@ -3327,28 +3326,12 @@ gsk_container_node_get_opaque_rect (GskRenderNode *node,
if (i == self->n_children)
return FALSE;
size = opaque->size.width * opaque->size.height;
/* the 80% is random. I just want it to be low enough to catch
* rounded corners, but not so small it catches on to .view
* backgrounds for the smaller child of a paned.
*/
desired_size = node->bounds.size.width * node->bounds.size.height * 0.8;
for (i++; i < self->n_children; i++)
{
if (size >= desired_size)
break;
if (!gsk_render_node_get_opaque_rect (self->children[i], &child_opaque))
continue;
child_size = child_opaque.size.width * child_opaque.size.height;
/* We allow == here because we want to find the topmost opaque child */
if (child_size < size)
continue;
*opaque = child_opaque;
size = child_size;
gsk_rect_coverage (opaque, &child_opaque, opaque);
}
return TRUE;

View File

@ -0,0 +1,26 @@
/* the covered node */
color {
bounds: 30 30 40 40;
color: black;
}
container {
color {
bounds: 0 0 50 50;
color: lime;
}
color {
bounds: 50 0 50 50;
color: red;
}
}
container {
color {
bounds: 0 50 50 50;
color: blue;
}
color {
bounds: 50 50 50 50;
color: yellow;
}
}

View File

@ -0,0 +1,12 @@
color {
bounds: 0 0 25 50;
}
color {
bounds: 25 0 25 50;
}
color {
bounds: 50 0 25 50;
}
color {
bounds: 75 0 25 50;
}

View File

@ -0,0 +1,12 @@
color {
bounds: 75 0 25 50;
}
color {
bounds: 50 0 25 50;
}
color {
bounds: 25 0 25 50;
}
color {
bounds: 0 0 25 50;
}

View File

@ -0,0 +1,12 @@
color {
bounds: 75 0 50 50;
}
color {
bounds: 50 0 50 50;
}
color {
bounds: 25 0 50 50;
}
color {
bounds: 0 0 50 50;
}

View File

@ -0,0 +1,12 @@
color {
bounds: 0 0 50 50;
}
color {
bounds: 25 0 50 50;
}
color {
bounds: 50 0 50 50;
}
color {
bounds: 75 0 50 50;
}

View File

@ -0,0 +1,8 @@
color {
bounds: 0 0 50 50;
color: lime;
}
color {
bounds: 40 10 50 50;
color: red;
}

View File

@ -0,0 +1,12 @@
color {
bounds: 0 0 50 25;
}
color {
bounds: 0 25 50 25;
}
color {
bounds: 0 50 50 25;
}
color {
bounds: 0 75 50 25;
}

View File

@ -0,0 +1,12 @@
color {
bounds: 0 75 50 25;
}
color {
bounds: 0 50 50 25;
}
color {
bounds: 0 25 50 25;
}
color {
bounds: 0 0 50 25;
}

View File

@ -0,0 +1,12 @@
color {
bounds: 0 0 50 50;
}
color {
bounds: 0 25 50 50;
}
color {
bounds: 0 50 50 50;
}
color {
bounds: 0 75 50 50;
}

View File

@ -0,0 +1,8 @@
color {
bounds: 0 0 50 50;
color: lime;
}
color {
bounds: 10 40 50 50;
color: red;
}