After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 649513 - St: clamp border-radius properly
St: clamp border-radius properly
Status: RESOLVED FIXED
Product: gnome-shell
Classification: Core
Component: general
unspecified
Other All
: Normal normal
: ---
Assigned To: gnome-shell-maint
gnome-shell-maint
: 651310 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2011-05-05 20:57 UTC by Jasper St. Pierre (not reading bugmail)
Modified: 2011-07-10 00:14 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
St: clamp border-radius to an actor's halfsizes (9.49 KB, patch)
2011-05-05 20:57 UTC, Jasper St. Pierre (not reading bugmail)
reviewed Details | Review
tests: Add tests for border-radius clamping (1.04 KB, patch)
2011-05-06 00:09 UTC, Jasper St. Pierre (not reading bugmail)
needs-work Details | Review
St: clamp border-radius to an actor's halfsizes (11.72 KB, patch)
2011-05-12 06:01 UTC, Jasper St. Pierre (not reading bugmail)
needs-work Details | Review
tests: Add tests for border-radius clamping (2.43 KB, patch)
2011-05-12 06:01 UTC, Jasper St. Pierre (not reading bugmail)
none Details | Review
debugging (4.37 KB, patch)
2011-05-12 06:25 UTC, Jasper St. Pierre (not reading bugmail)
rejected Details | Review
St: clamp border-radius properly (11.72 KB, patch)
2011-05-16 23:35 UTC, Jasper St. Pierre (not reading bugmail)
needs-work Details | Review
St: Take the cairo fallback for overlapping corners. (2.59 KB, patch)
2011-05-16 23:36 UTC, Jasper St. Pierre (not reading bugmail)
none Details | Review
tests: Add tests for border-radius clamping (2.43 KB, patch)
2011-05-16 23:36 UTC, Jasper St. Pierre (not reading bugmail)
needs-work Details | Review
St: Take the cairo fallback for overlapping corners. (2.67 KB, patch)
2011-05-17 22:28 UTC, Jasper St. Pierre (not reading bugmail)
reviewed Details | Review
St: Implement CSS3 specification for reducing border-radius (11.89 KB, patch)
2011-07-06 21:20 UTC, Jasper St. Pierre (not reading bugmail)
reviewed Details | Review
St: Take the cairo fallback for complex corners (2.93 KB, patch)
2011-07-06 21:22 UTC, Jasper St. Pierre (not reading bugmail)
reviewed Details | Review
St: Implement CSS3 specification for reducing border-radius (11.89 KB, patch)
2011-07-09 09:05 UTC, Jasper St. Pierre (not reading bugmail)
committed Details | Review
St: Take the cairo fallback for large corners (3.08 KB, patch)
2011-07-09 09:06 UTC, Jasper St. Pierre (not reading bugmail)
committed Details | Review
tests: Add tests for border-radius clamping (2.16 KB, patch)
2011-07-09 09:06 UTC, Jasper St. Pierre (not reading bugmail)
reviewed Details | Review
tests: Add tests for large rounded corners (1.03 KB, patch)
2011-07-09 23:23 UTC, Jasper St. Pierre (not reading bugmail)
committed Details | Review

Description Jasper St. Pierre (not reading bugmail) 2011-05-05 20:57:52 UTC
We didn't clamp border-radius to halfwidth or halfheight before, so having a
big border-radius combined with a small-sized actor gave extremely incorrect
rendering.
Comment 1 Jasper St. Pierre (not reading bugmail) 2011-05-05 20:57:55 UTC
Created attachment 187323 [details] [review]
St: clamp border-radius to an actor's halfsizes
Comment 2 Jasper St. Pierre (not reading bugmail) 2011-05-06 00:09:24 UTC
Created attachment 187332 [details] [review]
tests: Add tests for border-radius clamping
Comment 3 Florian Müllner 2011-05-12 01:11:29 UTC
Review of attachment 187323 [details] [review]:

Code looks good except for some style nitpicks. The approach is pretty simple and looks OK, but nevertheless I wonder if it's worth sticking to the standard[0] here instead.

[0]http://www.w3.org/TR/css3-background/#corner-overlap

::: src/st/st-theme-node-drawing.c
@@ +308,3 @@
   cache = st_texture_cache_get_default ();
 
+  int max_radius = MIN (node->alloc_width, node->alloc_height)/2;

Variables must be declared at the start of a block. Missing spaces around '/'.

@@ +946,3 @@
   get_arbitrary_border_color (node, &border_color);
 
