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 uprect::intersection can fail due to floating point precision #306
Comments
|
Dupe of #177 |
|
I tried working around it, and we just hit the exact same issue within webrender::image::tiles. Floats are a pain. |
|
So I had a look at Gecko's rect implementation and tried to rewrite euclid's the same way: if !self.intersects(other) {
return None;
}
let x = max(self.min_x(), other.min_x());
let y = max(self.min_y(), other.min_y());
let w = min(
self.min_x() - x + self.size.width,
other.min_x() - x + other.size.width,
);
let h = min(
self.min_y() - y + self.size.height,
other.min_y() - y + other.size.height,
);
Some(rect(x, y, w, h))The idea of having the exact same precision behavior as gecko is very appealing and it does address this particular test case, but gecko's implementation appears to rely on the number representation being signed. With this implementation |
Yeah that might be enough of a motivation to add the endpoint representation and move some of webrender's code over to it. |
|
I tried the same thing! The gecko expression is ordered weirdly, but you can write it more sanely as self.max_x() - x, and that avoids the underflow. The effective difference is that current code is doing min() on the bottom-right points, and then converting the result to width/height. The gecko version computes the two lengths, and does min() on that. |
Fixes for tiled blobs This switches TileOffset to u32 (since gecko reftests have cases that overflow a u16 offset), and fixes the floating point precision issues outlined in servo/euclid#306 <!-- 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/3237) <!-- Reviewable:end -->
|
I went back to this and tried a few permutations. Even writing
Btw we are currently converting the rect into a box and doing the intersection in the endpoints form instead of the origin+size form of when this issue filed (the test case is still failing). In my opinion the better solution is to avoid using |
I have a testcase with tiling where we're calling rect::intersection with the following rects:
{20, 280.399994, 200, 256}
{20, 280.399994, 200, 256.000031}
The result ends up returning a width of 256.000031, not 256.