Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle gradients with multiple color stops at 0.0 or 1.0 #1189

Merged
merged 1 commit into from May 17, 2017

Conversation

@eqrion
Copy link
Contributor

eqrion commented May 2, 2017

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 Reviewable

@eqrion
Copy link
Contributor Author

eqrion commented May 2, 2017

r? @kvark @glennw

This PR makes changes to GradientData so it collides with #1181 . I can rebase on that if it will be merged soon, or help rebase #1181 on this.

I hope this PR is clear, I got confused a few too many times by indices conversions and whatnot.

@Gankra
Copy link
Contributor

Gankra commented May 2, 2017

I could split my gradient changes out to a different pr?

@eqrion
Copy link
Contributor Author

eqrion commented May 2, 2017

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.

@kvark

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.

@eqrion

eqrion May 3, 2017

Author Contributor

Yes, I did something similar when I rebased.

@@ -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.

@kvark

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.

@eqrion

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.

@bors-servo
Copy link
Contributor

bors-servo commented May 2, 2017

The latest upstream changes (presumably #1191) made this pull request unmergeable. Please resolve the merge conflicts.

@eqrion eqrion force-pushed the eqrion:gradient/clamp-bounds branch from 00f1408 to e383899 May 3, 2017
@eqrion
Copy link
Contributor Author

eqrion commented May 3, 2017

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.

@Gankra

Gankra May 3, 2017

Contributor

Should this be (next_idx, cur_idx]?

This comment has been minimized.

@eqrion

eqrion May 3, 2017

Author Contributor

Yes I forgot to reverse that comment, it should be [next_idx, cur_idx)

@bors-servo
Copy link
Contributor

bors-servo commented May 3, 2017

The latest upstream changes (presumably #1181) made this pull request unmergeable. Please resolve the merge conflicts.

@eqrion eqrion force-pushed the eqrion:gradient/clamp-bounds branch from e383899 to eef3942 May 3, 2017
@eqrion
Copy link
Contributor Author

eqrion commented May 3, 2017

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.

@kvark kvark changed the title Handle gradients with multiple color stops at 0.0 or 1.0 [WIP] Handle gradients with multiple color stops at 0.0 or 1.0 May 3, 2017
@kvark
Copy link
Member

kvark commented May 3, 2017

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.
@eqrion eqrion force-pushed the eqrion:gradient/clamp-bounds branch from eef3942 to b0af541 May 4, 2017
@eqrion
Copy link
Contributor Author

eqrion commented May 4, 2017

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.

@eqrion eqrion changed the title [WIP] Handle gradients with multiple color stops at 0.0 or 1.0 Handle gradients with multiple color stops at 0.0 or 1.0 May 4, 2017
@glennw
Copy link
Member

glennw commented May 5, 2017

@rlhunt Have you run this against the Servo reftests? If not, let me know and I'll run them locally here.

@kvark
Copy link
Member

kvark commented May 5, 2017

I tried 256 (254 for the table, 2 for the border) and that fixed a few but not all

That doesn't sound good

@eqrion
Copy link
Contributor Author

eqrion commented May 5, 2017

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 tried 256 (254 for the table, 2 for the border) and that fixed a few but not all

That doesn't sound good

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.

@kvark
Copy link
Member

kvark commented May 5, 2017

@rlhunt do you see why increasing the table size could make the quality worse?

@eqrion
Copy link
Contributor Author

eqrion commented May 5, 2017

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.

@eqrion
Copy link
Contributor Author

eqrion commented May 5, 2017

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.

@pyfisch
Copy link
Contributor

pyfisch commented May 6, 2017

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 fix_gradient_stops. If this is merged please make sure this passes testcases 2, 11, 12 and 14.

@pyfisch pyfisch mentioned this pull request May 7, 2017
2 of 2 tasks complete
@glennw
Copy link
Member

glennw commented May 8, 2017

@rlhunt Is this ready for review / merge based on your comments above about running the Servo tests? Or is there more testing required based on the comment from @pyfisch above?

@eqrion
Copy link
Contributor Author

eqrion commented May 9, 2017

@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.

@eqrion
Copy link
Contributor Author

eqrion commented May 11, 2017

@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.

@glennw
Copy link
Member

glennw commented May 17, 2017

@bors-servo r+

Thanks! Sorry for the delay in reviewing this one.

@bors-servo
Copy link
Contributor

bors-servo commented May 17, 2017

📌 Commit b0af541 has been approved by glennw

@bors-servo
Copy link
Contributor

bors-servo commented May 17, 2017

Testing commit b0af541 with merge 997111a...

bors-servo added a commit that referenced this pull request May 17, 2017
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 -->
@bors-servo
Copy link
Contributor

bors-servo commented May 17, 2017

☀️ Test successful - status-travis
Approved by: glennw
Pushing 997111a to master...

@bors-servo bors-servo merged commit b0af541 into servo:master May 17, 2017
3 checks passed
3 checks passed
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
homu Test successful
Details
@eqrion eqrion deleted the eqrion:gradient/clamp-bounds branch May 17, 2017
pyfisch added a commit to pyfisch/servo that referenced this pull request Feb 12, 2018
pyfisch added a commit to pyfisch/servo that referenced this pull request Feb 15, 2018
pyfisch added a commit to pyfisch/servo that referenced this pull request Feb 24, 2018
nupurbaghel added a commit to paavininanda/servo that referenced this pull request Mar 14, 2018
pandusonu2 added a commit to pandusonu2/servo that referenced this pull request Mar 15, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

6 participants
You can’t perform that action at this time.