mikke89 / RmlUi

RmlUi - The HTML/CSS User Interface library evolved
https://mikke89.github.io/RmlUiDoc/
MIT License
2.75k stars 302 forks source link

border-radius property #115

Closed rokups closed 4 years ago

rokups commented 4 years ago

Add that to wishlist. If we had border-radius then we could create decent-looking UIs with pure rcss.

mikke89 commented 4 years ago

Yeah, I've been thinking about this feature myself. Might look into it some time :)

viciious commented 4 years ago

The only solution to this that I see right now is to construct svg "files" in memory and render them to bitmaps using some kind of library such as nanosvg. Then draw them in corner tiles using 9-patch decorator or something.

mikke89 commented 4 years ago

Alright, I made an effort at implementing this. Let me know if there are any problems :)

I'm also considering adding support for angled corners (as suggested by @C-Core), although then we also better support two-axis radii. We'll see.

image

rokups commented 4 years ago

I started testing border-radius. So far i noticed this: image Bottom corners look almost right, but top ones are totally weird.


body
{
    font: Delicious;
    font-weight: normal;
    font-style: normal;
    color: white;
    display: inline-block;
    overflow: hidden;
}

#window
{
    font-size: 16dp;
    background-color: #1c2b32;
    padding: 4dp;
    min-width: 100dp;
    min-height: 100dp;
    border-radius: 5dp;
}

#titlebar
{
    text-align: left;
    margin: -0.4rem;
    padding: 0.4rem 0.8rem 0.4rem 0.8rem;
    border-bottom: 0.1rem #2b3939;
    /* border: 1px green; */
}

#content
{
    width: auto;
    overflow: hidden auto;
    /* border: 1px red; */
}
mikke89 commented 4 years ago

Looks like you have anti-aliasing disabled. Without that the renderer can't really do much better than your screenshot there. Try enabling it first.

We may also want to tune the number of points generated. You can try playing with/increasing GeometryBackgroundBorder::GetNumPoints() to see if you get better results (it still won't help much without AA enabled). Let me know how it goes :)

Oh, and I also fixed an issue in 371fa73401b167438c1dcce1ddf404897822ce17, so make sure you have updated to that first.

rokups commented 4 years ago

I think we can do something. I mean Dear ImGui handles AA somehow even though renderers do not have it enabled. We could get some ideas from there. I will ask around and post more details once i know them.

rokups commented 4 years ago

Omar said this:

We’re rendering AA fringe triangles on the edge of every polygons

Looks like this is implemented here: https://github.com/ocornut/imgui/blob/7b0570d6bac96ed64d379d240907f8fee319d57b/imgui_draw.cpp#L667-L814

mikke89 commented 4 years ago

It's a big undertaking to do AA on the library side. Not to mention it won't work as well as hardware AA once you apply transforms to your objects.

I'd consider taking a pull request to add optional support for it. In the meantime I suggest to use hardware AA if you can, especially if you are using transforms or border-radius.

rokups commented 4 years ago

Something is still off. Check this out: image Note how roundings at the top of elements (buttons, checkbox) look inconsistent. Radio button with border-radius: 0.5em looks anything but round. Note all elements use same rounding for all corners.

I noticed that when i tweak margin of h3 stylesheet (rml.rcss) and it causes entire layout to shift vertically - with some margins rounding looks more proper than with the others. Could this be some rounding error in rounded corner geometry generation somewhere?

My rml and rcss: Data.zip

Edit: enabling multisampling does improve rendering at the expense of edges looking blurred. One pixel borders now span two pixels. Clamping element position to pixel grid sounds like would be a rather cheap solution to considerably improve rendering both of rounded corners and of elements in general.

mikke89 commented 4 years ago

Yeah, I suspect the issue is fractional pixel values for size and position, resulting in inconsistent rendering of off-pixel vertices (which is most prominent with AA off).

This is actually a more complicated problem than one might think, see eg. this article. Just rounding the pixel values to integers - at least during layouting - will create very jarring results in several situations, since the position of nested elements can "jump" many pixels around when eg. resizing the window by even a single pixel.

We could/should at least round the values for rendering backgrounds and borders, despite that it will break some of the constraints that David Baron mentions in the above article. As far as I understand, web browsers these days use fixed-point arithmetic for layouting, which is something we might consider as well. See this related webkit document. Doing this really well requires a lot more work than one might think.

rokups commented 4 years ago

will create very jarring results in several situations, since the position of nested elements can "jump" many pixels around when eg. resizing the window by even a single pixel.

I spent a good deal of time working on HDPI support for Dear ImGui, exploring various approaches. Maybe some of those insights would be useful:

  1. we had "very jarring results" after applying fractional scale to element positions/sizes, due to imgui flooring coordinates through entire codebase. This resulted in inconsistently shifting widget sizes during drag/resize operations. Solution - use rounding instead.
  2. a less complicated solution to the problem is to just keep flooring all the things while never having fractional sizes anywhere. this would mean that rcss style would have to floor it's dp values.

I suppose 2. is basically what you meant by "fixed-point arithmetic"?

mikke89 commented 4 years ago

We used to do rounding during layouting before, but that resulted in this jarring behavior. Then we moved to doing rounding before rendering instead. I think I just forgot to add it to the new border/background rendering.

With fixed-point arithmetic I mean using integers with a fixed number of decimal digits per pixel, eg. in chromium they use 1/64th the size of a pixel, see the second link in my previous post.

See https://github.com/mikke89/RmlUi/commit/afb141eae88419d24a3a6f81532dcd413a85c393, which should make borders and backgrounds sharp, at the cost of possible 1px gaps or overlapping borders for adjacent elements.

mikke89 commented 4 years ago

Alright, I consider the border-radius implementation done.

We can open a new issue if we want to further discuss rounding of values during layouting and rendering.

I experimented a bit with angled corners. I was hoping it would be as easy as only adjusting the vertex count to two vertices for each corner, and I added some option for custom angles of the corners, but of course it is never that easy. Borders were uneven, several edge cases needed to be solved, and it frankly just didn't look that good. So I dropped working more on it. For now, decorators are the way to go for this style.