Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upHandle gradients with multiple color stops at 0.0 or 1.0 #1189
Conversation
|
I could split my gradient changes out to a different pr? |
|
If that's feasible that would work, otherwise this can wait. |
| @@ -393,6 +400,10 @@ impl GradientData { | |||
| ColorF::new(0.0, 0.0, 0.0, 0.0) | |||
| }; | |||
|
|
|||
| // Fill in the first gradient entry with the first color stop | |||
| self.fill_colors(cur_idx, cur_idx + 1, &cur_color, &cur_color); | |||
This comment has been minimized.
This comment has been minimized.
kvark
May 2, 2017
Member
this is a bit confusing. Perhaps, do fill_colors(0, 1, ...) followed by cur_idx = 1;?
This comment has been minimized.
This comment has been minimized.
| @@ -381,7 +385,10 @@ impl GradientData { | |||
| // Compute an entry index based on a gradient stop offset. | |||
| #[inline] | |||
| fn get_index(offset: f32) -> usize { | |||
| (offset.max(0.0).min(1.0) * GRADIENT_DATA_RESOLUTION as f32).round() as usize | |||
| let clamped = offset.max(0.0).min(1.0); | |||
| let scaled = clamped * (GRADIENT_DATA_LAST - GRADIENT_DATA_FIRST) as f32 + GRADIENT_DATA_FIRST as f32; | |||
This comment has been minimized.
This comment has been minimized.
kvark
May 2, 2017
Member
So this function returns indices between the GRADIENT_DATA_FIRST and GRADIENT_DATA_LAST, inclusive. It seems a little inconsistent that we have a border element to the left of FIRST (under index 0), but no border to the right of LAST.
This comment has been minimized.
This comment has been minimized.
eqrion
May 3, 2017
Author
Contributor
Yes it returns from [GRADIENT_DATA_FIRST, GRADIENT_DATA_END] but the fill_colors code will only fill from [start_idx, next_idx). So we should have a border element before GRADIENT_DATA_FIRST, and starting at GRADIENT_DATA_END. I've added some comments, and they might make things clearer. Or less clear.
|
|
|
Rebased this and added some comments around GradientData, it needed some. Whew, lots of fun exclusive and inclusive ranges. |
| self.fill_colors(GRADIENT_DATA_LAST_STOP, GRADIENT_DATA_LAST_STOP + 1, &cur_color, &cur_color); | ||
|
|
||
| // Fill in the center of the gradient table, generating a color ramp between each consecutive pair | ||
| // of gradient stops. Each iteration of a loop will fill the indices in [cur_idx, next_idx). The |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
eqrion
May 3, 2017
Author
Contributor
Yes I forgot to reverse that comment, it should be [next_idx, cur_idx)
|
|
|
I've rebased and updated the comment. I just ran the gecko reftests with this patch and noticed that there are a couple of failures fixed but some new failures. So I'd like to investigate those first now. |
|
Thanks @rlhunt ! I marked the PR as WIP for now. |
When a clamped gradient has multiple color stops at 0.0, the last one will fill GradientData[0]. When a clamped gradient has multiple color stops at 1.0, the first one will fill GradientData[N-1]. Both of these conditions will cause the area outside of the gradient to not be filled with the correct clamped color, which is the first or last gradient color stop. Filling the first or last color entry of GradientData with the first or last color stop isn't exactly correct either because the first or last color stop entry is only needed in this case for the range outside of [0, 1]. This commit changes the GradientData so that the first color entry is used for offset < 0, the last color entry is used for offset >= 1, and the color entries in between are for the range in between. The first and last color entries are then filled with the correct colors for those ranges.
|
The issue was that I took 2 of the 128 gradient data entries (leaving 126 left), and it looks like some reftests are sensitive to the resolution of the table. I tried 256 (254 for the table, 2 for the border) and that fixed a few but not all, so I've settled with doing 130 (128 for the table, 2 for the border) and that seems to work well. |
|
@rlhunt Have you run this against the Servo reftests? If not, let me know and I'll run them locally here. |
That doesn't sound good |
|
I'll run the Servo reftests now. I've tried this on the Gecko reftests and it doesn't cause any regressions and fixes a few tests.
I can confirm that without this PR, if you change the table size to be 254 from 128, these tests fail. So I suppose these tests are sensitive to the inner table of GradientData size being a power of two. |
|
@rlhunt do you see why increasing the table size could make the quality worse? |
|
Increasing the table size does actually seem to improve the quality, it's just seems to be a problem with non power of two sizes (or something else). 126 and 254 causes failures, 128 and 256 seem fine. I ran some experiments here, noticeable increasing the inner table to 1024 actually resolved a test, so quality does improve, but I think 1024 is overkill. |
|
I've successfully ran the servo wpt-tests and css-tests with this change. I think it's interesting that the inner table size is very sensitive and we should do more follow up work with it, but it's a preexisting condition unrelated to this PR. |
|
It seems like I duplicated some of the work done here on the servo side. servo/servo#16666 also contains a function to handle first and last stops and it is called |
|
@glennw This should be ready for review / merge. I haven't checked whether it passes those Servo tests, but it passes more Gecko tests without regressions so I'd prefer a followup investigation. |
|
@pyfisch I ran your test case with a Servo build with this patch applied and it seems like it passes all the test cases (except for gradients with transparency which is related to #1219). The only iffy test case is 12, where it seems that Gecko/Blink are rendering it incorrectly according to the spec and we differ with this patch. |
|
@bors-servo r+ Thanks! Sorry for the delay in reviewing this one. |
|
|
Handle gradients with multiple color stops at 0.0 or 1.0 When a clamped gradient has multiple color stops at 0.0, the last one will fill GradientData[0]. When a clamped gradient has multiple color stops at 1.0, the first one will fill GradientData[N-1]. Both of these conditions will cause the area outside of the gradient to not be filled with the correct clamped color, which is the first or last gradient color stop. Filling the first or last color entry of GradientData with the first or last color stop isn't exactly correct either because the first or last color stop entry is only needed in this case for the range outside of [0, 1]. This commit changes the GradientData so that the first color entry is used for offset < 0, the last color entry is used for offset > 1, and the color entries in between are for the range in between. The first and last color entries are then filled with the correct colors for those ranges. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1189) <!-- Reviewable:end -->
|
|
Webrender solved the issue with servo/webrender#1189.
Webrender solved the issue with servo/webrender#1189.
Webrender solved the issue with servo/webrender#1189.
Webrender solved the issue with servo/webrender#1189.
Webrender solved the issue with servo/webrender#1189.
eqrion commentedMay 2, 2017
•
edited by larsbergstrom
When a clamped gradient has multiple color stops at 0.0, the last one
will fill GradientData[0]. When a clamped gradient has multiple color
stops at 1.0, the first one will fill GradientData[N-1]. Both of these
conditions will cause the area outside of the gradient to not be filled
with the correct clamped color, which is the first or last gradient
color stop.
Filling the first or last color entry of GradientData with the first or
last color stop isn't exactly correct either because the first or last
color stop entry is only needed in this case for the range outside of
[0, 1].
This commit changes the GradientData so that the first color entry is
used for offset < 0, the last color entry is used for offset > 1, and
the color entries in between are for the range in between. The first and
last color entries are then filled with the correct colors for those
ranges.
This change is