+  int max_radius = MIN (node->alloc_width, node->alloc_height)/2;

Dto.

@@ +1483,3 @@
                                               &border_width_1, &border_width_2);
 
+      border_radius[corner_id] = MIN (node->border_radius[corner_id], MIN (width, height)/2);

Missing spaces around '/'.
Comment 4 Florian Müllner 2011-05-12 01:11:46 UTC
Review of attachment 187332 [details] [review]:

Looks like you didn't test your test case ...

::: tests/interactive/border-radius.js
@@ +53,3 @@
 
+// radius clamping
+box.add(new St.Label({ text: "20px",

text should be "999px;" - that's the border-radius used (and the actual point of the test case)

@@ +54,3 @@
+// radius clamping
+box.add(new St.Label({ text: "20px",
+                       style: 'width: 20px; height: 20px;'

That's too small for the text - you don't need to set any width/height (but padding would do good). In fact, you should probably just use
addTestCase("999px", false);

@@ +57,3 @@
+                              + ' border-radius: 999px;'
+                              + ' background-color: red; ',
+                       x_fill: false }));

That is wrong - St.Label does not have a x_fill property. The intention is probably to pass it as 2nd parameter to box.add(), but you messed up the braces/parentheses (again: just use addTestCase ;-)
Comment 5 Jasper St. Pierre (not reading bugmail) 2011-05-12 06:01:45 UTC
Created attachment 187674 [details] [review]
St: clamp border-radius to an actor's halfsizes

We didn't clamp border-radius to halfwidth or halfheight before, so having a
big border-radius combined with a small-sized actor gave extremely incorrect
rendering.
Comment 6 Jasper St. Pierre (not reading bugmail) 2011-05-12 06:01:49 UTC
Created attachment 187675 [details] [review]
tests: Add tests for border-radius clamping
Comment 7 Jasper St. Pierre (not reading bugmail) 2011-05-12 06:10:51 UTC
Review of attachment 187674 [details] [review]:

this is a WIP... run the tests and you'll see why.
Comment 8 Jasper St. Pierre (not reading bugmail) 2011-05-12 06:25:40 UTC
Created attachment 187676 [details] [review]
debugging
Comment 9 Jasper St. Pierre (not reading bugmail) 2011-05-12 06:27:24 UTC
Review of attachment 187676 [details] [review]:

This is just some simple debugging to help me diagnose the problem... not meant to go into the tree
Comment 10 Jasper St. Pierre (not reading bugmail) 2011-05-16 23:35:50 UTC
Created attachment 187939 [details] [review]
St: clamp border-radius properly

Welp, OK. Answer for why the rendering errors happened? When the corners
went beyond the halfsizes, the corners overlapped, so the assumption that we
could lay down each corner, in no order, individually was wrong...

So, we can either take the cairo path and implement CSS3 properly,
or just clamp to the halfsizes.

Additionally, I made an HTML testcase to help me out for what correct renderings
should look like. It might help you guys as well:

  http://magcius.mecheye.net/shell/border-radius.html
Comment 11 Jasper St. Pierre (not reading bugmail) 2011-05-16 23:36:05 UTC
Created attachment 187940 [details] [review]
St: Take the cairo fallback for overlapping corners.

The cogl path makes the assumption that we don't have overlapping
corners. It'd be extremely complicated to fix this assumption, so
just take the slow path.
Comment 12 Jasper St. Pierre (not reading bugmail) 2011-05-16 23:36:16 UTC
Created attachment 187941 [details] [review]
tests: Add tests for border-radius clamping
Comment 13 Jasper St. Pierre (not reading bugmail) 2011-05-17 22:28:35 UTC
Created attachment 187998 [details] [review]
St: Take the cairo fallback for overlapping corners.

The cogl path makes the assumption that we don't have overlapping
corners. It'd be extremely complicated to fix this assumption, so
just take the slow path.



Florian mentioned on IRC that I wasn't taking the reduced borders into account
when determining whether to take the slow path. Fixed.
Comment 14 Jasper St. Pierre (not reading bugmail) 2011-05-28 07:31:18 UTC
*** Bug 651310 has been marked as a duplicate of this bug. ***
Comment 15 Florian Müllner 2011-07-06 19:55:16 UTC
Review of attachment 187939 [details] [review]:

The code looks good except for some nitpicks, but the commit message is lying - "clamping" is what you did in a previous patch, but now the standard's behavior of scaling the radii proportionally to fit the allocation is implemented.

::: src/st/st-theme-node-drawing.c
@@ +259,3 @@
 
+/**
+ * st_theme_node_reduce_border_radius:

g-ir-scanner can probably deal with it, but I'd still use normal /* */ comments for non-public methods.

@@ +270,3 @@
+                                    guint        *corners)
+{
+  gfloat min;

"min" is a bit of a misnomer for a scaling factor - I don't think it needs to be overly specific, just calling it "scale" should be clearer.

@@ +1003,2 @@
   for (i = 0; i < 4; i++)
     {

Style nit - the brackets can be removed now (not a biggie, so feel free to ignore)
Comment 16 Florian Müllner 2011-07-06 19:56:17 UTC
Review of attachment 187941 [details] [review]:

I'd go with much simpler test cases and merge the patch with the main one.

::: tests/interactive/border-radius.js
@@ +24,3 @@
 scroll.add_actor(box);
 
+function addTestCase(radii, useGradient, size) {

I don't think the additional parameter is helpful. In theory, it can be used to confirm that
  border-radius: 200px;
  width: 400px;
  height: 400px;
does not trigger scaling of the radius, but as our test cases are purely visual, there's no way to tell that the radius does not end up at 199px anyway.

@@ +60,3 @@
 addTestCase("15px  0px  5px 10px", true);
 
+// radius clamping

"clamping" is wrong (see previous review)

@@ +64,3 @@
+addTestCase("200px 200px 0px 200px",   false, "400px");
+addTestCase("100px 200px 400px 800px", false, "400px");
+addTestCase("800px 400px 200px 100px", false, "400px");

It's not really obvious why those test cases are separate - I'd just add 2-3 cases to each the filled and gradient cases above, e.g.

addTestCase("999px", false);
addTestCase("100px 200px 400px 800px", false);

@@ +73,3 @@
+// no borders
+addTestCase("0px 0px 0px 0px", false, "500px");
+addTestCase("0px 0px 0px 0px", true,  "500px");

What is this testing?
Comment 17 Florian Müllner 2011-07-06 19:56:28 UTC
Review of attachment 187998 [details] [review]:

Looks good, except for a variable misnomer.

::: src/st/st-theme-node-drawing.c
@@ +1333,3 @@
   gboolean has_border_radius;
   gboolean has_inset_box_shadow;
+  gboolean has_complex_border;

Confusing variable name - how about "has_overlapping_corners"?
Comment 18 Jasper St. Pierre (not reading bugmail) 2011-07-06 21:20:04 UTC
Created attachment 191425 [details] [review]
St: Implement CSS3 specification for reducing border-radius

Currently, any cases of overlapping corners were just ignored and rendered incorrectly.
Implement the corner overlap algorithm as specified by the W3C to fix this.



OK
Comment 19 Jasper St. Pierre (not reading bugmail) 2011-07-06 21:22:18 UTC
Created attachment 191426 [details] [review]
St: Take the cairo fallback for complex corners

The cogl path makes the assumption that we don't have complex corners,
which is when a corner texture is bigger than the actor's half-size.

It'd be extremely complicated to fix this assumption, so just take
the slow path for now.



"overlapping corners" is bad too. When we reduce, we lose all overlapping corners.

This is for when we have corners that are past halfsizes: the cogl code is just
incorrect in this regard. So I'm calling it "complex corners", and put in a comment
explaining it.
Comment 20 Jasper St. Pierre (not reading bugmail) 2011-07-06 21:32:18 UTC
(In reply to comment #16)
> Review of attachment 187941 [details] [review]:
> 
> I'd go with much simpler test cases and merge the patch with the main one.

I guess so. This was my main tester when working on the patches, so it contains tests for a bunch of edge cases I was seeing.

> ::: tests/interactive/border-radius.js
> @@ +24,3 @@
>  scroll.add_actor(box);
> 
> +function addTestCase(radii, useGradient, size) {
> 
> I don't think the additional parameter is helpful. In theory, it can be used to
> confirm that
>   border-radius: 200px;
>   width: 400px;
>   height: 400px;
> does not trigger scaling of the radius, but as our test cases are purely
> visual, there's no way to tell that the radius does not end up at 199px anyway.

I simply wanted to test "what happens if this is larger/smaller than the halfsizes"

> @@ +60,3 @@
>  addTestCase("15px  0px  5px 10px", true);
> 
> +// radius clamping
> 
> "clamping" is wrong (see previous review)
> 
> @@ +64,3 @@
> +addTestCase("200px 200px 0px 200px",   false, "400px");
> +addTestCase("100px 200px 400px 800px", false, "400px");
> +addTestCase("800px 400px 200px 100px", false, "400px");

> It's not really obvious why those test cases are separate - I'd just add 2-3
> cases to each the filled and gradient cases above, e.g.

Rendering errors:

  http://magcius.mecheye.net/shell/border-radius.png
  http://magcius.mecheye.net/shell/border-radius-2.png
  http://magcius.mecheye.net/shell/border-radius-3.png

> addTestCase("999px", false);
> addTestCase("100px 200px 400px 800px", false);
> 
> @@ +73,3 @@
> +// no borders
> +addTestCase("0px 0px 0px 0px", false, "500px");
> +addTestCase("0px 0px 0px 0px", true,  "500px");
> 
> What is this testing?

I had an accident where this happened:

  http://magcius.mecheye.net/shell/shell-round-corners.png
Comment 21 Florian Müllner 2011-07-06 21:43:25 UTC
(In reply to comment #19)
> "overlapping corners" is bad too. When we reduce, we lose all overlapping
> corners.
> 
> This is for when we have corners that are past halfsizes: the cogl code is just
> incorrect in this regard. So I'm calling it "complex corners", and put in a
> comment
> explaining it.

I'm not particularly fond of "overlapping", but "complex" is really confusing - it implies that the corners are somehow constructed differently than "non-complex" corners, which simply isn't true. The only thing special about them is that they break the assumption of the padding code (resulting in overlapping corner areas, which is where my suggestion comes from).

Maybe "large corner" is better?
Comment 22 Florian Müllner 2011-07-06 21:46:25 UTC
Review of attachment 191425 [details] [review]:

Looks good.
Comment 23 Florian Müllner 2011-07-06 21:47:09 UTC
Review of attachment 191425 [details] [review]:

Looks good.

(edit: Didn't you plan to merge the test cases?)
Comment 24 Florian Müllner 2011-07-06 22:11:05 UTC
Review of attachment 191426 [details] [review]:

Not quite.

::: src/st/st-theme-node-drawing.c
@@ +1372,3 @@
+   * halfsize of the actor. The cogl code doesn't support these
+   * cases, so for now, set a flag to fall us back to cairo. */
+  has_complex_corners = FALSE;

Sorry, but I don't think the comment is very clear without the context of this bug. As mentioned in a previous comment, I'd suggest "large corners" if you don't like "overlap". Then a comment along the lines of

/* The cogl code pads each corner to the maximum border radius,
   which results in overlapping corner areas if the radius
   exceeds the actor's halfsize. Set a flag to fall back to
   cairo in these cases. */

should be clear enough.
Comment 25 Florian Müllner 2011-07-06 22:26:59 UTC
(In reply to comment #20)
> I simply wanted to test "what happens if this is larger/smaller than the
> halfsizes"

Sure, but this doesn't make much sense without debug printfs in the code (which I assume you had when using those test cases).


> Rendering errors:
> 
>   http://magcius.mecheye.net/shell/border-radius.png
>   http://magcius.mecheye.net/shell/border-radius-2.png
>   http://magcius.mecheye.net/shell/border-radius-3.png

Those are actually good examples why the explicit size is bad - as the labels are cut off, it is impossible to see what's tested without reading the code ;-)


> > What is this testing?
> 
> I had an accident where this happened:
> 
>   http://magcius.mecheye.net/shell/shell-round-corners.png

I still don't see how this relates to a "0px border radius" border-radius test ...
Comment 26 Jasper St. Pierre (not reading bugmail) 2011-07-09 09:05:01 UTC
Created attachment 191570 [details] [review]
St: Implement CSS3 specification for reducing border-radius

Currently, any cases of overlapping corners were just ignored and rendered incorrectly.
Implement the corner overlap algorithm as specified by the W3C to fix this.



+  if (sum > 0)
+    scale = MIN (Node->alloc_height/sum, scale);

oops. I need to find that emacs keybinding that does that silly capitalization and disable it.
Comment 27 Jasper St. Pierre (not reading bugmail) 2011-07-09 09:06:15 UTC
Created attachment 191571 [details] [review]
St: Take the cairo fallback for large corners

The cogl path pads the corners out to the maximum corner radius to make the
math and painting logic easier. Unfortunately, when the radius exceeds the
actor's halfsize, the padding ends up interfering with other corners, creating
a big mess of rendering errors.

It'd be extremely complicated to fix this properly in the Cogl code,
so take the Cairo fallback.



Is this comment+commit message any better?

Overlapping is really the wrong word, because they're not overlapping at all -- that's what the corner reduction is for!

I didn't see your suggestion of "large corners" before, and yep, it fits much better.
Comment 28 Jasper St. Pierre (not reading bugmail) 2011-07-09 09:06:37 UTC
Created attachment 191572 [details] [review]
tests: Add tests for border-radius clamping

OK, I'm trying to jog my memory here, but I got nothing. Simplified tests a lot.
Comment 29 Florian Müllner 2011-07-09 12:58:45 UTC
Review of attachment 191572 [details] [review]:

I still don't get why you insist on the "size" parameter - the additional test cases basically end up as
  "border-radius: 2..."
which means that it is not clear what is tested only from running the test.

Removing it the label is informative, and assuming that the labels' heights don't end up exceeding 400px (font-size: 390px?) covers the cases just fine.

Other than that, the commit message is wrong :-)
Comment 30 Florian Müllner 2011-07-09 12:58:56 UTC
Review of attachment 191570 [details] [review]:

OK to commit with the style fixes pointed out below:

::: src/st/st-theme-node-drawing.c
@@ +280,3 @@
+
+  if (sum > 0)
+    scale = MIN (node->alloc_width/sum, scale);

Missing spaces around operator (likewise the other MIN()s)
Comment 31 Florian Müllner 2011-07-09 12:59:09 UTC
Review of attachment 191571 [details] [review]:

"creating a big mess" is a bit colloquial, but well ...
Other than that, OK to commit with the style fixes pointed out below:

::: src/st/st-theme-node-drawing.c
@@ +1383,3 @@
+    for (corner = 0; corner < 4; corner ++) {
+      if (border_radius[corner]*2 > height ||
+          border_radius[corner]*2 > width) {

Missing spaces around operator
Comment 32 Jasper St. Pierre (not reading bugmail) 2011-07-09 17:47:38 UTC
(In reply to comment #29)
> Review of attachment 191572 [details] [review]:
> 
> I still don't get why you insist on the "size" parameter - the additional test
> cases basically end up as
>   "border-radius: 2..."
> which means that it is not clear what is tested only from running the test.
> 
> Removing it the label is informative, and assuming that the labels' heights
> don't end up exceeding 400px (font-size: 390px?) covers the cases just fine.
> 
> Other than that, the commit message is wrong :-)

Because otherwise the container is sized based upon the label. All I want to do is test if there's any rendering errors. How do you suggest I do that without a constant width/height?
Comment 33 Jasper St. Pierre (not reading bugmail) 2011-07-09 20:48:01 UTC
Should I just land these without tests for now?
Comment 34 Florian Müllner 2011-07-09 21:59:04 UTC
(In reply to comment #32)
> Because otherwise the container is sized based upon the label. All I want to do
> is test if there's any rendering errors. How do you suggest I do that without a
> constant width/height?

As long as either width or height of the label is smaller than twice the radius, the reducing code path is triggered. I don't see why rendering errors in that path wouldn't show up then.
Comment 35 Florian Müllner 2011-07-09 21:59:26 UTC
(In reply to comment #33)
> Should I just land these without tests for now?

Sure.
Comment 36 Jasper St. Pierre (not reading bugmail) 2011-07-09 22:05:45 UTC
Attachment 191570 [details] pushed as ee4ae62 - St: Implement CSS3 specification for reducing border-radius
Attachment 191571 [details] pushed as 325462d - St: Take the cairo fallback for large corners
Comment 37 Jasper St. Pierre (not reading bugmail) 2011-07-09 23:23:57 UTC
Created attachment 191604 [details] [review]
tests: Add tests for large rounded corners

I was mostly afraid of depending on the size of the font, given that all we do is:

stage {
    font: 16pt serif;
}

With a special font configuriation, the tests may not be testing large corners at all!
Comment 38 Florian Müllner 2011-07-09 23:58:01 UTC
Review of attachment 191604 [details] [review]:

(In reply to comment #37)
> I was mostly afraid of depending on the size of the font, given that all we do
> is:
> 
> stage {
>     font: 16pt serif;
> }
> 
> With a special font configuriation, the tests may not be testing large corners
> at all!

Sure, but that configuration is probably special enough to render the entire system unusable :-)

(It's probably far more likely to hit a font configuration where the "normal" test cases hit the large-corner path anyway)
Comment 39 Jasper St. Pierre (not reading bugmail) 2011-07-10 00:14:45 UTC
Attachment 191604 [details] pushed as 5bc1ded - tests: Add tests for large rounded corners


OK.