slint icon indicating copy to clipboard operation
slint copied to clipboard

Improve `Rectangle`'s handling of border and clipping

Open tronical opened this issue 2 years ago • 4 comments
trafficstars

The Rectangle element has a border-width and border-colour property, as well as a clip property. How the border of a rectangle is draw in relation to the background of the Rectangle, as well as how the clipping applies in relation to the border is different between different renderers. In this issue we'd like to outline the current differences and discuss what the correct behavior should be, so that we can fix all of the renderers to produce the same output.

Suppose the following test-case:

export Demo := Window {
    width: 500px;
    height: 500px;
    first := Rectangle {
        x: 10px;
        y: 10px;
        width: 400px;
        height: 400px;
        background: #0000ff;
        border-color: #ff00006f;
        border-width: 50px;
        border-radius: 20px;
        clip: true;

        second := Rectangle {
            background: green;
            x: 200px;
            y: 200px;
        }
    }

    third := Rectangle {
        border-color: black;
        border-width: 1px;
        x: 10px;
        y: 10px;
        width: 400px;
        height: 400px;
    }
}

The first rectangle's border and clipping is what we would like to discuss. The second rectangle serves the purpose of visualising the clipping with regards to the border, and the third rectangle shows the effective external bounds of the first rectangle.

The following screenshots show the "current" state as of commit aea216fb492f9892f89fdd2764ecd98d019e6cdd:

FemtoVG: Screenshot 2022-12-14 at 15 31 09

Skia: Screenshot 2022-12-14 at 15 31 32

Qt: Screenshot 2022-12-14 at 15 31 54

Software renderer: Screenshot 2022-12-14 at 15 33 35

It's a known issue that the software renderer doesn't do rounded clipping and that the border radius has the wrong size.

The two choices we're wondering about and are seeking feedback on are:

Border and Background

FemtoVG, Skia, and Qt show a purple area, which shows that in these the background is drawn first and it extends into the area of the border.

The two possibilities that we're thinking of are

  • The background covers the entire area of the border as well, the entire border would be rendered purple.
  • The background does not overlap with the border, the entire border would be rendered red.

Border and Clipping

The green rectangle is sometimes clipped within the blue area, sometimes half-way within the border, and sometimes entirely on the outside.

Should the clip property on the rectangle clip children within the the border or within the bounds of the rectangle?

tronical avatar Dec 14 '22 14:12 tronical

It's a known issue that the software renderer [...] border radius has the wrong size.

I checked and it has the right size, looking at your screenshot in an image editor, the border radius is about 40 pixels, which is matching the 20px set with a scale factor of 2.

It is, in fact all the other renderers which are wrong as the actual radius is increased with the border size

ogoffart avatar Dec 14 '22 14:12 ogoffart

We didn't reach conclusion yet, but i think:

  • The background should extend under the border (border should be entirely purple) , this is what CSS does.

As for the clip, it all depends on whether we want to apply #110. If we want to say that the default border-width is 1px, then the clip shouldn't take the border into account. But in a sense, i think it makes more sense to take the border into account.

ogoffart avatar Jan 18 '23 08:01 ogoffart

We didn't reach conclusion yet, but i think:

  • The background should extend under the border (border should be entirely purple) , this is what CSS does.

In the light of our target audience and the principle of least surprise, I, too, think that we should pick this option. That's also what you implemented in #2078, right?

As for the clip, it all depends on whether we want to apply #110. If we want to say that the default border-width is 1px, then the clip shouldn't take the border into account. But in a sense, i think it makes more sense to take the border into account.

Another option here would be to let clip take an enum instead. So instead of clip: true; and the user wondering: "Oh, does this include the border?" it could be clip: border-box and clip: content-box - similar to CSS.

tronical avatar Jan 18 '23 08:01 tronical

Status in current master:

image

Remaining problems:

  • Femtovg seems to be almost right here (appart from the small artifact of the border "leaking" slightly some pink pixles)
  • Software renderer doesn't implement border clipping at all (tracked in #4176)
  • Skia's clip is not of the correct width
  • Same for Qt's clip, in addition, the border is rendered outside of the radius

ogoffart avatar Jun 28 '24 07:06 ogoffart